File:
[LON-CAPA] /
loncom /
interface /
lonstatistics.pm
Revision
1.115:
download - view:
text,
annotated -
select for diffs
Fri Feb 25 02:37:49 2005 UTC (19 years, 4 months ago) by
matthew
Branches:
MAIN
CVS tags:
HEAD
Reworking to use navmaps directly. It compiles. Most statistics pages
will not load. chart works for html output only, although the columns are
off and all sequences are selected regardless of what you say. In short,
it needs work. A lot of work. Guess I'll be busy tomorrow.
1: # The LearningOnline Network with CAPA
2: #
3: # $Id: lonstatistics.pm,v 1.115 2005/02/25 02:37:49 matthew Exp $
4: #
5: # Copyright Michigan State University Board of Trustees
6: #
7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
8: #
9: # LON-CAPA is free software; you can redistribute it and/or modify
10: # it under the terms of the GNU General Public License as published by
11: # the Free Software Foundation; either version 2 of the License, or
12: # (at your option) any later version.
13: #
14: # LON-CAPA is distributed in the hope that it will be useful,
15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: # GNU General Public License for more details.
18: #
19: # You should have received a copy of the GNU General Public License
20: # along with LON-CAPA; if not, write to the Free Software
21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: #
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: # (Navigate problems for statistical reports
28: #
29: ###
30:
31: =pod
32:
33: =head1 NAME
34:
35: lonstatistics
36:
37: =head1 SYNOPSIS
38:
39: Main handler for statistics and chart.
40:
41: =over 4
42:
43: =cut
44:
45: package Apache::lonstatistics;
46:
47: use strict;
48: use Apache::Constants qw(:common :http);
49: use vars qw(
50: @FullClasslist
51: @Students
52: @Sections
53: @SelectedSections
54: %StudentData
55: @StudentDataOrder
56: @SelectedStudentData
57: $enrollment_status);
58:
59: use Apache::lonnet();
60: use Apache::lonhomework;
61: use Apache::loncommon;
62: use Apache::loncoursedata;
63: use Apache::lonhtmlcommon;
64: use Apache::lonmysql;
65: use Apache::lonlocal;
66: use Time::HiRes;
67: #
68: # Statistics Packages
69: use Apache::lonproblemanalysis();
70: use Apache::lonsubmissiontimeanalysis();
71: use Apache::loncorrectproblemplot();
72: use Apache::lonproblemstatistics();
73: use Apache::lonstudentassessment();
74: use Apache::lonpercentage;
75: use Apache::lonstudentsubmissions();
76: use Apache::lonsurveyreports();
77:
78: #######################################################
79: #######################################################
80:
81: =pod
82:
83: =item Package Variables
84:
85: =item @FullClasslist The full classlist
86:
87: =item @Students The students we are concerned with for this invocation
88:
89: =item @Sections The sections available in this class
90:
91: =item $curr_student The student currently being examined
92:
93: =item $prev_student The student previous in the classlist
94:
95: =item $next_student The student next in the classlist
96:
97: =over
98:
99: =cut
100:
101: #######################################################
102: #######################################################
103: #
104: # Classlist variables
105: #
106: my $curr_student;
107: my $prev_student;
108: my $next_student;
109:
110: #######################################################
111: #######################################################
112:
113: =pod
114:
115: =item &clear_classlist_variables()
116:
117: undef the following package variables:
118:
119: =over
120:
121: =item @FullClasslist
122:
123: =item @Students
124:
125: =item @Sections
126:
127: =item @SelectedSections
128:
129: =item %StudentData
130:
131: =item @StudentDataOrder
132:
133: =item @SelectedStudentData
134:
135: =item $curr_student
136:
137: =item $prev_student
138:
139: =item $next_student
140:
141: =back
142:
143: =cut
144:
145: #######################################################
146: #######################################################
147: sub clear_classlist_variables {
148: undef(@FullClasslist);
149: undef(@Students);
150: undef(@Sections);
151: undef(@SelectedSections);
152: undef(%StudentData);
153: undef(@SelectedStudentData);
154: undef($curr_student);
155: undef($prev_student);
156: undef($next_student);
157: }
158:
159: #######################################################
160: #######################################################
161:
162: =pod
163:
164: =item &PrepareClasslist()
165:
166: Build up the classlist information. The classlist information is kept in
167: the following package variables:
168:
169: =over
170:
171: =item @FullClasslist
172:
173: =item @Students
174:
175: =item @Sections
176:
177: =item @SelectedSections
178:
179: =item %StudentData
180:
181: =item @SelectedStudentData
182:
183: =item $curr_student
184:
185: =item $prev_student
186:
187: =item $next_student
188:
189: =back
190:
191: $curr_student, $prev_student, and $next_student may not be defined, depending
192: upon the calling context.
193:
194: =cut
195:
196: #######################################################
197: #######################################################
198: sub PrepareClasslist {
199: my %Sections;
200: &clear_classlist_variables();
201: #
202: # Retrieve the classlist
203: my $cid = $ENV{'request.course.id'};
204: my $cdom = $ENV{'course.'.$cid.'.domain'};
205: my $cnum = $ENV{'course.'.$cid.'.num'};
206: my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cid,
207: $cdom,$cnum);
208: if (exists($ENV{'form.Section'})) {
209: if (ref($ENV{'form.Section'})) {
210: @SelectedSections = @{$ENV{'form.Section'}};
211: } elsif ($ENV{'form.Section'} !~ /^\s*$/) {
212: @SelectedSections = ($ENV{'form.Section'});
213: }
214: }
215: @SelectedSections = ('all') if (! @SelectedSections);
216: foreach (@SelectedSections) {
217: if ($_ eq 'all') {
218: @SelectedSections = ('all');
219: }
220: }
221: #
222: # Deal with instructors with restricted section access
223: if ($ENV{'request.course.sec'} !~ /^\s*$/) {
224: @SelectedSections = ($ENV{'request.course.sec'});
225: }
226: #
227: # Set up %StudentData
228: @StudentDataOrder = qw/fullname username domain id section status comments/;
229: foreach my $field (@StudentDataOrder) {
230: $StudentData{$field}->{'title'} = &mt($field);
231: $StudentData{$field}->{'base_width'} = length(&mt($field));
232: $StudentData{$field}->{'width'} =
233: $StudentData{$field}->{'base_width'};
234: }
235: #
236: # get the status requested
237: $enrollment_status = 'Active';
238: $enrollment_status = $ENV{'form.Status'} if (exists($ENV{'form.Status'}));
239: #
240: # Process the classlist
241: while (my ($student,$student_data) = each (%$classlist)) {
242: my $studenthash = ();
243: for (my $i=0; $i< scalar(@$field_names);$i++) {
244: my $field = $field_names->[$i];
245: # Store the data
246: $studenthash->{$field}=$student_data->[$i];
247: # Keep track of the width of the fields
248: next if (! exists($StudentData{$field}));
249: my $length = length($student_data->[$i]);
250: if ($StudentData{$field}->{'width'} < $length) {
251: $StudentData{$field}->{'width'} = $length;
252: }
253: }
254: push (@FullClasslist,$studenthash);
255: #
256: # Build up a list of sections
257: my $section = $studenthash->{'section'};
258: if (! defined($section) || $section =~/^\s*$/ || $section == -1) {
259: $studenthash->{'section'} = 'none';
260: $section = $studenthash->{'section'};
261: }
262: $Sections{$section}++;
263: #
264: # Only put in the list those students we are interested in
265: foreach my $sect (@SelectedSections) {
266: if ( (($sect eq 'all') ||
267: ($section eq $sect)) &&
268: (($studenthash->{'status'} eq $enrollment_status) ||
269: ($enrollment_status eq 'Any'))
270: ){
271: push (@Students,$studenthash);
272: last;
273: }
274: }
275: }
276: #
277: # Put the consolidated section data in the right place
278: if ($ENV{'request.course.sec'} !~ /^\s*$/) {
279: @Sections = ($ENV{'request.course.sec'});
280: } else {
281: @Sections = sort {$a cmp $b} keys(%Sections);
282: unshift(@Sections,'all'); # Put 'all' at the front of the list
283: }
284: #
285: # Sort the Students
286: my $sortby = 'fullname';
287: $sortby = $ENV{'form.sort'} if (exists($ENV{'form.sort'}));
288: my @TmpStudents = sort { $a->{$sortby} cmp $b->{$sortby} ||
289: $a->{'fullname'} cmp $b->{'fullname'} } @Students;
290: @Students = @TmpStudents;
291: #
292: # Now deal with that current student thing....
293: $curr_student = undef;
294: if (exists($ENV{'form.SelectedStudent'})) {
295: my ($current_uname,$current_dom) =
296: split(':',$ENV{'form.SelectedStudent'});
297: my $i;
298: for ($i = 0; $i<=$#Students; $i++) {
299: next if (($Students[$i]->{'username'} ne $current_uname) ||
300: ($Students[$i]->{'domain'} ne $current_dom));
301: $curr_student = $Students[$i];
302: last; # If we get here, we have our student.
303: }
304: if (defined($curr_student)) {
305: if ($i == 0) {
306: $prev_student = undef;
307: } else {
308: $prev_student = $Students[$i-1];
309: }
310: if ($i == $#Students) {
311: $next_student = undef;
312: } else {
313: $next_student = $Students[$i+1];
314: }
315: }
316: }
317: #
318: if (exists($ENV{'form.StudentData'})) {
319: if (ref($ENV{'form.StudentData'}) eq 'ARRAY') {
320: @SelectedStudentData = @{$ENV{'form.StudentData'}};
321: } else {
322: @SelectedStudentData = ($ENV{'form.StudentData'});
323: }
324: } else {
325: @SelectedStudentData = ('username');
326: }
327: foreach (@SelectedStudentData) {
328: if ($_ eq 'all') {
329: @SelectedStudentData = ('all');
330: last;
331: }
332: }
333: #
334: return;
335: }
336:
337:
338: #######################################################
339: #######################################################
340:
341: =pod
342:
343: =item get_students
344:
345: Returns a list of the selected students
346:
347: =cut
348:
349: #######################################################
350: #######################################################
351: sub get_students {
352: if (! @Students) {
353: &PrepareClasslist()
354: }
355: return @Students;
356: }
357:
358: #######################################################
359: #######################################################
360:
361: =pod
362:
363: =item ¤t_student()
364:
365: Returns a pointer to a hash containing data about the currently
366: selected student.
367:
368: =cut
369:
370: #######################################################
371: #######################################################
372: sub current_student {
373: return $curr_student;
374: }
375:
376: #######################################################
377: #######################################################
378:
379: =pod
380:
381: =item &previous_student()
382:
383: Returns a pointer to a hash containing data about the student prior
384: in the list of students. Or something.
385:
386: =cut
387:
388: #######################################################
389: #######################################################
390: sub previous_student {
391: return $prev_student;
392: }
393:
394: #######################################################
395: #######################################################
396:
397: =pod
398:
399: =item &next_student()
400:
401: Returns a pointer to a hash containing data about the next student
402: to be viewed.
403:
404: =cut
405:
406: #######################################################
407: #######################################################
408: sub next_student {
409: return $next_student;
410: }
411:
412: ##############################################
413: ##############################################
414:
415: =pod
416:
417: =item &StudentDataSelect($elementname,$status,$numvisible,$selected)
418:
419: Returns html for a selection box allowing the user to choose one (or more)
420: of the fields of student data available (fullname, username, id, section, etc)
421:
422: =over 4
423:
424: =item $elementname The name of the HTML form element
425:
426: =item $status 'multiple' or 'single' selection box
427:
428: =item $numvisible The number of options to be visible
429:
430: =back
431:
432: =cut
433:
434: ##############################################
435: ##############################################
436: sub StudentDataSelect {
437: my ($elementname,$status,$numvisible)=@_;
438: if ($numvisible < 1) {
439: return;
440: }
441: #
442: # Build the form element
443: my $Str = "\n";
444: $Str .= '<select name="'.$elementname.'" ';
445: if ($status ne 'single') {
446: $Str .= 'multiple="true" ';
447: }
448: $Str .= 'size="'.$numvisible.'" >'."\n";
449: #
450: # Deal with 'all'
451: $Str .= ' <option value="all" ';
452: foreach (@SelectedStudentData) {
453: if ($_ eq 'all') {
454: $Str .= 'selected ';
455: last;
456: }
457: }
458: $Str .= ">all</option>\n";
459: #
460: # Loop through the student data fields
461: foreach my $item (@StudentDataOrder) {
462: $Str .= ' <option value="'.$item.'" ';
463: foreach (@SelectedStudentData) {
464: if ($item eq $_ ) {
465: $Str .= 'selected ';
466: last;
467: }
468: }
469: $Str .= '>'.$item."</option>\n";
470: }
471: $Str .= "</select>\n";
472: return $Str;
473: }
474:
475: #######################################################
476: #######################################################
477:
478: =pod
479:
480: =item &get_selected_maps($elementname)
481:
482: Input: Name of the <select> form element used to specify the maps.
483:
484: Returns: Array of symbs of selected maps or the description 'all'.
485: If form.$elementname does not exist, 'all' is returned.
486:
487: =cut
488:
489: #######################################################
490: #######################################################
491: sub get_selected_maps {
492: my ($elementname) = @_;
493: my @selected_maps;
494: if (exists($ENV{'form.'.$elementname})) {
495: if (ref($ENV{'form.'.$elementname})) {
496: @selected_maps = @{$ENV{'form.'.$elementname}};
497: } else {
498: @selected_maps = ($ENV{'form.'.$elementname});
499: }
500: } else {
501: @selected_maps = ('all');
502: }
503: return @selected_maps;
504: }
505:
506:
507: #######################################################
508: #######################################################
509:
510: =pod
511:
512: =item &sequences_with_assessments
513:
514: Retrieve the sequences which were selected by the user to show.
515:
516: Input: $mode: scalar. Either 'selected' or 'all'. If not specified,
517: 'selected' is used.
518:
519: Returns: an array containing a navmap object and navmap resources,
520: or an array containing a scalar with an error message.
521:
522: =cut
523:
524: #######################################################
525: #######################################################
526: sub sequences_with_assessments {
527: my ($mode) = @_;
528: $mode = 'selected' if (! defined($mode));
529: my $navmap = Apache::lonnavmaps::navmap->new();
530: if (!defined($navmap)) {
531: return ('Can not open Coursemap');
532: }
533: #
534: my @sequences = $navmap->retrieveResources(undef,
535: sub { shift->is_map(); },1,0,1);
536: my @sequences_with_assessments;
537: for my $sequence ($navmap->getById('0.0'), @sequences) {
538: if ($navmap->hasResource($sequence,sub { shift->is_problem(); }, 0)){
539: push(@sequences_with_assessments,$sequence);
540: }
541: }
542: #
543: my @sequences_to_show;
544: foreach my $sequence (@sequences_with_assessments) {
545: if ($mode eq 'all') {
546: push (@sequences_to_show,$sequence);
547: } elsif ($mode eq 'selected') {
548: foreach my $map_symb (&get_selected_maps()) {
549: if ($sequence->symb eq $map_symb || $map_symb eq 'all'){
550: push (@sequences_to_show,$sequence);
551: last; # Only put it in once
552: }
553: }
554: }
555:
556: }
557: return $navmap,@sequences_to_show;
558: }
559:
560: ##############################################
561: ##############################################
562:
563: =pod
564:
565: =item &map_select($elementname,$status,$numvisible,$restriction)
566:
567: Returns html for a selection box allowing the user to choose one (or more)
568: of the sequences in the course. The values of the sequences are the symbs.
569: If the top sequence is selected, the value 'top' will result.
570:
571: =over 4
572:
573: =item $elementname The name of the HTML form element
574:
575: =item $status 'multiple' or 'single' selection box
576:
577: =item $numvisible The number of options to be visible
578:
579: =back
580:
581: =cut
582:
583: ##############################################
584: ##############################################
585: sub map_select {
586: my ($elementname,$status,$numvisible)=@_;
587: if ($numvisible < 1) {
588: return;
589: }
590: #
591: # Set up array of selected items
592: my @selected_maps = &get_selected_maps($elementname);
593: #
594: # Build the form element
595: my $form = "\n";
596: $form .= '<select name="'.$elementname.'" ';
597: if ($status ne 'single') {
598: $form .= 'multiple="true" ';
599: }
600: $form .= 'size="'.$numvisible.'" >'."\n";
601: #
602: # Deal with 'all'
603: foreach (@selected_maps) {
604: if ($_ eq 'all') {
605: @selected_maps = ('all');
606: last;
607: }
608: }
609: #
610: # Put in option for 'all'
611: $form .= ' <option value="all" ';
612: foreach (@selected_maps) {
613: if ($_ eq 'all') {
614: $form .= 'selected ';
615: last;
616: }
617: }
618: $form .= ">all</option>\n";
619: #
620: # Loop through the sequences
621: my @sequences = &sequences_with_assessments();
622: my $navmap;
623: if (!ref($sequences[0])) {
624: return $sequences[0];
625: } else {
626: $navmap = shift(@sequences);
627: }
628: foreach my $seq (@sequences){
629: $form .= ' <option value="'.$seq->symb.'" ';
630: foreach (@selected_maps) {
631: if ($seq->symb eq $_) {
632: $form .= 'selected ';
633: last;
634: }
635: }
636: $form .= '>'.$seq->compTitle."</option>\n";
637: }
638: $form .= "</select>\n";
639: return $form;
640: }
641:
642: ##############################################
643: ##############################################
644:
645: =pod
646:
647: =item &SectionSelect($elementname,$status,$numvisible)
648:
649: Returns html for a selection box allowing the user to choose one (or more)
650: of the sections in the course.
651:
652: Uses the package variables @Sections and @SelectedSections
653: =over 4
654:
655: =item $elementname The name of the HTML form element
656:
657: =item $status 'multiple' or 'single' selection box
658:
659: =item $numvisible The number of options to be visible
660:
661: =back
662:
663: =cut
664:
665: ##############################################
666: ##############################################
667: sub SectionSelect {
668: my ($elementname,$status,$numvisible)=@_;
669: if ($numvisible < 1) {
670: return;
671: }
672: #
673: # Make sure we have the data we need to continue
674: if (! @Sections) {
675: &PrepareClasslist()
676: }
677: #
678: # Build the form element
679: my $Str = "\n";
680: $Str .= '<select name="'.$elementname.'" ';
681: if ($status ne 'single') {
682: $Str .= 'multiple="true" ';
683: }
684: $Str .= 'size="'.$numvisible.'" >'."\n";
685: #
686: # Loop through the sequences
687: foreach my $s (@Sections) {
688: $Str .= ' <option value="'.$s.'" ';
689: foreach (@SelectedSections) {
690: if ($s eq $_) {
691: $Str .= 'selected ';
692: last;
693: }
694: }
695: $Str .= '>'.$s."</option>\n";
696: }
697: $Str .= "</select>\n";
698: return $Str;
699: }
700:
701: ##################################################
702: ##################################################
703: sub DisplayClasslist {
704: my ($r)=@_;
705: &Apache::lonhtmlcommon::add_breadcrumb
706: ({text=>'Select One Student'});
707: #
708: # Output some of the standard interface components
709: my $Str;
710: $Str .= &Apache::lonhtmlcommon::breadcrumbs(undef,'Select One Student');
711: $Str .= '<p><table cellspacing="5">'."\n";
712: $Str .= '<tr>';
713: $Str .= '<th align="center"><b>'.&mt('Sections').'</b></th>';
714: $Str .= '<th align="center"><b>'.&mt('Enrollment Status').'</b></th>';
715: $Str .= '</tr>'.$/;
716: $Str .= '<tr>';
717: $Str .= '<td>'.
718: &Apache::lonstatistics::SectionSelect('Section','multiple',5).
719: '</td>';
720: $Str .= '<td>'.
721: &Apache::lonhtmlcommon::StatusOptions(undef,undef,5).
722: '</td>';
723:
724: $Str .= '</tr>'.$/;
725: $Str .= '</table></p>';
726: $Str .= '<input type="submit" name="selectstudent" value="'.
727: &mt('Update Display').'" />';
728: $r->print($Str);
729: $r->rflush();
730: #
731: my @Fields = ('fullname','username','domain','id','section','status');
732: #
733: $Str = '';
734: if (! @Students) {
735: if ($SelectedSections[0] eq 'all') {
736: if (lc($ENV{'form.Status'}) eq 'any') {
737: $Str .= '<h2>'.
738: &mt('There are no students in the course.').
739: '</h2>';
740: } elsif (lc($ENV{'form.Status'}) eq 'active') {
741: $Str .= '<h2>'.
742: &mt('There are no currently enrolled students in the course.').
743: '</h2>';
744: } elsif (lc($ENV{'form.Status'}) eq 'expired') {
745: $Str .= '<h2>'.
746: &mt('There are no previously enrolled students in the course.').
747: '</h2>';
748: }
749: } else {
750: my $sections;
751: if (lc($ENV{'form.Status'}) eq 'any') {
752: $Str .= '<h2>'.
753: &mt('There are no students in the selected sections.').
754: '</h2>';
755: } elsif (lc($ENV{'form.Status'}) eq 'active') {
756: $Str .= '<h2>'.
757: &mt('There are no currently enrolled students in the selected sections.').
758: '</h2>';
759: } elsif (lc($ENV{'form.Status'}) eq 'expired') {
760: $Str .= '<h2>'.
761: &mt('There are no previously enrolled students in the selected sections.').
762: '</h2>';
763: }
764: }
765: $Str.= '<a href="/adm/statistics?reportSelected=student_assessment">'.
766: &mt('Click here to return to the chart').'</a>';
767: $r->print($Str);
768: $r->rflush();
769: return;
770: }
771:
772: # "Click" is asinine but it is probably not my place to change the world.
773: $Str .= '<h2>Click on a students name or username to view their chart</h2>';
774: $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";
775: $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";
776: foreach my $field (@Fields) {
777: $Str .= '<th><a href="/adm/statistics?'.
778: 'reportSelected=student_assessment&'.
779: 'selectstudent=1&'.
780: 'sort='.$field.'">'.&mt($field).
781: '</a></th>';
782: }
783: $Str .= '</tr>'."\n";
784: #
785: my $alternate = 0;
786: foreach my $student (@Students) { # @Students is a package variable
787: my $sname = $student->{'username'}.':'.$student->{'domain'};
788: if($alternate) {
789: $Str .= '<tr bgcolor="#ffffe6">';
790: } else {
791: $Str .= '<tr bgcolor="#ffffc6">';
792: }
793: $alternate = ($alternate + 1) % 2;
794: #
795: foreach my $field (@Fields) {
796: $Str .= '<td>';
797: if ($field eq 'fullname' || $field eq 'username') {
798: $Str .= '<a href="/adm/statistics?reportSelected=';
799: $Str .= &Apache::lonnet::escape('student_assessment');
800: $Str .= '&sort='.&Apache::lonnet::escape($ENV{'form.sort'});
801: $Str .= '&SelectedStudent=';
802: $Str .= &Apache::lonnet::escape($sname).'">';
803: $Str .= $student->{$field}.' ';
804: $Str .= '</a>';
805: } elsif ($field eq 'status') {
806: $Str .= &mt($student->{$field});
807: } else {
808: $Str .= $student->{$field};
809: }
810: $Str .= '</td>';
811: }
812: $Str .= "</tr>\n";
813: }
814: $Str .= '</table></td></tr></table>'."\n";
815: #
816: $r->print($Str);
817: $r->rflush();
818: #
819: return;
820: }
821:
822: ##############################################
823: ##############################################
824: sub CreateMainMenu {
825: #
826: # Define menu data
827: my @reports = ({ internal_name => 'problem_statistics',
828: name => &mt('Overall Problem Statistics'),
829: short_description =>
830: &mt('Student performance statistics on all problems.'),
831: },
832: { internal_name => 'problem_analysis',
833: name => &mt('Detailed Problem Analysis'),
834: short_description =>
835: &mt('Detailed statistics and graphs of student performance on problems.'),
836: },
837: { internal_name => 'submissiontime_analysis',
838: name => &mt('Submission Time Plots'),
839: short_description =>
840: &mt('Display and analysis of submission times on assessments.'),
841: },
842: { internal_name => 'student_submission_reports',
843: name => &mt('Student Submission Reports'),
844: short_description =>
845: &mt('Prepare reports of student submissions.'),
846: },
847: { internal_name => 'survey_reports',
848: name => &mt('Survey Reports'),
849: short_description =>
850: &mt('Prepare reports on survey results.'),
851: },
852: { internal_name => 'correct_problems_plot',
853: name => &mt('Correct Problems Plot'),
854: short_description =>
855: &mt('Display a histogram of student performance in the course.'),
856: },
857: # { internal_name => 'student_assessment',
858: # name => &mt('Problem Status Chart'),
859: # short_description =>
860: # &mt('Brief view of each students performance in course.'),
861: # },
862: # 'percentage' => 'Correct-problems Plot',
863: # 'activitylog' => 'Activity Log',
864: );
865: #
866: # Create the menu
867: my $Str;
868: $Str .= '<h2>'.&mt('Please select a report to generate').'</h2>';
869: foreach my $reportdata (@reports) {
870: $Str .=' <h3><a href="/adm/statistics?reportSelected='.
871: $reportdata->{'internal_name'}.'" >'.
872: $reportdata->{'name'}."</a></h3>\n";
873: $Str .= ' '.(' 'x8).$reportdata->{'short_description'}.
874: "\n";
875: }
876: $Str .="</dl>\n";
877: #
878: return $Str;
879: }
880:
881: ##############################################
882: ##############################################
883: sub handler {
884: my $r=shift;
885: my $c = $r->connection();
886: #
887: # Check for overloading
888: my $loaderror=&Apache::lonnet::overloaderror($r);
889: if ($loaderror) { return $loaderror; }
890: $loaderror=
891: &Apache::lonnet::overloaderror($r,
892: $ENV{'course.'.$ENV{'request.course.id'}.'.home'});
893: if ($loaderror) { return $loaderror; }
894: #
895: # Check for access
896: if (! &Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
897: $ENV{'user.error.msg'}=
898: $r->uri.":vgr:0:0:Cannot view grades for complete course";
899: if (! &Apache::lonnet::allowed('vgr',
900: $ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'})) {
901: $ENV{'user.error.msg'}=
902: $r->uri.":vgr:0:0:Cannot view grades with given role";
903: return HTTP_NOT_ACCEPTABLE;
904: }
905: }
906: #
907: # Send the header
908: &Apache::loncommon::no_cache($r);
909: &Apache::loncommon::content_type($r,'text/html');
910: $r->send_http_header;
911: if ($r->header_only) { return OK; }
912: #
913: # Extract form elements from query string
914: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
915: ['sort','reportSelected',
916: 'SelectedStudent']);
917: #
918: # Give the LON-CAPA page header
919: my $style = <<ENDSTYLE;
920: <style type="text/css">
921: ul.sub_studentans { list-style-type: none }
922: ul.sub_correctans { list-style-type: none }
923: tr.even { background-color: \#CCCCCC }
924: td.essay { border: 1px solid gray; }
925: </style>
926: ENDSTYLE
927: my $html=&Apache::lonxml::xmlbegin();
928: $r->print($html.'<head><title>'.
929: &mt('Course Statistics and Charts').
930: '</title>'.$style.
931: "</head>\n".
932: &Apache::loncommon::bodytag('Course Statistics and Charts'));
933: $r->rflush();
934: #
935: # Either print out a menu for them or send them to a report
936: &Apache::lonhtmlcommon::clear_breadcrumbs();
937: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/statistics',
938: title=>'Statistics',
939: text =>'Statistics',
940: faq=>139,
941: bug=>'Statistics and Charts'});
942: if (! exists($ENV{'form.reportSelected'}) ||
943: $ENV{'form.reportSelected'} eq '') {
944: $r->print(&Apache::lonhtmlcommon::breadcrumbs
945: (undef,&mt('Statistics Main Page')).
946: &CreateMainMenu());
947: } else {
948: #
949: if (! &Apache::lonmysql::verify_sql_connection()) {
950: my $serveradmin = $r->dir_config('lonAdmEMail');
951: $r->print('<h2><font color="Red">'.
952: &mt('Unable to connect to database!').
953: '</font></h2>');
954: $r->print('<p>'.
955: &mt('Please notify the server administrator ').
956: '<b>'.$serveradmin.'</b></p>');
957: $r->print('<p>'.
958: &mt('Course Statistics and Charts cannot be '.
959: 'retrieved until the database is restarted. '.
960: 'Your data is intact but cannot be displayed '.
961: 'at this time.').'</p>');
962: $r->print('</body></html>');
963: return;
964: }
965: #
966: # Clean out the caches
967: if (exists($ENV{'form.ClearCache'})) {
968: &Apache::loncoursedata::delete_caches($ENV{'requres.course.id'});
969: }
970: #
971: # Begin form output
972: $r->print('<form name="Statistics" ');
973: $r->print('method="post" action="/adm/statistics">');
974: $r->rflush();
975: #
976: my $GoToPage = $ENV{'form.reportSelected'};
977: #
978: $r->print('<input type="hidden" name="reportSelected" value="'.
979: $GoToPage.'">');
980: if($GoToPage eq 'activitylog') {
981: # &Apache::lonproblemstatistics::Activity();
982: } elsif($GoToPage eq 'problem_statistics') {
983: &Apache::lonhtmlcommon::add_breadcrumb
984: ({href=>'/adm/statistics?reportselected=problem_statistics',
985: text=>'Overall Problem Statistics'});
986: &Apache::lonproblemstatistics::BuildProblemStatisticsPage($r,$c);
987: } elsif($GoToPage eq 'problem_analysis') {
988: &Apache::lonhtmlcommon::add_breadcrumb
989: ({href=>'/adm/statistics?reportselected=problem_analysis',
990: text=>'Detailed Problem Analysis'});
991: &Apache::lonproblemanalysis::BuildProblemAnalysisPage($r,$c);
992: } elsif($GoToPage eq 'submissiontime_analysis') {
993: &Apache::lonhtmlcommon::add_breadcrumb
994: ({href=>
995: '/adm/statistics?reportselected=submissiontime_analysis',
996: text=>'Submission Time Plots'});
997: &Apache::lonsubmissiontimeanalysis::BuildSubmissionTimePage($r,$c);
998: } elsif($GoToPage eq 'student_submission_reports') {
999: &Apache::lonhtmlcommon::add_breadcrumb
1000: ({href=>
1001: '/adm/statistics?reportselected=student_submission_reports',
1002: text=>'Student Submission Reports'});
1003: &Apache::lonstudentsubmissions::BuildStudentSubmissionsPage($r,$c);
1004: } elsif($GoToPage eq 'survey_reports') {
1005: &Apache::lonhtmlcommon::add_breadcrumb
1006: ({href=>
1007: '/adm/statistics?reportselected=survey_reports',
1008: text=>'Survey Reports'});
1009: &Apache::lonsurveyreports::BuildSurveyReportsPage($r,$c);
1010: } elsif($GoToPage eq 'correct_problems_plot') {
1011: &Apache::lonhtmlcommon::add_breadcrumb
1012: ({href=>'/adm/statistics?reportselected=correct_problems_plot',
1013: text=>'Correct Problems Plot'});
1014: &Apache::loncorrectproblemplot::BuildCorrectProblemsPage($r,$c);
1015: } elsif($GoToPage eq 'student_assessment') {
1016: &Apache::lonhtmlcommon::clear_breadcrumbs();
1017: &Apache::lonhtmlcommon::add_breadcrumb
1018: ({href=>'/adm/statistics?reportselected=student_assessment',
1019: text=>'Chart'});
1020: &Apache::lonstudentassessment::BuildStudentAssessmentPage($r,$c);
1021: }
1022: #
1023: $r->print("</form>\n");
1024: }
1025: $r->print("</body>\n</html>\n");
1026: $r->rflush();
1027: #
1028: return OK;
1029: }
1030:
1031: 1;
1032:
1033: #######################################################
1034: #######################################################
1035:
1036: =pod
1037:
1038: =back
1039:
1040: =cut
1041:
1042: #######################################################
1043: #######################################################
1044:
1045: __END__
1046:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>