File:
[LON-CAPA] /
loncom /
interface /
lonstatistics.pm
Revision
1.118:
download - view:
text,
annotated -
select for diffs
Tue Mar 1 22:25:59 2005 UTC (19 years, 4 months ago) by
matthew
Branches:
MAIN
CVS tags:
HEAD
loncorrectproblemsplot: use navmaps.
lonstatistics:&get_selected_maps: Now returns an array containing just
'all' if any one of the items in the array of selected maps is 'all'.
simplified code in &map_select to take advantage of the new functionality
in &get_selected_maps.
1: # The LearningOnline Network with CAPA
2: #
3: # $Id: lonstatistics.pm,v 1.118 2005/03/01 22:25:59 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: foreach my $map (@selected_maps) {
504: if ($map eq 'all') {
505: @selected_maps = ('all');
506: last;
507: }
508: }
509: return @selected_maps;
510: }
511:
512:
513: #######################################################
514: #######################################################
515:
516: =pod
517:
518: =item &selected_sequences_with_assessments
519:
520: Retrieve the sequences which were selected by the user to show.
521:
522: Input: $mode: scalar. Either 'selected' or 'all'. If not specified,
523: 'selected' is used.
524:
525: Returns: an array containing a navmap object and navmap resources,
526: or an array containing a scalar with an error message.
527:
528: =cut
529:
530: #######################################################
531: #######################################################
532: sub selected_sequences_with_assessments {
533: my ($mode) = @_;
534: $mode = 'selected' if (! defined($mode));
535: my $navmap = Apache::lonnavmaps::navmap->new();
536: if (!defined($navmap)) {
537: return ('Can not open Coursemap');
538: }
539: #
540: my @sequences = $navmap->retrieveResources(undef,
541: sub { shift->is_map(); },1,0,1);
542: my @sequences_with_assessments;
543: for my $sequence ($navmap->getById('0.0'), @sequences) {
544: if ($navmap->hasResource($sequence,sub { shift->is_problem(); }, 0)){
545: push(@sequences_with_assessments,$sequence);
546: }
547: }
548: #
549: my @sequences_to_show;
550: foreach my $sequence (@sequences_with_assessments) {
551: if ($mode eq 'all') {
552: push (@sequences_to_show,$sequence);
553: } elsif ($mode eq 'selected') {
554: foreach my $map_symb (&get_selected_maps('Maps')) {
555: if ($sequence->symb eq $map_symb || $map_symb eq 'all'){
556: push (@sequences_to_show,$sequence);
557: last; # Only put it in once
558: }
559: }
560: }
561:
562: }
563: return $navmap,@sequences_to_show;
564: }
565:
566: ##############################################
567: ##############################################
568:
569: =pod
570:
571: =item &map_select($elementname,$status,$numvisible,$restriction)
572:
573: Returns html for a selection box allowing the user to choose one (or more)
574: of the sequences in the course. The values of the sequences are the symbs.
575: If the top sequence is selected, the value 'top' will result.
576:
577: =over 4
578:
579: =item $elementname The name of the HTML form element
580:
581: =item $status 'multiple' or 'single' selection box
582:
583: =item $numvisible The number of options to be visible
584:
585: =back
586:
587: =cut
588:
589: ##############################################
590: ##############################################
591: sub map_select {
592: my ($elementname,$status,$numvisible)=@_;
593: if ($numvisible < 1) {
594: return;
595: }
596: #
597: # Set up array of selected items
598: my @selected_maps = &get_selected_maps($elementname);
599: #
600: # Build the form element
601: my $form = "\n";
602: $form .= '<select name="'.$elementname.'" ';
603: if ($status ne 'single') {
604: $form .= 'multiple="true" ';
605: }
606: $form .= 'size="'.$numvisible.'" >'."\n";
607: #
608: # Put in option for 'all'
609: $form .= ' <option value="all" ';
610: if ($selected_maps[0] eq 'all') {
611: $form .= 'selected ';
612: }
613: $form .= ">all</option>\n";
614: #
615: # Loop through the sequences
616: my @sequences = &selected_sequences_with_assessments('all');
617: my $navmap;
618: if (!ref($sequences[0])) {
619: return $sequences[0];
620: } else {
621: $navmap = shift(@sequences);
622: }
623: foreach my $seq (@sequences){
624: $form .= ' <option value="'.$seq->symb.'" ';
625: foreach (@selected_maps) {
626: if ($seq->symb eq $_) {
627: $form .= 'selected ';
628: last;
629: }
630: }
631: $form .= '>'.$seq->compTitle."</option>\n";
632: }
633: $form .= "</select>\n";
634: return $form;
635: }
636:
637: ##############################################
638: ##############################################
639:
640: =pod
641:
642: =item &SectionSelect($elementname,$status,$numvisible)
643:
644: Returns html for a selection box allowing the user to choose one (or more)
645: of the sections in the course.
646:
647: Uses the package variables @Sections and @SelectedSections
648: =over 4
649:
650: =item $elementname The name of the HTML form element
651:
652: =item $status 'multiple' or 'single' selection box
653:
654: =item $numvisible The number of options to be visible
655:
656: =back
657:
658: =cut
659:
660: ##############################################
661: ##############################################
662: sub SectionSelect {
663: my ($elementname,$status,$numvisible)=@_;
664: if ($numvisible < 1) {
665: return;
666: }
667: #
668: # Make sure we have the data we need to continue
669: if (! @Sections) {
670: &PrepareClasslist()
671: }
672: #
673: # Build the form element
674: my $Str = "\n";
675: $Str .= '<select name="'.$elementname.'" ';
676: if ($status ne 'single') {
677: $Str .= 'multiple="true" ';
678: }
679: $Str .= 'size="'.$numvisible.'" >'."\n";
680: #
681: # Loop through the sequences
682: foreach my $s (@Sections) {
683: $Str .= ' <option value="'.$s.'" ';
684: foreach (@SelectedSections) {
685: if ($s eq $_) {
686: $Str .= 'selected ';
687: last;
688: }
689: }
690: $Str .= '>'.$s."</option>\n";
691: }
692: $Str .= "</select>\n";
693: return $Str;
694: }
695:
696: ##################################################
697: ##################################################
698: sub DisplayClasslist {
699: my ($r)=@_;
700: &Apache::lonhtmlcommon::add_breadcrumb
701: ({text=>'Select One Student'});
702: #
703: # Output some of the standard interface components
704: my $Str;
705: $Str .= &Apache::lonhtmlcommon::breadcrumbs(undef,'Select One Student');
706: $Str .= '<p><table cellspacing="5">'."\n";
707: $Str .= '<tr>';
708: $Str .= '<th align="center"><b>'.&mt('Sections').'</b></th>';
709: $Str .= '<th align="center"><b>'.&mt('Enrollment Status').'</b></th>';
710: $Str .= '</tr>'.$/;
711: $Str .= '<tr>';
712: $Str .= '<td>'.
713: &Apache::lonstatistics::SectionSelect('Section','multiple',5).
714: '</td>';
715: $Str .= '<td>'.
716: &Apache::lonhtmlcommon::StatusOptions(undef,undef,5).
717: '</td>';
718:
719: $Str .= '</tr>'.$/;
720: $Str .= '</table></p>';
721: $Str .= '<input type="submit" name="selectstudent" value="'.
722: &mt('Update Display').'" />';
723: $r->print($Str);
724: $r->rflush();
725: #
726: my @Fields = ('fullname','username','domain','id','section','status');
727: #
728: $Str = '';
729: if (! @Students) {
730: if ($SelectedSections[0] eq 'all') {
731: if (lc($ENV{'form.Status'}) eq 'any') {
732: $Str .= '<h2>'.
733: &mt('There are no students in the course.').
734: '</h2>';
735: } elsif (lc($ENV{'form.Status'}) eq 'active') {
736: $Str .= '<h2>'.
737: &mt('There are no currently enrolled students in the course.').
738: '</h2>';
739: } elsif (lc($ENV{'form.Status'}) eq 'expired') {
740: $Str .= '<h2>'.
741: &mt('There are no previously enrolled students in the course.').
742: '</h2>';
743: }
744: } else {
745: my $sections;
746: if (lc($ENV{'form.Status'}) eq 'any') {
747: $Str .= '<h2>'.
748: &mt('There are no students in the selected sections.').
749: '</h2>';
750: } elsif (lc($ENV{'form.Status'}) eq 'active') {
751: $Str .= '<h2>'.
752: &mt('There are no currently enrolled students in the selected sections.').
753: '</h2>';
754: } elsif (lc($ENV{'form.Status'}) eq 'expired') {
755: $Str .= '<h2>'.
756: &mt('There are no previously enrolled students in the selected sections.').
757: '</h2>';
758: }
759: }
760: $Str.= '<a href="/adm/statistics?reportSelected=student_assessment">'.
761: &mt('Click here to return to the chart').'</a>';
762: $r->print($Str);
763: $r->rflush();
764: return;
765: }
766:
767: # "Click" is asinine but it is probably not my place to change the world.
768: $Str .= '<h2>Click on a students name or username to view their chart</h2>';
769: $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";
770: $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";
771: foreach my $field (@Fields) {
772: $Str .= '<th><a href="/adm/statistics?'.
773: 'reportSelected=student_assessment&'.
774: 'selectstudent=1&'.
775: 'sort='.$field.'">'.&mt($field).
776: '</a></th>';
777: }
778: $Str .= '</tr>'."\n";
779: #
780: my $alternate = 0;
781: foreach my $student (@Students) { # @Students is a package variable
782: my $sname = $student->{'username'}.':'.$student->{'domain'};
783: if($alternate) {
784: $Str .= '<tr bgcolor="#ffffe6">';
785: } else {
786: $Str .= '<tr bgcolor="#ffffc6">';
787: }
788: $alternate = ($alternate + 1) % 2;
789: #
790: foreach my $field (@Fields) {
791: $Str .= '<td>';
792: if ($field eq 'fullname' || $field eq 'username') {
793: $Str .= '<a href="/adm/statistics?reportSelected=';
794: $Str .= &Apache::lonnet::escape('student_assessment');
795: $Str .= '&sort='.&Apache::lonnet::escape($ENV{'form.sort'});
796: $Str .= '&SelectedStudent=';
797: $Str .= &Apache::lonnet::escape($sname).'">';
798: $Str .= $student->{$field}.' ';
799: $Str .= '</a>';
800: } elsif ($field eq 'status') {
801: $Str .= &mt($student->{$field});
802: } else {
803: $Str .= $student->{$field};
804: }
805: $Str .= '</td>';
806: }
807: $Str .= "</tr>\n";
808: }
809: $Str .= '</table></td></tr></table>'."\n";
810: #
811: $r->print($Str);
812: $r->rflush();
813: #
814: return;
815: }
816:
817: ##############################################
818: ##############################################
819: sub CreateMainMenu {
820: #
821: # Define menu data
822: my @reports = ({ internal_name => 'problem_statistics',
823: name => &mt('Overall Problem Statistics'),
824: short_description =>
825: &mt('Student performance statistics on all problems.'),
826: },
827: { internal_name => 'problem_analysis',
828: name => &mt('Detailed Problem Analysis'),
829: short_description =>
830: &mt('Detailed statistics and graphs of student performance on problems.'),
831: },
832: { internal_name => 'submissiontime_analysis',
833: name => &mt('Submission Time Plots'),
834: short_description =>
835: &mt('Display and analysis of submission times on assessments.'),
836: },
837: { internal_name => 'student_submission_reports',
838: name => &mt('Student Submission Reports'),
839: short_description =>
840: &mt('Prepare reports of student submissions.'),
841: },
842: { internal_name => 'survey_reports',
843: name => &mt('Survey Reports'),
844: short_description =>
845: &mt('Prepare reports on survey results.'),
846: },
847: { internal_name => 'correct_problems_plot',
848: name => &mt('Correct Problems Plot'),
849: short_description =>
850: &mt('Display a histogram of student performance in the course.'),
851: },
852: # { internal_name => 'student_assessment',
853: # name => &mt('Problem Status Chart'),
854: # short_description =>
855: # &mt('Brief view of each students performance in course.'),
856: # },
857: # 'percentage' => 'Correct-problems Plot',
858: # 'activitylog' => 'Activity Log',
859: );
860: #
861: # Create the menu
862: my $Str;
863: $Str .= '<h2>'.&mt('Please select a report to generate').'</h2>';
864: foreach my $reportdata (@reports) {
865: $Str .=' <h3><a href="/adm/statistics?reportSelected='.
866: $reportdata->{'internal_name'}.'" >'.
867: $reportdata->{'name'}."</a></h3>\n";
868: $Str .= ' '.(' 'x8).$reportdata->{'short_description'}.
869: "\n";
870: }
871: $Str .="</dl>\n";
872: #
873: return $Str;
874: }
875:
876: ##############################################
877: ##############################################
878: sub handler {
879: my $r=shift;
880: my $c = $r->connection();
881: #
882: # Check for overloading
883: my $loaderror=&Apache::lonnet::overloaderror($r);
884: if ($loaderror) { return $loaderror; }
885: $loaderror=
886: &Apache::lonnet::overloaderror($r,
887: $ENV{'course.'.$ENV{'request.course.id'}.'.home'});
888: if ($loaderror) { return $loaderror; }
889: #
890: # Check for access
891: if (! &Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
892: $ENV{'user.error.msg'}=
893: $r->uri.":vgr:0:0:Cannot view grades for complete course";
894: if (! &Apache::lonnet::allowed('vgr',
895: $ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'})) {
896: $ENV{'user.error.msg'}=
897: $r->uri.":vgr:0:0:Cannot view grades with given role";
898: return HTTP_NOT_ACCEPTABLE;
899: }
900: }
901: #
902: # Send the header
903: &Apache::loncommon::no_cache($r);
904: &Apache::loncommon::content_type($r,'text/html');
905: $r->send_http_header;
906: if ($r->header_only) { return OK; }
907: #
908: # Extract form elements from query string
909: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
910: ['sort','reportSelected',
911: 'SelectedStudent']);
912: #
913: # Give the LON-CAPA page header
914: my $style = <<ENDSTYLE;
915: <style type="text/css">
916: ul.sub_studentans { list-style-type: none }
917: ul.sub_correctans { list-style-type: none }
918: tr.even { background-color: \#CCCCCC }
919: td.essay { border: 1px solid gray; }
920: </style>
921: ENDSTYLE
922: my $html=&Apache::lonxml::xmlbegin();
923: $r->print($html.'<head><title>'.
924: &mt('Course Statistics and Charts').
925: '</title>'.$style.
926: "</head>\n".
927: &Apache::loncommon::bodytag('Course Statistics and Charts'));
928: $r->rflush();
929: #
930: # Either print out a menu for them or send them to a report
931: &Apache::lonhtmlcommon::clear_breadcrumbs();
932: &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/statistics',
933: title=>'Statistics',
934: text =>'Statistics',
935: faq=>139,
936: bug=>'Statistics and Charts'});
937: if (! exists($ENV{'form.reportSelected'}) ||
938: $ENV{'form.reportSelected'} eq '') {
939: $r->print(&Apache::lonhtmlcommon::breadcrumbs
940: (undef,&mt('Statistics Main Page')).
941: &CreateMainMenu());
942: } else {
943: #
944: if (! &Apache::lonmysql::verify_sql_connection()) {
945: my $serveradmin = $r->dir_config('lonAdmEMail');
946: $r->print('<h2><font color="Red">'.
947: &mt('Unable to connect to database!').
948: '</font></h2>');
949: $r->print('<p>'.
950: &mt('Please notify the server administrator ').
951: '<b>'.$serveradmin.'</b></p>');
952: $r->print('<p>'.
953: &mt('Course Statistics and Charts cannot be '.
954: 'retrieved until the database is restarted. '.
955: 'Your data is intact but cannot be displayed '.
956: 'at this time.').'</p>');
957: $r->print('</body></html>');
958: return;
959: }
960: #
961: # Clean out the caches
962: if (exists($ENV{'form.ClearCache'})) {
963: &Apache::loncoursedata::delete_caches($ENV{'requres.course.id'});
964: }
965: #
966: # Begin form output
967: $r->print('<form name="Statistics" ');
968: $r->print('method="post" action="/adm/statistics">');
969: $r->rflush();
970: #
971: my $GoToPage = $ENV{'form.reportSelected'};
972: #
973: $r->print('<input type="hidden" name="reportSelected" value="'.
974: $GoToPage.'">');
975: if($GoToPage eq 'activitylog') {
976: # &Apache::lonproblemstatistics::Activity();
977: } elsif($GoToPage eq 'problem_statistics') {
978: &Apache::lonhtmlcommon::add_breadcrumb
979: ({href=>'/adm/statistics?reportselected=problem_statistics',
980: text=>'Overall Problem Statistics'});
981: &Apache::lonproblemstatistics::BuildProblemStatisticsPage($r,$c);
982: } elsif($GoToPage eq 'problem_analysis') {
983: &Apache::lonhtmlcommon::add_breadcrumb
984: ({href=>'/adm/statistics?reportselected=problem_analysis',
985: text=>'Detailed Problem Analysis'});
986: &Apache::lonproblemanalysis::BuildProblemAnalysisPage($r,$c);
987: } elsif($GoToPage eq 'submissiontime_analysis') {
988: &Apache::lonhtmlcommon::add_breadcrumb
989: ({href=>
990: '/adm/statistics?reportselected=submissiontime_analysis',
991: text=>'Submission Time Plots'});
992: &Apache::lonsubmissiontimeanalysis::BuildSubmissionTimePage($r,$c);
993: } elsif($GoToPage eq 'student_submission_reports') {
994: &Apache::lonhtmlcommon::add_breadcrumb
995: ({href=>
996: '/adm/statistics?reportselected=student_submission_reports',
997: text=>'Student Submission Reports'});
998: &Apache::lonstudentsubmissions::BuildStudentSubmissionsPage($r,$c);
999: } elsif($GoToPage eq 'survey_reports') {
1000: &Apache::lonhtmlcommon::add_breadcrumb
1001: ({href=>
1002: '/adm/statistics?reportselected=survey_reports',
1003: text=>'Survey Reports'});
1004: &Apache::lonsurveyreports::BuildSurveyReportsPage($r,$c);
1005: } elsif($GoToPage eq 'correct_problems_plot') {
1006: &Apache::lonhtmlcommon::add_breadcrumb
1007: ({href=>'/adm/statistics?reportselected=correct_problems_plot',
1008: text=>'Correct Problems Plot'});
1009: &Apache::loncorrectproblemplot::BuildCorrectProblemsPage($r,$c);
1010: } elsif($GoToPage eq 'student_assessment') {
1011: &Apache::lonhtmlcommon::clear_breadcrumbs();
1012: &Apache::lonhtmlcommon::add_breadcrumb
1013: ({href=>'/adm/statistics?reportselected=student_assessment',
1014: text=>'Chart'});
1015: &Apache::lonstudentassessment::BuildStudentAssessmentPage($r,$c);
1016: }
1017: #
1018: $r->print("</form>\n");
1019: }
1020: $r->print("</body>\n</html>\n");
1021: $r->rflush();
1022: #
1023: return OK;
1024: }
1025:
1026: 1;
1027:
1028: #######################################################
1029: #######################################################
1030:
1031: =pod
1032:
1033: =back
1034:
1035: =cut
1036:
1037: #######################################################
1038: #######################################################
1039:
1040: __END__
1041:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>