File:
[LON-CAPA] /
loncom /
interface /
lonstatistics.pm
Revision
1.116:
download - view:
text,
annotated -
select for diffs
Fri Feb 25 19:48:00 2005 UTC (19 years, 4 months ago) by
matthew
Branches:
MAIN
CVS tags:
HEAD
lonstatistics:Changed name of sequences_with_assessments to
selected_sequences_with_assessments AND fixed bug where it returned all the
sequences with assessments instead of just those selected by the user.
lonstudentassessment: Now call selected_sequences_with_assessments
1: # The LearningOnline Network with CAPA
2: #
3: # $Id: lonstatistics.pm,v 1.116 2005/02/25 19:48:00 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 &selected_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 selected_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('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 = &selected_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>