Annotation of loncom/interface/lonstatistics.pm, revision 1.30
1.1 albertel 1: # The LearningOnline Network with CAPA
2: # (Publication Handler
3: #
1.30 ! stredwic 4: # $Id: lonstatistics.pm,v 1.29 2002/07/22 20:35:05 stredwic 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: # (Navigate problems for statistical reports
29: # YEAR=2001
1.15 minaeibi 30: # 5/5,7/9,7/25/1,8/11,9/13,9/26,10/5,10/9,10/22,10/26 Behrouz Minaei
1.14 minaeibi 31: # 11/1,11/4,11/16,12/14,12/16,12/18,12/20,12/31 Behrouz Minaei
1.1 albertel 32: # YEAR=2002
1.18 minaeibi 33: # 1/22,2/1,2/6,2/25,3/2,3/6,3/17,3/21,3/22,3/26,4/7,5/6 Behrouz Minaei
1.28 minaeibi 34: # 5/12,5/14,5/15,5/19,5/26,7/16 Behrouz Minaei
1.14 minaeibi 35: #
1.1 albertel 36: ###
37:
1.3 minaeibi 38: package Apache::lonstatistics;
1.1 albertel 39:
1.30 ! stredwic 40: use strict;
1.1 albertel 41: use Apache::Constants qw(:common :http);
42: use Apache::lonnet();
43: use Apache::lonhomework;
1.12 minaeibi 44: use Apache::loncommon;
1.29 stredwic 45: use Apache::loncoursedata;
46: use Apache::lonhtmlcommon;
1.30 ! stredwic 47: use Apache::lonproblemanalysis;
! 48: use Apache::lonproblemstatistics;
! 49: use Apache::lonstudentassessment;
1.29 stredwic 50: use Apache::lonchart;
1.1 albertel 51: use HTML::TokeParser;
52: use GDBM_File;
53:
54: my $r;
1.25 minaeibi 55: my %color;
1.27 stredwic 56:
57: sub CheckFormElement {
58: my ($cache, $ENVName, $cacheName, $default)=@_;
59:
60: if(defined($ENV{'form.'.$ENVName})) {
61: $cache->{$cacheName} = $ENV{'form.'.$ENVName};
62: } elsif(!defined($cache->{$cacheName})) {
63: $cache->{$cacheName} = $default;
64: }
65:
66: return;
67: }
68:
69: sub ProcessFormData{
1.29 stredwic 70: my ($cache)=@_;
1.27 stredwic 71:
1.29 stredwic 72: $cache->{'reportKey'} = 'false';
1.27 stredwic 73:
1.29 stredwic 74: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.30 ! stredwic 75: ['sort','download','reportSelected',
! 76: 'StudentAssessmentStudent']);
1.29 stredwic 77: &CheckFormElement($cache, 'Status', 'Status', 'Active');
78: &CheckFormElement($cache, 'postdata', 'reportSelected', 'Class list');
79: &CheckFormElement($cache, 'reportSelected', 'reportSelected',
80: 'Class list');
1.30 ! stredwic 81: $cache->{'reportSelected'} =
! 82: &Apache::lonnet::unescape($cache->{'reportSelected'});
1.29 stredwic 83: &CheckFormElement($cache, 'DownloadAll', 'DownloadAll', 'false');
84: &CheckFormElement($cache, 'sort', 'sort', 'fullname');
85: &CheckFormElement($cache, 'download', 'download', 'false');
86:
87: if(defined($ENV{'form.CreateStudentAssessment'}) ||
88: defined($ENV{'form.NextStudent'}) ||
89: defined($ENV{'form.PreviousStudent'})) {
90: $cache->{'reportSelected'} = 'Student Assessment';
91: }
92: if(defined($ENV{'form.NextStudent'})) {
93: $cache->{'StudentAssessmentMove'} = 'next';
94: } elsif(defined($ENV{'form.PreviousStudent'})) {
95: $cache->{'StudentAssessmentMove'} = 'previous';
96: } else {
97: $cache->{'StudentAssessmentMove'} = 'selected';
98: }
99: &CheckFormElement($cache, 'StudentAssessmentMap', 'StudentAssessmentMap',
100: 'All Maps');
101: &CheckFormElement($cache, 'StudentAssessmentStudent',
1.30 ! stredwic 102: 'StudentAssessmentStudent', 'All Students');
! 103: $cache->{'StudentAssessmentStudent'} =
! 104: &Apache::lonnet::unescape($cache->{'StudentAssessmentStudent'});
1.29 stredwic 105:
106: foreach (keys(%ENV)) {
107: if(/form\.Analyze:::/) {
108: # $cache->{'reportSelected'} = 'Analyze';
109: # $cache->{'reportKey'} = 'Problem Analysis';
110: my ($uri, $title, $part, $problem);
111: (undef, $uri, $title, $part, $problem)=split(':::', $_);
112: $cache->{'AnalyzeURI'} = $uri;
113: $cache->{'AnalyzeTitle'} = $title;
114: $cache->{'AnalyzePart'} = $part;
115: $cache->{'AnalyzeProblem'} = $problem;
116:
117: &CheckFormElement($cache, 'Interval', 'Interval', '1');
1.27 stredwic 118: }
1.29 stredwic 119: }
1.27 stredwic 120:
1.29 stredwic 121: return;
1.27 stredwic 122:
1.29 stredwic 123: # Select page to display
124: if(defined($ENV{'form.ProblemStatistics'}) ||
125: defined($ENV{'form.ProblemStatisticsRecalculate'}) ||
126: defined($ENV{'form.DisplayCSVFormat'})) {
127: $cache->{'GoToPage'} = 'ProblemStatistics';
128: &CheckFormElement($cache, 'DisplayCSVFormat',
129: 'DisplayFormat', 'Display Table Format');
130: &CheckFormElement($cache, 'Ascend','ProblemStatisticsAscend',
131: 'Ascending');
132: &CheckFormElement($cache, 'Maps', 'ProblemStatisticsMap',
133: 'All Maps');
134: } elsif(defined($ENV{'form.ProblemAnalysis'})) {
135: $cache->{'GoToPage'} = 'ProblemAnalysis';
136: &CheckFormElement($cache, 'Interval', 'Interval', '1');
137: } elsif(defined($ENV{'form.DoDiffGraph'})) {
138: $cache->{'GoToPage'} = 'DoDiffGraph';
139: } elsif(defined($ENV{'form.PercentWrongGraph'})) {
140: $cache->{'GoToPage'} = 'PercentWrongGraph';
141: } elsif(defined($ENV{'form.ActivityLog'})) {
142: $cache->{'GoToPage'} = 'ActivityLog';
143: } else {
144: $cache->{'GoToPage'} = 'Menu';
145: }
1.27 stredwic 146:
1.29 stredwic 147: &CheckFormElement($cache, 'Status', 'Status', 'Active');
1.27 stredwic 148:
149: return;
150: }
151:
152: =pod
153:
154: =item &SortStudents()
155:
156: Determines which students to display and in which order. Which are
157: displayed are determined by their status(active/expired). The order
158: is determined by the sort button pressed (default to username). The
159: type of sorting is username, lastname, or section.
160:
161: =over 4
162:
163: Input: $students, $CacheData
164:
165: $students: A array pointer to a list of students (username:domain)
166:
167: $CacheData: A pointer to the hash tied to the cached data
168:
169: Output: \@order
170:
171: @order: An ordered list of students (username:domain)
172:
173: =back
174:
175: =cut
176:
177: sub SortStudents {
1.29 stredwic 178: my ($cache)=@_;
1.27 stredwic 179:
1.29 stredwic 180: my @students = split(':::',$cache->{'NamesOfStudents'});
1.27 stredwic 181: my @sorted1Students=();
1.29 stredwic 182: foreach (@students) {
183: if($cache->{'Status'} eq 'Any' ||
184: $cache->{$_.':Status'} eq $cache->{'Status'}) {
185: push(@sorted1Students, $_);
186: }
1.1 albertel 187: }
1.27 stredwic 188:
1.29 stredwic 189: my $sortBy = '';
190: if(defined($cache->{'sort'})) {
191: $sortBy = ':'.$cache->{'sort'};
1.27 stredwic 192: }
1.29 stredwic 193: my @order = sort { $cache->{$a.$sortBy} cmp $cache->{$b.$sortBy} ||
194: $cache->{$a.':fullname'} cmp $cache->{$b.':fullname'} }
195: @sorted1Students;
1.27 stredwic 196:
197: return \@order;
198: }
199:
200: sub PrepareData {
201: my ($c, $cacheDB)=@_;
202:
203: # Test for access to the cache data
204: my $courseID=$ENV{'request.course.id'};
205: my $isRecalculate=0;
1.29 stredwic 206: if(defined($ENV{'form.Recalculate'})) {
1.27 stredwic 207: $isRecalculate=1;
208: }
209:
1.29 stredwic 210: my $isCached = &Apache::loncoursedata::TestCacheData($cacheDB,
211: $isRecalculate);
1.27 stredwic 212: if($isCached < 0) {
213: return "Unable to tie hash to db file.";
214: }
215:
216: # Download class list information if not using cached data
217: my %cache;
1.29 stredwic 218: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {
219: return "Unable to tie hash to db file.";
220: }
221:
1.27 stredwic 222: if(!$isCached) {
223: my $processTopResourceMapReturn=
224: &Apache::loncoursedata::ProcessTopResourceMap(\%cache, $c);
225: if($processTopResourceMapReturn ne 'OK') {
226: untie(%cache);
227: return $processTopResourceMapReturn;
228: }
1.29 stredwic 229: }
1.27 stredwic 230:
1.29 stredwic 231: if($c->aborted()) {
232: untie(%cache);
233: return 'aborted';
234: }
1.27 stredwic 235:
1.29 stredwic 236: my $classlist=&Apache::loncoursedata::DownloadClasslist($courseID,
237: $cache{'ClasslistTimestamp'},
238: $c);
239: foreach (keys(%$classlist)) {
240: if(/^(con_lost|error|no_such_host)/i) {
1.27 stredwic 241: untie(%cache);
242: return "Error getting student data.";
243: }
1.29 stredwic 244: }
1.27 stredwic 245:
1.29 stredwic 246: if($c->aborted()) {
247: untie(%cache);
248: return 'aborted';
249: }
250:
251: # Active is a temporary solution, remember to change
252: Apache::loncoursedata::ProcessClasslist(\%cache,$classlist,$courseID,$c);
253: if($c->aborted()) {
254: untie(%cache);
255: return 'aborted';
256: }
1.27 stredwic 257:
1.29 stredwic 258: &ProcessFormData(\%cache);
259: my $students = &SortStudents(\%cache);
1.27 stredwic 260:
1.29 stredwic 261: if($cache{'download'} ne 'false') {
262: my $who = $cache{'download'};
263: my $courseData =
1.30 ! stredwic 264: &Apache::loncoursedata::DownloadCourseInformation(
1.29 stredwic 265: $who, $courseID,
266: $cache{$who.':lastDownloadTime'});
267: &Apache::loncoursedata::ProcessStudentData(\%cache, $courseData, $who);
268: $cache{'download'} = 'false';
269: } elsif($cache{'DownloadAll'} ne 'false') {
270: my @allStudents;
271: if($cache{'DownloadAll'} eq 'sorted') {
272: @allStudents = @$students;
273: } else {
274: @allStudents = split(':::', $cache{'NamesOfStudents'});
275: }
276: foreach (@allStudents) {
277: my $courseData =
1.30 ! stredwic 278: &Apache::loncoursedata::DownloadCourseInformation(
1.29 stredwic 279: $_, $courseID,
280: $cache{$_.':lastDownloadTime'});
281: &Apache::loncoursedata::ProcessStudentData(\%cache, $courseData,
282: $_);
283: if($c->aborted()) {
284: untie(%cache);
285: return 'aborted';
286: }
1.27 stredwic 287: }
1.29 stredwic 288: $cache{'DownloadAll'} = 'false';
289: }
1.27 stredwic 290:
1.29 stredwic 291: if($c->aborted()) {
1.27 stredwic 292: untie(%cache);
1.29 stredwic 293: return 'aborted';
294: }
295:
296: if($c->aborted()) {
297: untie(%cache);
298: return 'aborted';
1.27 stredwic 299: }
300:
1.29 stredwic 301: untie(%cache);
302:
303: return ('OK', $students);
1.27 stredwic 304: }
305:
306: # Create progress
307: sub Create_PrgWin {
308: $r->print(<<ENDPOP);
309: <script>
310: popwin=open('','popwin','width=400,height=100');
311: popwin.document.writeln('<html><body bgcolor="#88DDFF">'+
312: '<title>LON-CAPA Statistics</title>'+
313: '<h4>Computation Progress</h4>'+
314: '<form name=popremain>'+
315: '<input type=text size=35 name=remaining value=Starting></form>'+
316: '</body></html>');
317: popwin.document.close();
318: </script>
319: ENDPOP
320:
321: $r->rflush();
1.1 albertel 322: }
323:
1.27 stredwic 324: # update progress
325: sub Update_PrgWin {
326: my ($totalStudents,$index,$name)=@_;
327: $r->print('<script>popwin.document.popremain.remaining.value="'.
328: 'Computing '.$index.'/'.$totalStudents.': '.
329: $name.'";</script>');
330: $r->rflush();
331: }
1.1 albertel 332:
1.27 stredwic 333: # close Progress Line
334: sub Close_PrgWin {
335: $r->print('<script>popwin.close()</script>');
336: $r->rflush();
1.25 minaeibi 337: }
338:
339: # For loading the colored table for display or un-colored for print
340: sub setbgcolor {
341: my $PrintTable=shift;
342: undef %color;
343: if ($PrintTable){
344: $color{"gb"}="#FFFFFF";
345: $color{"red"}="#FFFFFF";
346: $color{"yellow"}="#FFFFFF";
347: $color{"green"}="#FFFFFF";
348: $color{"purple"}="#FFFFFF";
349: } else {
350: $color{"gb"}="#DDFFFF";
351: $color{"red"}="#FFDDDD";
352: $color{"yellow"}="#EEFFCC";
353: $color{"green"}="#DDFFDD";
354: $color{"purple"}="#FFDDFF";
355: }
1.27 stredwic 356:
357: return;
1.1 albertel 358: }
359:
1.29 stredwic 360: sub BuildClasslist {
361: my ($cacheDB,$students,$studentInformation,$headings,$spacePadding)=@_;
362:
363: my %cache;
364: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
365: return '<html><body>Unable to tie database.</body></html>';
1.1 albertel 366: }
367:
1.29 stredwic 368: my $Str='';
369: $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";
370: $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";
371:
372: my $displayString = '<td align="left"><a href="/adm/statistics?';
373: $displayString .= 'sort=LINKDATA">DISPLAYDATA </a></td>'."\n";
374: $Str .= &Apache::lonhtmlcommon::CreateStudentInformationHeadings(\%cache,
375: $studentInformation,
376: $headings,
377: $displayString);
378: $Str .= '<td align="left">';
379: $Str .= '<a href="/adm/statistics?sort=lastDownloadTime">';
1.30 ! stredwic 380: $Str .= 'Last Updated </a></td>'."\n";
1.29 stredwic 381: $Str .= '</tr>'."\n";
382: my $alternate=0;
383: foreach (@$students) {
384: my ($username, $domain) = split(':', $_);
385: if($alternate) {
386: $Str .= '<tr bgcolor="#ffffe6"><td>';
387: } else {
388: $Str .= '<tr bgcolor="#ffffc6"><td>';
389: }
390: $alternate = ($alternate + 1) % 2;
391: foreach my $data (@$studentInformation) {
392: if($data eq 'fullname') {
393: $Str .= '<a href="/adm/statistics?reportSelected=';
1.30 ! stredwic 394: $Str .= &Apache::lonnet::escape('Student Assessment');
! 395: $Str .= '&StudentAssessmentStudent=';
! 396: $Str .= &Apache::lonnet::escape($cache{$_.':'.$data}).'">';
! 397: #$Str .= 'Student Assessment'.'">';
1.29 stredwic 398: }
399:
400: $Str .= $cache{$_.':'.$data}.' ';
401:
402: if($data eq 'fullname') {
403: $Str .= '</a>';
404: }
405:
406: $Str .= '</td><td>';
407: }
408:
409: $Str .= '<a href="/adm/statistics?download='.$_.'">';
410: my $downloadTime = $cache{$_.':lastDownloadTime'};
411: if($downloadTime ne 'Not downloaded') {
412: $downloadTime = localtime($downloadTime);
413: }
414: $Str .= $downloadTime;
415:
416: $Str .= ' </a></td></tr>'."\n";
1.1 albertel 417: }
1.29 stredwic 418:
419: $Str .= '</table></td></tr></table>'."\n";
420:
1.27 stredwic 421: untie(%cache);
1.1 albertel 422:
1.29 stredwic 423: return $Str;
1.1 albertel 424: }
425:
1.29 stredwic 426: sub BuildStatistics {
427: my ($r)=@_;
428:
429: my $c = $r->connection;
430: my @studentInformation=('fullname','section','id','domain','username');
431: my @headings=('Full Name', 'Section', 'PID', 'Domain', 'User Name');
432: my $spacePadding = ' ';
433: my %reports = ('classlist' => 'Class list',
434: 'problem_statistics' => 'Problem Statistics',
435: 'student_assessment' => 'Student Assessment',
436: 'reportSelected' => 'Class list');
1.27 stredwic 437:
438: my %cache;
1.29 stredwic 439: my $courseID=$ENV{'request.course.id'};
440: my $cacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
441: "_$ENV{'user.domain'}_$courseID\_statistics.db";
442:
443: &setbgcolor(0);
444: my ($returnValue, $students) = &PrepareData($c, $cacheDB);
445: if($returnValue ne 'OK') {
446: $r->print('<html><body>'.$returnValue."\n".'</body></html>');
447: return OK;
448: }
449:
450: my $GoToPage;
451: if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
452: $GoToPage = $cache{'reportSelected'};
453: $reports{'reportSelected'} = $cache{'reportSelected'};
454: # if(defined($cache{'reportKey'}) && $cache{'reportKey'} ne 'false') {
455: # $reports{$cache{'reportKey'}} = $cache{'reportSelected'};
456: # }
457:
458: if(defined($cache{'OptionResponses'})) {
459: $reports{'problem_analysis'} = 'Problem Analysis';
460: }
461:
462: $r->print(&Apache::lonhtmlcommon::Title('LON-CAPA Statistics'));
463: $r->print('<form name="Statistics" ');
464: $r->print('method="post" action="/adm/statistics">');
465: $r->print(&Apache::lonhtmlcommon::CreateStatisticsMainMenu(
466: $cache{'Status'},
467: \%reports));
468: untie(%cache);
469: } else {
1.27 stredwic 470: $r->print('<html><body>Unable to tie database.</body></html>');
1.29 stredwic 471: return OK;
472: }
473:
474: if($GoToPage eq 'Activity Log') {
1.30 ! stredwic 475: &Apache::lonproblemstatistics::Activity();
1.29 stredwic 476: } elsif($GoToPage eq 'Problem Statistics') {
1.30 ! stredwic 477: $r->print(
! 478: &Apache::lonproblemstatistics::BuildProblemStatisticsPage($cacheDB,
! 479: $students,
! 480: $courseID,
! 481: $c,$r));
1.29 stredwic 482: } elsif($GoToPage eq 'Problem Analysis') {
1.30 ! stredwic 483: $r->print(
! 484: &Apache::lonproblemanalysis::BuildProblemAnalysisPage($cacheDB));
1.29 stredwic 485: } elsif($GoToPage eq 'Student Assessment') {
1.30 ! stredwic 486: $r->print(
! 487: &Apache::lonstudentassessment::BuildStudentAssessmentPage($cacheDB,
! 488: $students,
! 489: $courseID,
! 490: $c));
1.29 stredwic 491: } elsif($GoToPage eq 'Analyze') {
1.30 ! stredwic 492: $r->print(&Apache::lonproblemanalysis::BuildAnalyzePage($cacheDB,
! 493: $students,
! 494: $courseID));
1.29 stredwic 495: } elsif($GoToPage eq 'DoDiffGraph') {
1.30 ! stredwic 496: &Apache::lonproblemstatistics::BuildDiffGraph($courseID);
1.29 stredwic 497: } elsif($GoToPage eq 'PercentWrongGraph') {
1.30 ! stredwic 498: &Apache::lonproblemstatistics::BuildWrongGraph($courseID);
1.29 stredwic 499: } elsif($GoToPage eq 'Class list') {
500: $r->print(&BuildClasslist($cacheDB, $students, \@studentInformation,
501: \@headings, $spacePadding));
1.27 stredwic 502: }
503:
504: $r->print('</form>'."\n");
1.29 stredwic 505: $r->print("\n".'</body>'."\n".'</html>');
506: $r->rflush();
1.27 stredwic 507:
1.29 stredwic 508: return OK;
1.27 stredwic 509: }
1.1 albertel 510:
511: # ================================================================ Main Handler
512:
513: sub handler {
514: $r=shift;
515:
1.27 stredwic 516: unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
517: $ENV{'user.error.msg'}=
518: $r->uri.":vgr:0:0:Cannot view grades for complete course";
519: return HTTP_NOT_ACCEPTABLE;
520: }
521:
522: # Set document type for header only
523: if($r->header_only) {
524: if ($ENV{'browser.mathml'}) {
525: $r->content_type('text/xml');
526: } else {
527: $r->content_type('text/html');
528: }
529: &Apache::loncommon::no_cache($r);
530: $r->send_http_header;
531: return OK;
532: }
533:
534: unless($ENV{'request.course.fn'}) {
1.1 albertel 535: my $requrl=$r->uri;
1.27 stredwic 536: $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";
537: return HTTP_NOT_ACCEPTABLE;
538: }
1.1 albertel 539:
1.27 stredwic 540: $r->content_type('text/html');
541: $r->send_http_header;
1.1 albertel 542:
1.29 stredwic 543: &BuildStatistics($r);
1.27 stredwic 544:
545: return OK;
1.1 albertel 546: }
547: 1;
548: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>