[system] / trunk / webwork2 / lib / WeBWorK / ContentGenerator / Instructor / Preflight.pm Repository:
ViewVC logotype

Annotation of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/Preflight.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2778 - (view) (download) (as text)

1 : gage 2240 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4 : sh002i 2778 # $CVSHeader: webwork2/lib/WeBWorK/ContentGenerator/Instructor/Preflight.pm,v 1.3 2004/06/14 20:58:17 toenail Exp $
5 : gage 2240 #
6 :     # This program is free software; you can redistribute it and/or modify it under
7 :     # the terms of either: (a) the GNU General Public License as published by the
8 :     # Free Software Foundation; either version 2, or (at your option) any later
9 :     # version, or (b) the "Artistic License" which comes with this package.
10 :     #
11 :     # This program is distributed in the hope that it will be useful, but WITHOUT
12 :     # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13 :     # FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14 :     # Artistic License for more details.
15 :     ################################################################################
16 :    
17 :     package WeBWorK::ContentGenerator::Instructor::Preflight;
18 :     use base qw(WeBWorK::ContentGenerator::Instructor);
19 :    
20 :     =head1 NAME
21 :    
22 :     WeBWorK::ContentGenerator::Instructor::Preflight.pm -- display past answers of many students
23 :    
24 :     =cut
25 :    
26 :     use strict;
27 :     use warnings;
28 :     use CGI qw();
29 : toenail 2305 use WeBWorK::HTML::OptionList qw/optionList/;
30 :     use WeBWorK::HTML::ScrollingRecordList qw/scrollingRecordList/;
31 : gage 2240
32 :     sub initialize {
33 :     my $self = shift;
34 :     my $r = $self->r;
35 :     my $urlpath = $r->urlpath;
36 :     my $db = $r->db;
37 :     my $ce = $r->ce;
38 :     my $authz = $r->authz;
39 :     my $courseName = $urlpath->arg("courseID");
40 :     my $user = $r->param('user');
41 :    
42 : toenail 2305 # Check permissions
43 :     return unless ($authz->hasPermissions($user, "access_instructor_tools"));
44 : gage 2240 }
45 :    
46 :    
47 :     sub body {
48 :     my $self = shift;
49 :     my $r = $self->r;
50 :     my $urlpath = $r->urlpath;
51 :     my $db = $r->db;
52 :     my $ce = $r->ce;
53 :     my $authz = $r->authz;
54 :     my $root = $ce->{webworkURLs}->{root};
55 :     my $courseName = $urlpath->arg('courseID');
56 : toenail 2305 my $setName = $r->param('setID') || ""; # these are passed in the search args in this case
57 :     my $problemNumber = $r->param('problemID') || "";
58 :     if ($problemNumber =~ /\!(\d+)/) { $problemNumber = $1 };
59 : gage 2240 my $user = $r->param('user');
60 :     my $key = $r->param('key');
61 : toenail 2305 my $studentUser = $r->param('studentUser') || "";
62 : gage 2240
63 : toenail 2305 # Check permissions
64 :     return CGI::div({class=>"ResultsWithError"}, "You are not authorized to access the Instructor tools.")
65 :     unless $authz->hasPermissions($r->param("user"), "access_instructor_tools");
66 :    
67 : gage 2240
68 :     my $showAnswersPage = $urlpath->newFromModule($urlpath->module, courseID => $courseName);
69 :     my $showAnswersURL = $self->systemLink($showAnswersPage,authen => 0 );
70 :    
71 : toenail 2248 my ($safeUser, $safeCourse) = (showHTML($studentUser), showHTML($courseName));
72 :     my ($safeSet, $safeProb) = (showHTML($setName), showHTML($problemNumber));
73 : toenail 2305
74 :     my @defaultOrder = qw(user_id set_id problem_id date answers);
75 :    
76 :     my %prettyFieldNames;
77 : gage 2240
78 : toenail 2305 @prettyFieldNames{qw(
79 :     user_id
80 :     set_id
81 :     problem_id
82 :     date
83 :     answers
84 :     )} = (
85 :     "User ID",
86 :     "Set Name",
87 :     "Problem Number",
88 :     "Date",
89 :     "Answers",
90 :     );
91 :     $prettyFieldNames{nofield} = "";
92 :    
93 : gage 2240 #####################################################################
94 :     # print form
95 :     #####################################################################
96 :    
97 : toenail 2305 my @userIDs = grep /\w/, sort $db->listUsers();
98 :     my @Users = $db->getUsers(@userIDs);
99 :     my %users = map { $_ => $db->getUser($_)->first_name } @userIDs;
100 :     my @setIDs = sort $db->listGlobalSets();
101 :     my @GlobalSets = $db->getGlobalSets(@setIDs);
102 :     my @GlobalProblems = $db->getAllGlobalProblems($setName);
103 :    
104 :     my $scrolling_user_list = scrollingRecordList({
105 :     name => "studentUser",
106 :     request => $r,
107 :     default_sort => "lnfn",
108 :     default_format => "lnfn_uid",
109 :     default_filters => ["all"],
110 :     default => "Select one or more users: ",
111 :     # hide_sort => 1,
112 :     # hide_format => 1,
113 :     # hide_filter => 1,
114 :     size => 10,
115 :     # multiple => 0,
116 :     }, @Users);
117 :    
118 :     my $scrolling_set_list = scrollingRecordList({
119 :     name => "setID",
120 :     request => $r,
121 :     default_sort => "set_id",
122 :     default_format => "set_id",
123 :     default_filters => ["all"],
124 :     default => "Select one or more sets: ",
125 :     # hide_sort => 1,
126 :     # hide_format => 1,
127 :     # hide_filter => 1,
128 :     size => 10,
129 :     # multiple => 0,
130 :     }, @GlobalSets);
131 :    
132 :     my $scrolling_problem_list = scrollingRecordList({
133 :     name => "problemID",
134 :     request => $r,
135 :     default => "Select one or more problems: ",
136 :     default_filters => ["all"],
137 :     # hide_sort => 1,
138 :     # hide_format => 1,
139 :     # hide_filter => 1,
140 :     size => 10,
141 :     # multiple => 0,
142 :     }, @GlobalProblems);
143 :    
144 :     my @selected_fields = $r->param("selected_fields");
145 :     my @selected_answers = $r->param("selected_answers");
146 :    
147 : toenail 2248 print join ("",
148 :     CGI::br(),
149 :     "\n\n",
150 :     CGI::hr(),
151 : toenail 2305 CGI::start_form(
152 :     -method => "post",
153 :     -action => $showAnswersURL,
154 :     -target => 'information',
155 : toenail 2248 ),
156 : toenail 2305 CGI::start_table(
157 :     -border => "0",
158 :     -cellpadding => "0",
159 :     -cellspacing => "0",
160 : toenail 2248 ),
161 : toenail 2305 CGI::Tr(
162 :     CGI::td({style=>"width:33%"}, $scrolling_user_list),
163 :     CGI::td({style=>"width:33%"}, $scrolling_set_list),
164 :     CGI::td({style=>"width:33%"}, $scrolling_problem_list),
165 : toenail 2248 ),
166 : toenail 2305 CGI::Tr({},
167 :     CGI::submit(
168 :     -name => 'action',
169 :     -value => 'Past Answers for',
170 :     ), "\n",
171 :     # $self->hidden_authen_fields,
172 :     # "   \n User:  ",
173 :     # CGI::textfield(
174 :     # -name => 'studentUser1',
175 :     # -value => $safeUser,
176 :     # -size => 10,
177 :     # ),
178 :     # "   \n Set:  ",
179 :     # CGI::textfield(
180 :     # -name => 'setID1',
181 :     # -value => $safeSet,
182 :     # -size => 10,
183 :     # ),
184 :     # "   \n Problem:  ",
185 :     # CGI::textfield(
186 :     # -name => 'problemID',
187 :     # -value => $safeProb,
188 :     # -size => 10,
189 :     # ),
190 :     # "   \n",
191 :     # CGI::br(),CGI::br(),
192 : toenail 2248 ),
193 : toenail 2305 # CGI::Tr({},
194 :     # CGI::popup_menu(
195 :     # -name => 'studentUser',
196 :     # -size => 10,
197 :     # -values => \@userIDs,
198 :     # -multiple => 1,
199 :     # ),
200 :     # CGI::popup_menu(
201 :     # -name => 'setID',
202 :     # -values => \@setIDs,
203 :     # -size => 10,
204 :     # -multiple => 1,
205 :     # ),
206 :     # ),
207 :     CGI::Tr({},
208 :     CGI::td({},
209 :     "Select which fields to show: " . CGI::br(),
210 :     CGI::scrolling_list(
211 :     -name => "selected_fields",
212 :     -values => \@defaultOrder,
213 :     -labels => \%prettyFieldNames,
214 :     -default => \@selected_fields,
215 :     -size => 5,
216 :     -multiple => 1,
217 :     ),
218 :     ),
219 :     CGI::td({},
220 :     "and which answers to show: " . CGI::br(),
221 :     CGI::scrolling_list(
222 :     -name => "selected_answers",
223 :     -values => [1..100],
224 :     -default => \@selected_answers,
225 :     -size => 5,
226 :     -multiple => 1,
227 :     )
228 :     ),
229 : toenail 2248 ),
230 : toenail 2305 CGI::end_table({}),
231 :     CGI::end_form({}),
232 : toenail 2248 );
233 : toenail 2305
234 :     #####################################################################
235 :     # create ordering system
236 :     #####################################################################
237 : toenail 2248
238 : toenail 2305 # FIXME: We need a way to choose the order as well as the fields!
239 :     my (@fieldOrder) = @selected_fields ? @selected_fields : @defaultOrder;
240 :    
241 : gage 2240 if (defined($setName) and defined($problemNumber) ) {
242 :     #####################################################################
243 :     # print result table of answers
244 :     #####################################################################
245 :     my $answer_log = $self->{ce}->{courseFiles}->{logs}->{'answer_log'};
246 :    
247 :     $studentUser = $r->param('studentUser') if ( defined($r->param('studentUser')) );
248 : toenail 2248 my ($safeUser, $safeCourse) = (showHTML($studentUser), showHTML($courseName));
249 :     my ($safeSet, $safeProb) = (showHTML($setName), showHTML($problemNumber));
250 : gage 2240
251 :    
252 : toenail 2248 print CGI::h3( "Past Answers for " . ($safeUser ? "user $safeUser " : '' ) . ($safeSet ? "set $safeSet " : '' ) . ($safeSet and $safeProb ? ', ' : '') . ($safeProb ? "problem $safeProb" : ''));
253 : gage 2240
254 : toenail 2305 $studentUser = "[^|]*" if (not defined $studentUser or $studentUser eq "" or $studentUser eq "*");
255 : gage 2240 $setName = "[^|]*" if ($setName eq "" or $setName eq "*");
256 :     $problemNumber = "[^|]*" if ($problemNumber eq "" or $problemNumber eq "*");
257 : toenail 2248
258 :     #my $pattern = "^[[^]]*]|[^|]*\\|$setName\\|$problemNumber\\|";
259 :     my $pattern = "\\|$studentUser\\|$setName\\|$problemNumber\\|";
260 : gage 2240
261 : toenail 2248 our ($lastdate, $lasttime, $lastID, $lastn);
262 : gage 2240
263 :    
264 :     if (open(LOG,"$answer_log")) {
265 : toenail 2248 my $line;
266 :     local ($lastdate, $lasttime, $lastID, $lastn) = ("",0,"",0);
267 :     $self->{lastdate} = '';
268 :     $self->{lasttime} = '';
269 :     $self->{lastID} = '';
270 :     $self->{lastn} = '';
271 : gage 2240
272 : toenail 2248 # get data from file
273 :    
274 :     my @lines = grep(/$pattern/,<LOG>); close(LOG);
275 : toenail 2305 chomp(@lines);
276 :    
277 :     my $maxcount = 0;
278 :     foreach my $newline (@lines) {
279 :     my @words = split /\t/, $newline;
280 :     my $count = @words;
281 :     $maxcount = $count if $count > $maxcount;
282 :     }
283 :     @selected_answers = (1..$maxcount) unless @selected_answers;
284 :    
285 : toenail 2248 # print "<CENTER>\n";
286 :     print CGI::start_table({
287 :     -border => "1",
288 : toenail 2305 # -cellpadding => '3',
289 :     # -cellspacing => '0',
290 :     -onload => "",
291 : toenail 2248 }) . "\n";
292 :    
293 :     my @tableHeaders;
294 :     foreach (@fieldOrder) {
295 :     push @tableHeaders, $prettyFieldNames{$_} unless $_ eq "answers";
296 :     }
297 :     print CGI::Tr({}, CGI::th({}, \@tableHeaders) , CGI::th({-colspan => 200}, $prettyFieldNames{answers}));
298 :    
299 : toenail 2305 my @Records;
300 :     #####################################################################
301 :     # create array of records
302 :     #####################################################################
303 : toenail 2248 foreach $line ( @lines ) {
304 : toenail 2305 my %fakeRecord = ();
305 : toenail 2248 #print CGI::br() . $line;
306 : toenail 2305 next if not $line =~ /\|(\w+)\|([\w\d_-]+)\|(\d+)\|\s*(\d+)(.*?)\t?$/;
307 : toenail 2248 $fakeRecord{user_id} = "$1";
308 :     $fakeRecord{set_id} = "$2";
309 :     $fakeRecord{problem_id} = "$3";
310 : sh002i 2778 $fakeRecord{date} = $4; #$self->formatDateTime($4);
311 : toenail 2248 $fakeRecord{answers} = [ split "\t", "$5", -1 ] if $5; # the -1 stops split from dropping any trailing null fields
312 : toenail 2305 my @answers = map { $_ ? showHTML($_) : CGI::small(CGI::i("empty")) } @{ $fakeRecord{answers} };
313 :     shift @answers; # first field is always empty
314 :     $fakeRecord{answers} = \@answers;
315 :    
316 : toenail 2248
317 :     my @tableCells;
318 :     foreach (@fieldOrder) {
319 : toenail 2305
320 :     #push @tableCells, showHTML($fakeRecord{$_});
321 : toenail 2248 }
322 :    
323 : toenail 2305 push @Records, \%fakeRecord;
324 :    
325 :     #print join " ", map { "$_ = $fakeRecord{$_}" } keys %fakeRecord;
326 :     #print CGI::br();
327 :     # print CGI::Tr({}, CGI::td({}, \@tableCells));
328 : toenail 2248
329 :     #print $self->tableRow(split("\t",$line."\tx"));
330 :     }
331 : toenail 2305
332 :     #####################################################################
333 :     # sort array of records
334 :     #####################################################################
335 :    
336 :     @Records = sort byUSPD @Records;
337 :    
338 :     #####################################################################
339 :     # print array of records
340 :     #####################################################################
341 :    
342 :     foreach my $record (@Records) {
343 :     my @tableCells;
344 :     foreach (@fieldOrder) {
345 :     if ($_ eq "answers") {
346 :     my $i = 0;
347 :     my %answers = map { ++$i => $_ } @{ $record->{$_} };
348 :     push @tableCells, @answers{@selected_answers};
349 :     } elsif ($_ eq "date") {
350 :     my ( $sec, $min, $hour, $mday, $mon, $year, $wday, $yday, $isdst) = localtime $record->{$_};
351 :     $wday = ("Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat")[$wday];
352 :     $mon = ("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec")[$mon];
353 :     $year += 1900;
354 :     my $ampm = ("am", "pm")[$hour > 12];
355 :     $hour = $hour % 12;
356 :     push @tableCells, showHTML("$wday $mday $mon $year $hour:$min $ampm");
357 :     } else {
358 :     push @tableCells, $record->{$_};
359 :     }
360 :     }
361 :    
362 :     print CGI::Tr({}, CGI::td({}, \@tableCells));
363 :     }
364 :    
365 : toenail 2248 # print a horizontal line
366 :     #print CGI::Tr({}, CGI::td({colspan => $lastn}, CGI::hr({size => 3})));
367 :     print CGI::end_table({});
368 :     # print "\n</CENTER>\n\n";
369 :     print CGI::p(
370 :     CGI::i("No entries for " . ($safeUser ? "user $safeUser " : '' ) . ($safeSet ? "set $safeSet " : '' ) . ($safeSet and $safeProb ? ', ' : '') . ($safeProb ? "problem $safeProb" : ''))
371 :     ) unless @lines;
372 :    
373 : gage 2240 } else {
374 : toenail 2248 print CGI::em("Can't open the access log $answer_log");
375 : gage 2240 }
376 :     }
377 :    
378 :    
379 :     return "";
380 :     }
381 :    
382 :     sub tableRow {
383 : toenail 2248 my $self = shift;
384 :     my $lastID = $self->{lastID};
385 :     my $lastn = $self->{lastn};
386 :     my $lasttime = $self->{lasttime};
387 :     my $lastdate = $self->{lastdate};
388 :     my ($out,$answer,$studentUser,$set,$prob) = "";
389 :     my ($ID,$rtime,@answers) = @_; pop(@answers);
390 :     my $date = scalar(localtime($rtime)); $date =~ s/\s+/ /g;
391 :     my ($day,$month,$mdate,$time,$year) = split(" ",$date);
392 :     $date = "$mdate $month $year";
393 :     my $n = 2*(scalar(@answers)+1);
394 : gage 2240
395 : toenail 2248 if ($lastID ne $ID) {
396 :     if ($lastn) {
397 :     print qq{<TR><TD COLSPAN="$lastn"><HR SIZE="3"></TD></TR>\n<P>\n\n};
398 :     print '<TABLE BORDER="0" CELLPADDING="0" CELLSPACING="3">',"\n";
399 :     }
400 :     ($studentUser,$set,$prob) = (split('\|',$ID))[1,2,3];
401 :     $out .= qq{<TR ALIGN="CENTER"><TD COLSPAN="$n"><HR SIZE="3">
402 :     User: <B>$studentUser</B> &nbsp;
403 :     Set: <B>$set</B> &nbsp;
404 :     Problem: <B>$prob</B></TD></TR>\n};
405 :     $lastID = $ID; $lasttime = 0; $lastdate = "";
406 :     }
407 : gage 2240
408 : toenail 2248 $out .= qq{<TR><TD COLSPAN="$n"><HR SIZE="1"></TD></TR>\n}
409 :     if ($rtime - $lasttime > 30*60);
410 :     $lasttime = $rtime; $lastn = $n;
411 : gage 2240
412 : toenail 2248 if ($lastdate ne $date) {
413 :     $out .= qq{<TR><TD COLSPAN="$n"><SMALL><I>$date</I></SMALL></TD></TR>\n};
414 :     $lastdate = $date;
415 :     }
416 : gage 2240
417 : toenail 2248 $out .= '<TR><TD WIDTH="10"></TD>'.
418 :     '<TD><FONT COLOR="#808080"><SMALL>'.$time.'</SMALL></FONT></TD>';
419 :     foreach $answer (@answers) {
420 :     $answer =~ s/(^\s+|\s+$)//g;
421 :     $answer = showHTML($answer);
422 :     $answer = "<SMALL><I>empty</I></SMALL>" if ($answer eq "");
423 :     $out .= qq{<TD WIDTH="20"></TD><TD NOWRAP>$answer</TD>};
424 :     }
425 :     $out .= "</TR>\n";
426 :     $out;
427 : gage 2240 }
428 :    
429 : toenail 2305 ################################################################################
430 :     # sorts
431 :     ################################################################################
432 :    
433 :     sub byUserID { $a->{user_id} cmp $b->{user_id} }
434 :     sub bySetID { lc($a->{set_id}) cmp lc($b->{set_id}) }
435 :     sub byProblemID { $a->{problem_id} <=> $b->{problem_id} }
436 :     sub byDate { $a->{date} cmp $b->{date} }
437 :    
438 :     sub byUSPD { &byUserID || &bySetID || &byProblemID || &byDate }
439 :    
440 : gage 2240 ##################################################
441 :     #
442 :     # Make HTML symbols printable
443 :     #
444 :     sub showHTML {
445 : toenail 2248 my $string = shift;
446 : toenail 2305 return '' unless defined $string;
447 : toenail 2248 $string =~ s/&/\&amp;/g;
448 :     $string =~ s/</\&lt;/g;
449 :     $string =~ s/>/\&gt;/g;
450 :     $string =~ s/
451 :     $string =~ s/ /&nbsp;/g;
452 :     return $string;
453 : gage 2240 }
454 :    
455 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9