Annotation of loncom/interface/lonstatistics.pm, revision 1.64
1.1 albertel 1: # The LearningOnline Network with CAPA
2: #
1.64 ! matthew 3: # $Id: lonstatistics.pm,v 1.63 2003/03/03 19:17:51 matthew Exp $
1.1 albertel 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
1.14 minaeibi 28: #
1.1 albertel 29: ###
30:
1.59 matthew 31: =pod
32:
33: =head1 NAME
34:
35: lonstatistics
36:
37: =head1 SYNOPSIS
38:
39: Main handler for statistics and chart.
40:
41: =head1 PACKAGES USED
42:
1.60 matthew 43: use strict;
44: use Apache::Constants qw(:common :http);
45: use Apache::lonnet();
46: use Apache::lonhomework;
47: use Apache::loncommon;
48: use Apache::loncoursedata;
49: use Apache::lonhtmlcommon;
50: use Apache::lonproblemanalysis;
51: use Apache::lonproblemstatistics;
52: use Apache::lonstudentassessment;
53: use Apache::lonpercentage;
54: use GDBM_File;
1.59 matthew 55:
56: =over 4
57:
58: =cut
59:
1.55 minaeibi 60: package Apache::lonstatistics;
1.1 albertel 61:
1.30 stredwic 62: use strict;
1.1 albertel 63: use Apache::Constants qw(:common :http);
1.61 matthew 64: use vars qw(
65: @FullClasslist
66: @Students
67: @Sections
68: @SelectedSections
69: %StudentData
70: @StudentDataOrder
71: @SelectedStudentData
72: $top_map
73: @Sequences
74: @SelectedMaps
75: @Assessments);
76:
1.1 albertel 77: use Apache::lonnet();
78: use Apache::lonhomework;
1.12 minaeibi 79: use Apache::loncommon;
1.29 stredwic 80: use Apache::loncoursedata;
81: use Apache::lonhtmlcommon;
1.61 matthew 82: use Apache::lonproblemanalysis();
83: use Apache::lonproblemstatistics();
84: use Apache::lonstudentassessment();
1.49 stredwic 85: use Apache::lonpercentage;
1.1 albertel 86: use GDBM_File;
87:
1.60 matthew 88:
89: #######################################################
90: #######################################################
91:
92: =pod
93:
94: =item Package Variables
95:
96: =item @FullClasslist The full classlist
97:
98: =item @Students The students we are concerned with for this invocation
99:
100: =item @Sections The sections available in this class
101:
102: =item $curr_student The student currently being examined
103:
104: =item $prev_student The student previous in the classlist
105:
106: =item $next_student The student next in the classlist
107:
108: =over
109:
110: =cut
111:
112: #######################################################
113: #######################################################
114: #
115: # Classlist variables
116: #
1.59 matthew 117: my $curr_student;
118: my $prev_student;
119: my $next_student;
120:
121: #######################################################
122: #######################################################
123:
124: =pod
125:
126: =item &clear_classlist_variables()
127:
128: undef the following package variables:
129:
130: =over
131:
1.60 matthew 132: =item @FullClasslist
133:
134: =item @Students
1.59 matthew 135:
1.60 matthew 136: =item @Sections
1.59 matthew 137:
1.60 matthew 138: =item @SelectedSections
1.59 matthew 139:
1.61 matthew 140: =item %StudentData
141:
142: =item @StudentDataOrder
143:
144: =item @SelectedStudentData
145:
1.60 matthew 146: =item $curr_student
1.59 matthew 147:
1.60 matthew 148: =item $prev_student
1.59 matthew 149:
1.60 matthew 150: =item $next_student
1.59 matthew 151:
152: =back
153:
154: =cut
155:
156: #######################################################
157: #######################################################
158: sub clear_classlist_variables {
159: undef(@FullClasslist);
160: undef(@Students);
161: undef(@Sections);
1.60 matthew 162: undef(@SelectedSections);
1.61 matthew 163: undef(%StudentData);
164: undef(@SelectedStudentData);
1.59 matthew 165: undef($curr_student);
166: undef($prev_student);
167: undef($next_student);
168: }
169:
170: #######################################################
171: #######################################################
172:
173: =pod
174:
175: =item &PrepareClasslist()
176:
177: Build up the classlist information. The classlist information is kept in
178: the following package variables:
179:
180: =over
181:
1.60 matthew 182: =item @FullClasslist
183:
184: =item @Students
1.59 matthew 185:
1.60 matthew 186: =item @Sections
1.59 matthew 187:
1.60 matthew 188: =item @SelectedSections
1.59 matthew 189:
1.61 matthew 190: =item %StudentData
191:
192: =item @SelectedStudentData
193:
1.60 matthew 194: =item $curr_student
1.59 matthew 195:
1.60 matthew 196: =item $prev_student
1.59 matthew 197:
1.60 matthew 198: =item $next_student
1.59 matthew 199:
200: =back
201:
202: $curr_student, $prev_student, and $next_student may not be defined, depending
203: upon the calling context.
204:
205: =cut
206:
207: #######################################################
208: #######################################################
209: sub PrepareClasslist {
210: my $r = shift;
211: my %Sections;
212: &clear_classlist_variables();
213: #
214: # Retrieve the classlist
215: my $cid = $ENV{'request.course.id'};
216: my $cdom = $ENV{'course.'.$cid.'.domain'};
217: my $cnum = $ENV{'course.'.$cid.'.num'};
218: my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cid,
219: $cdom,$cnum);
1.60 matthew 220: if (exists($ENV{'form.Section'})) {
1.59 matthew 221: if (ref($ENV{'form.Section'})) {
1.61 matthew 222: @SelectedSections = @{$ENV{'form.Section'}};
223: } elsif ($ENV{'form.Section'} !~ /^\s*$/) {
224: @SelectedSections = ($ENV{'form.Section'});
225: }
226: }
227: @SelectedSections = ('all') if (! @SelectedSections);
228: foreach (@SelectedSections) {
229: if ($_ eq 'all') {
230: @SelectedSections = ('all');
1.59 matthew 231: }
232: }
1.61 matthew 233: #
234: # Set up %StudentData
235: @StudentDataOrder = qw/fullname username domain id section status/;
236: foreach my $field (@StudentDataOrder) {
237: $StudentData{$field}->{'title'} = $field;
1.63 matthew 238: $StudentData{$field}->{'base_width'} = length($field);
1.61 matthew 239: $StudentData{$field}->{'width'} =
240: $StudentData{$field}->{'base_width'};
241: }
242:
1.59 matthew 243: #
244: # Process the classlist
245: while (my ($student,$student_data) = each (%$classlist)) {
246: my $studenthash = ();
247: for (my $i=0; $i< scalar(@$field_names);$i++) {
1.61 matthew 248: my $field = $field_names->[$i];
249: # Store the data
250: $studenthash->{$field}=$student_data->[$i];
251: # Keep track of the width of the fields
252: next if (! exists($StudentData{$field}));
1.63 matthew 253: my $length = length($student_data->[$i]);
1.61 matthew 254: if ($StudentData{$field}->{'width'} < $length) {
255: $StudentData{$field}->{'width'} = $length;
256: }
1.59 matthew 257: }
258: push (@FullClasslist,$studenthash);
259: #
260: # Build up a list of sections
261: my $section = $studenthash->{'section'};
1.60 matthew 262: if (! defined($section) || $section =~/^\s*$/ || $section == -1) {
263: $studenthash->{'section'} = 'none';
264: $section = $studenthash->{'section'};
265: }
1.59 matthew 266: $Sections{$section}++;
267: #
268: # Only put in the list those students we are interested in
1.60 matthew 269: foreach my $sect (@SelectedSections) {
1.61 matthew 270: if (($sect eq 'all') || ($section eq $sect)) {
1.60 matthew 271: push (@Students,$studenthash);
272: last;
273: }
1.59 matthew 274: }
275: }
276: #
277: # Put the consolidated section data in the right place
1.60 matthew 278: @Sections = sort {$a cmp $b} keys(%Sections);
1.61 matthew 279: unshift(@Sections,'all'); # Put 'all' at the front of the list
1.59 matthew 280: #
281: # Sort the Students
282: my $sortby = 'fullname';
1.60 matthew 283: $sortby = $ENV{'form.sort'} if (exists($ENV{'form.sort'}));
284: my @TmpStudents = sort { $a->{$sortby} cmp $b->{$sortby} ||
285: $a->{'fullname'} cmp $b->{'fullname'} } @Students;
286: @Students = @TmpStudents;
1.59 matthew 287: #
288: # Now deal with that current student thing....
289: if (exists($ENV{'form.StudentAssessmentStudent'})) {
290: my ($current_uname,$current_dom) =
291: split(':',$ENV{'form.StudentAssessmentStudent'});
292: my $i;
293: for ($i = 0; $i<=$#Students; $i++) {
294: next if (($Students[$i]->{'username'} ne $current_uname) ||
295: ($Students[$i]->{'domain'} ne $current_dom));
1.60 matthew 296: $curr_student = $Students[$i];
1.59 matthew 297: last; # If we get here, we have our student.
298: }
299: if ($i == 0) {
300: $prev_student = 'none';
301: } else {
302: $prev_student = $Students[$i-1];
303: }
304: if ($i == $#Students) {
305: $next_student = 'none';
306: } else {
307: $next_student = $Students[$i+1];
308: }
309: }
1.61 matthew 310: #
311: if (exists($ENV{'form.StudentData'})) {
312: if (ref($ENV{'form.StudentData'}) eq 'ARRAY') {
313: @SelectedStudentData = @{$ENV{'form.StudentData'}};
314: } else {
315: @SelectedStudentData = ($ENV{'form.StudentData'});
316: }
317: } else {
318: @SelectedStudentData = ('fullname');
319: }
320: foreach (@SelectedStudentData) {
321: if ($_ eq 'all') {
322: @SelectedStudentData = ('all');
323: last;
324: }
325: }
326: #
327: return;
328: }
329:
330: #######################################################
331: #######################################################
332:
333: =pod
334:
335: =item ¤t_student()
336:
337: Returns a pointer to a hash containing data about the currently
338: selected student.
339:
340: =cut
341:
342: #######################################################
343: #######################################################
344: sub current_student {
345: if (defined($curr_student)) {
346: return $curr_student;
347: } else {
348: return 'All Students';
349: }
350: }
351:
352: #######################################################
353: #######################################################
354:
355: =pod
356:
357: =item &previous_student()
358:
359: Returns a pointer to a hash containing data about the student prior
360: in the list of students. Or something.
361:
362: =cut
363:
364: #######################################################
365: #######################################################
366: sub previous_student {
367: if (defined($prev_student)) {
368: return $prev_student;
369: } else {
370: return 'No Student Selected';
371: }
1.59 matthew 372: }
373:
374: #######################################################
375: #######################################################
1.61 matthew 376:
377: =pod
378:
379: =item &next_student()
380:
381: Returns a pointer to a hash containing data about the next student
382: to be viewed.
383:
384: =cut
385:
386: #######################################################
387: #######################################################
388: sub next_student {
389: if (defined($next_student)) {
390: return $next_student;
391: } else {
392: return 'No Student Selected';
393: }
394: }
1.60 matthew 395:
396: #######################################################
397: #######################################################
398:
399: =pod
400:
401: =item &clear_sequence_variables()
402:
403: =cut
404:
405: #######################################################
406: #######################################################
407: sub clear_sequence_variables {
408: undef($top_map);
409: undef(@Sequences);
410: undef(@Assessments);
411: }
412:
413: #######################################################
414: #######################################################
415:
416: =pod
417:
1.61 matthew 418: =item &SetSelectedMaps($elementname)
419:
420: Sets the @SelectedMaps array from $ENV{'form.'.$elementname};
421:
422: =cut
423:
424: #######################################################
425: #######################################################
426: sub SetSelectedMaps {
427: my $elementname = shift;
428: if (exists($ENV{'form.'.$elementname})) {
429: if (ref($ENV{'form.'.$elementname})) {
430: @SelectedMaps = @{$ENV{'form.'.$elementname}};
431: } else {
432: @SelectedMaps = ($ENV{'form.'.$elementname});
433: }
434: } else {
435: @SelectedMaps = ('all');
436: }
1.64 ! matthew 437: }
! 438:
! 439:
! 440: #######################################################
! 441: #######################################################
! 442:
! 443: =pod
! 444:
! 445: =item &Sequences_with_Assess()
! 446:
! 447: Returns an array containing the subset of @Sequences which contain
! 448: assessments.
! 449:
! 450: =cut
! 451:
! 452: #######################################################
! 453: #######################################################
! 454: sub Sequences_with_Assess {
! 455: my @Sequences_to_Show;
! 456: foreach my $map_symb (@SelectedMaps) {
! 457: foreach my $sequence (@Sequences) {
! 458: next if ($sequence->{'symb'} ne $map_symb && $map_symb ne 'all');
! 459: next if ($sequence->{'num_assess'} < 1);
! 460: push (@Sequences_to_Show,$sequence);
! 461: }
! 462: }
! 463: return @Sequences_to_Show;
1.61 matthew 464: }
465:
466: #######################################################
467: #######################################################
468:
469: =pod
470:
1.60 matthew 471: =item &PrepareCourseData($r)
472:
473: =cut
474:
475: #######################################################
476: #######################################################
477: sub PrepareCourseData {
478: my ($r) = @_;
479: &clear_sequence_variables();
1.61 matthew 480: my ($top,$sequences,$assessments) =
481: &Apache::loncoursedata::get_sequence_assessment_data();
1.60 matthew 482: if (! defined($top) || ! ref($top)) {
483: # There has been an error, better report it
484: &Apache::lonnet::logthis('top is undefined');
485: return;
486: }
487: $top_map = $top if (ref($top));
488: @Sequences = @{$sequences} if (ref($sequences) eq 'ARRAY');
1.61 matthew 489: @Assessments = @{$assessments} if (ref($assessments) eq 'ARRAY');
490: #
491: # Compute column widths
492: foreach my $seq (@Sequences) {
1.63 matthew 493: my $name_length = length($seq->{'title'});
1.61 matthew 494: my $num_parts = $seq->{'num_assess_parts'};
495: #
496: # The number of columns needed for the summation text:
497: # " 1/5" = 1+3 columns, " 10/99" = 1+5 columns
1.63 matthew 498: my $sum_length = 1+1+2*(length($num_parts));
1.61 matthew 499: my $num_col = $num_parts+$sum_length;
500: if ($num_col < $name_length) {
501: $num_col = $name_length;
502: }
503: $seq->{'base_width'} = $name_length;
504: $seq->{'width'} = $num_col;
505: }
506: return;
507: }
508:
509: #######################################################
510: #######################################################
1.60 matthew 511:
512: =pod
513:
1.61 matthew 514: =item &log_sequence($sequence,$recursive,$padding)
515:
516: Write data about the sequence to a logfile. If $recursive is not
517: undef the data is written recursively. $padding is used for recursive
518: calls.
519:
520: =cut
521:
522: #######################################################
523: #######################################################
524: sub log_sequence {
525: my ($seq,$recursive,$padding) = @_;
526: $padding = '' if (! defined($padding));
527: if (ref($seq) ne 'HASH') {
528: &Apache::lonnet::logthis('log_sequence passed bad sequnce');
529: return;
530: }
531: &Apache::lonnet::logthis($padding.'sequence '.$seq->{'title'});
532: while (my($key,$value) = each(%$seq)) {
533: next if ($key eq 'contents');
534: if (ref($value) eq 'ARRAY') {
535: for (my $i=0;$i< scalar(@$value);$i++) {
536: &Apache::lonnet::logthis($padding.$key.'['.$i.']='.
537: $value->[$i]);
538: }
539: } else {
540: &Apache::lonnet::logthis($padding.$key.'='.$value);
541: }
542: }
543: if (defined($recursive)) {
544: &Apache::lonnet::logthis($padding.'-'x20);
545: &Apache::lonnet::logthis($padding.'contains:');
546: foreach my $item (@{$seq->{'contents'}}) {
547: if ($item->{'type'} eq 'container') {
548: &log_sequence($item,$recursive,$padding.' ');
549: } else {
550: &Apache::lonnet::logthis($padding.'title = '.$item->{'title'});
551: while (my($key,$value) = each(%$item)) {
552: next if ($key eq 'title');
553: if (ref($value) eq 'ARRAY') {
554: for (my $i=0;$i< scalar(@$value);$i++) {
555: &Apache::lonnet::logthis($padding.$key.'['.$i.']='.
556: $value->[$i]);
557: }
558: } else {
559: &Apache::lonnet::logthis($padding.$key.'='.$value);
560: }
561: }
562: }
1.60 matthew 563: }
1.61 matthew 564: &Apache::lonnet::logthis($padding.'end contents of '.$seq->{'title'});
565: &Apache::lonnet::logthis($padding.'-'x20);
1.60 matthew 566: }
1.61 matthew 567: return;
568: }
569:
570: ##############################################
571: ##############################################
572:
573: =pod
574:
575: =item &StudentDataSelect($elementname,$status,$numvisible,$selected)
576:
577: Returns html for a selection box allowing the user to choose one (or more)
578: of the fields of student data available (fullname, username, id, section, etc)
579:
580: =over 4
581:
582: =item $elementname The name of the HTML form element
583:
584: =item $status 'multiple' or 'single' selection box
585:
586: =item $numvisible The number of options to be visible
587:
588: =back
1.60 matthew 589:
590: =cut
591:
1.61 matthew 592: ##############################################
593: ##############################################
594: sub StudentDataSelect {
595: my ($elementname,$status,$numvisible)=@_;
596: if ($numvisible < 1) {
597: return;
598: }
599: #
600: # Build the form element
601: my $Str = "\n";
602: $Str .= '<select name="'.$elementname.'" ';
603: if ($status ne 'single') {
604: $Str .= 'multiple="true" ';
605: }
606: $Str .= 'size="'.$numvisible.'" >'."\n";
607: #
608: # Deal with 'all'
609: $Str .= ' <option value="all" ';
610: foreach (@SelectedStudentData) {
611: if ($_ eq 'all') {
612: $Str .= 'selected ';
613: last;
614: }
615: }
616: $Str .= ">all</option>\n";
617: #
618: # Loop through the student data fields
619: foreach my $item (@StudentDataOrder) {
620: $Str .= ' <option value="'.$item.'" ';
621: foreach (@SelectedStudentData) {
622: if ($item eq $_ ) {
623: $Str .= 'selected ';
624: last;
625: }
626: }
627: $Str .= '>'.$item."</option>\n";
628: }
629: $Str .= "</select>\n";
630: return $Str;
1.60 matthew 631: }
632:
633: ##############################################
634: ##############################################
635:
636: =pod
637:
1.61 matthew 638: =item &MapSelect($elementname,$status,$numvisible,$restriction)
1.60 matthew 639:
640: Returns html for a selection box allowing the user to choose one (or more)
641: of the sequences in the course. The values of the sequences are the symbs.
642: If the top sequence is selected, the value 'top' will result.
643:
644: =over 4
645:
646: =item $elementname The name of the HTML form element
647:
648: =item $status 'multiple' or 'single' selection box
649:
650: =item $numvisible The number of options to be visible
651:
652: =item $restriction Code reference to subroutine which returns true or
653: false. The code must expect a reference to a sequence data structure.
654:
655: =back
656:
657: =cut
658:
659: ##############################################
660: ##############################################
661: sub MapSelect {
1.61 matthew 662: my ($elementname,$status,$numvisible,$restriction)=@_;
1.60 matthew 663: if ($numvisible < 1) {
664: return;
665: }
666: #
667: # Set up array of selected items
1.61 matthew 668: &SetSelectedMaps($elementname);
1.60 matthew 669: #
670: # Set up the restriction call
671: if (! defined($restriction)) {
672: $restriction = sub { 1; };
673: }
674: #
675: # Build the form element
676: my $Str = "\n";
677: $Str .= '<select name="'.$elementname.'" ';
678: if ($status ne 'single') {
679: $Str .= 'multiple="true" ';
680: }
681: $Str .= 'size="'.$numvisible.'" >'."\n";
682: #
1.61 matthew 683: # Deal with 'all'
684: foreach (@SelectedMaps) {
685: if ($_ eq 'all') {
686: @SelectedMaps = ('all');
687: last;
688: }
689: }
690: #
691: # Put in option for 'all'
692: $Str .= ' <option value="all" ';
693: foreach (@SelectedMaps) {
694: if ($_ eq 'all') {
695: $Str .= 'selected ';
696: last;
697: }
698: }
699: $Str .= ">all</option>\n";
700: #
1.60 matthew 701: # Loop through the sequences
1.61 matthew 702: foreach my $seq (@Sequences) {
703: next if (! $restriction->($seq));
704: $Str .= ' <option value="'.$seq->{'symb'}.'" ';
705: foreach (@SelectedMaps) {
706: if ($seq->{'symb'} eq $_) {
1.60 matthew 707: $Str .= 'selected ';
708: last;
709: }
710: }
1.61 matthew 711: $Str .= '>'.$seq->{'title'}."</option>\n";
1.60 matthew 712: }
713: $Str .= "</select>\n";
714: return $Str;
715: }
716:
717: ##############################################
718: ##############################################
719:
720: =pod
721:
722: =item &SectionSelect($elementname,$status,$numvisible)
723:
724: Returns html for a selection box allowing the user to choose one (or more)
725: of the sections in the course.
726:
727: =over 4
728:
729: =item $elementname The name of the HTML form element
730:
731: =item $status 'multiple' or 'single' selection box
732:
733: =item $numvisible The number of options to be visible
734:
735: =item $selected Array ref to the names of the already selected sections.
736: If undef, $ENV{'form.'.$elementname} is used.
737: If $ENV{'form.'.$elementname} is also empty, none will be selected.
738:
739: =item $restriction Code reference to subroutine which returns true or
740: false. The code must expect a reference to a sequence data structure.
741:
742: =back
743:
744: =cut
745:
746: ##############################################
747: ##############################################
748: sub SectionSelect {
749: my ($elementname,$status,$numvisible)=@_;
750: if ($numvisible < 1) {
751: return;
752: }
753: #
754: # Build the form element
755: my $Str = "\n";
756: $Str .= '<select name="'.$elementname.'" ';
757: if ($status ne 'single') {
758: $Str .= 'multiple="true" ';
759: }
760: $Str .= 'size="'.$numvisible.'" >'."\n";
761: #
762: # Loop through the sequences
763: foreach my $s (@Sections) {
764: $Str .= ' <option value="'.$s.'" ';
765: foreach (@SelectedSections) {
1.61 matthew 766: if ($s eq $_) {
1.60 matthew 767: $Str .= 'selected ';
768: last;
769: }
770: }
771: $Str .= '>'.$s."</option>\n";
772: }
773: $Str .= "</select>\n";
774: return $Str;
775: }
776:
777: ##############################################
778: ##############################################
1.27 stredwic 779:
780: sub CheckFormElement {
781: my ($cache, $ENVName, $cacheName, $default)=@_;
782:
783: if(defined($ENV{'form.'.$ENVName})) {
784: $cache->{$cacheName} = $ENV{'form.'.$ENVName};
785: } elsif(!defined($cache->{$cacheName})) {
786: $cache->{$cacheName} = $default;
1.60 matthew 787: } else {
788: $ENV{'form.'.$ENVName} = $cache->{$cacheName};
1.27 stredwic 789: }
790: return;
791: }
792:
793: sub ProcessFormData{
1.29 stredwic 794: my ($cache)=@_;
1.27 stredwic 795:
1.29 stredwic 796: $cache->{'reportKey'} = 'false';
1.27 stredwic 797:
1.29 stredwic 798: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.60 matthew 799: ['download',
1.34 stredwic 800: 'reportSelected',
1.41 stredwic 801: 'StudentAssessmentStudent',
802: 'ProblemStatisticsSort']);
1.56 matthew 803: &CheckFormElement($cache, 'DownloadAll', 'DownloadAll', 'false');
804: if ($cache->{'DownloadAll'} ne 'false') {
805: # Clean the hell out of that cache!
806: # We cannot untie the hash at this scope (stupid libgd :( )
807: # So, remove every single key. What a waste of time....
808: # Of course, if you are doing this you are probably resigned
809: # to waiting a while.
810: &Apache::lonnet::logthis("Cleaning out the cache file");
811: while (my ($key,undef)=each(%$cache)) {
812: next if ($key eq 'DownloadAll');
813: delete($cache->{$key});
814: }
815: }
1.29 stredwic 816: &CheckFormElement($cache, 'Status', 'Status', 'Active');
817: &CheckFormElement($cache, 'postdata', 'reportSelected', 'Class list');
818: &CheckFormElement($cache, 'reportSelected', 'reportSelected',
819: 'Class list');
1.30 stredwic 820: $cache->{'reportSelected'} =
821: &Apache::lonnet::unescape($cache->{'reportSelected'});
1.29 stredwic 822: &CheckFormElement($cache, 'sort', 'sort', 'fullname');
823: &CheckFormElement($cache, 'download', 'download', 'false');
1.44 stredwic 824: &CheckFormElement($cache, 'StatisticsMaps',
825: 'StatisticsMaps', 'All Maps');
1.49 stredwic 826: &CheckFormElement($cache, 'StatisticsProblemSelect',
827: 'StatisticsProblemSelect', 'All Problems');
828: &CheckFormElement($cache, 'StatisticsPartSelect',
829: 'StatisticsPartSelect', 'All Parts');
1.44 stredwic 830: if(defined($ENV{'form.Section'})) {
831: my @sectionsSelected = (ref($ENV{'form.Section'}) ?
832: @{$ENV{'form.Section'}} :
833: ($ENV{'form.Section'}));
834: $cache->{'sectionsSelected'} = join(':', @sectionsSelected);
835: } elsif(!defined($cache->{'sectionsSelected'})) {
836: $cache->{'sectionsSelected'} = $cache->{'sectionList'};
837: }
1.29 stredwic 838:
1.38 stredwic 839: # student assessment
1.29 stredwic 840: if(defined($ENV{'form.CreateStudentAssessment'}) ||
841: defined($ENV{'form.NextStudent'}) ||
842: defined($ENV{'form.PreviousStudent'})) {
843: $cache->{'reportSelected'} = 'Student Assessment';
844: }
845: if(defined($ENV{'form.NextStudent'})) {
846: $cache->{'StudentAssessmentMove'} = 'next';
847: } elsif(defined($ENV{'form.PreviousStudent'})) {
848: $cache->{'StudentAssessmentMove'} = 'previous';
849: } else {
850: $cache->{'StudentAssessmentMove'} = 'selected';
851: }
852: &CheckFormElement($cache, 'StudentAssessmentStudent',
1.30 stredwic 853: 'StudentAssessmentStudent', 'All Students');
854: $cache->{'StudentAssessmentStudent'} =
855: &Apache::lonnet::unescape($cache->{'StudentAssessmentStudent'});
1.34 stredwic 856: &CheckFormElement($cache, 'DefaultColumns', 'DefaultColumns', 'false');
1.29 stredwic 857:
1.38 stredwic 858: # Problem analysis
859: &CheckFormElement($cache, 'Interval', 'Interval', '1');
860:
861: # ProblemStatistcs
862: &CheckFormElement($cache, 'DisplayCSVFormat',
863: 'DisplayFormat', 'Display Table Format');
864: &CheckFormElement($cache, 'ProblemStatisticsAscend',
865: 'ProblemStatisticsAscend', 'Ascending');
1.41 stredwic 866: &CheckFormElement($cache, 'ProblemStatisticsSort',
867: 'ProblemStatisticsSort', 'Homework Sets Order');
1.49 stredwic 868: &CheckFormElement($cache, 'DisplayLegend', 'DisplayLegend',
869: 'Hide Legend');
1.45 stredwic 870: &CheckFormElement($cache, 'SortProblems', 'SortProblems',
871: 'Sort Within Sequence');
1.38 stredwic 872:
873: # Search only form elements
1.34 stredwic 874: my @headingColumns=();
875: my @sequenceColumns=();
876: my $foundColumn = 0;
877: if(defined($ENV{'form.ReselectColumns'})) {
878: my @reselected = (ref($ENV{'form.ReselectColumns'}) ?
879: @{$ENV{'form.ReselectColumns'}}
880: : ($ENV{'form.ReselectColumns'}));
881: foreach (@reselected) {
882: if(/HeadingColumn/) {
883: push(@headingColumns, $_);
884: $foundColumn = 1;
885: } elsif(/SequenceColumn/) {
886: push(@sequenceColumns, $_);
887: $foundColumn = 1;
888: }
889: }
890: }
891:
1.37 stredwic 892: $cache->{'reportKey'} = 'false';
893: if($cache->{'reportSelected'} eq 'Analyze') {
894: $cache->{'reportKey'} = 'Analyze';
1.38 stredwic 895: } elsif($cache->{'reportSelected'} eq 'DoDiffGraph') {
896: $cache->{'reportKey'} = 'DoDiffGraph';
897: } elsif($cache->{'reportSelected'} eq 'PercentWrongGraph') {
898: $cache->{'reportKey'} = 'PercentWrongGraph';
899: }
900:
901: if(defined($ENV{'form.DoDiffGraph'})) {
902: $cache->{'reportSelected'} = 'DoDiffGraph';
903: $cache->{'reportKey'} = 'DoDiffGraph';
904: } elsif(defined($ENV{'form.PercentWrongGraph'})) {
905: $cache->{'reportSelected'} = 'PercentWrongGraph';
906: $cache->{'reportKey'} = 'PercentWrongGraph';
1.37 stredwic 907: }
908:
1.29 stredwic 909: foreach (keys(%ENV)) {
1.37 stredwic 910: if(/form\.Analyze/) {
911: $cache->{'reportSelected'} = 'Analyze';
912: $cache->{'reportKey'} = 'Analyze';
913: my $data;
914: (undef, $data)=split(':::', $_);
915: $cache->{'AnalyzeInfo'}=$data;
1.34 stredwic 916: } elsif(/form\.HeadingColumn/) {
917: my $value = $_;
918: $value =~ s/form\.//;
919: push(@headingColumns, $value);
920: $foundColumn=1;
921: } elsif(/form\.SequenceColumn/) {
922: my $value = $_;
923: $value =~ s/form\.//;
924: push(@sequenceColumns, $value);
925: $foundColumn=1;
1.27 stredwic 926: }
1.29 stredwic 927: }
1.27 stredwic 928:
1.34 stredwic 929: if($foundColumn) {
930: $cache->{'HeadingsFound'} = join(':', @headingColumns);
931: $cache->{'SequencesFound'} = join(':', @sequenceColumns);;
932: }
933: if(!defined($cache->{'HeadingsFound'}) ||
934: $cache->{'DefaultColumns'} ne 'false') {
935: $cache->{'HeadingsFound'}='HeadingColumnFull Name';
936: }
937: if(!defined($cache->{'SequencesFound'}) ||
938: $cache->{'DefaultColumns'} ne 'false') {
939: $cache->{'SequencesFound'}='All Sequences';
940: }
941: $cache->{'DefaultColumns'} = 'false';
942:
1.29 stredwic 943: return;
1.27 stredwic 944: }
945:
1.61 matthew 946: ##################################################
947: ##################################################
948:
1.27 stredwic 949: =pod
950:
951: =item &SortStudents()
952:
953: Determines which students to display and in which order. Which are
954: displayed are determined by their status(active/expired). The order
955: is determined by the sort button pressed (default to username). The
956: type of sorting is username, lastname, or section.
957:
958: =over 4
959:
960: Input: $students, $CacheData
961:
962: $students: A array pointer to a list of students (username:domain)
963:
964: $CacheData: A pointer to the hash tied to the cached data
965:
966: Output: \@order
967:
968: @order: An ordered list of students (username:domain)
969:
970: =back
971:
972: =cut
973:
974: sub SortStudents {
1.29 stredwic 975: my ($cache)=@_;
1.27 stredwic 976:
1.29 stredwic 977: my @students = split(':::',$cache->{'NamesOfStudents'});
1.27 stredwic 978: my @sorted1Students=();
1.29 stredwic 979: foreach (@students) {
980: if($cache->{'Status'} eq 'Any' ||
981: $cache->{$_.':Status'} eq $cache->{'Status'}) {
982: push(@sorted1Students, $_);
983: }
1.1 albertel 984: }
1.27 stredwic 985:
1.29 stredwic 986: my $sortBy = '';
987: if(defined($cache->{'sort'})) {
988: $sortBy = ':'.$cache->{'sort'};
1.54 matthew 989: } else {
990: $sortBy = ':fullname';
1.27 stredwic 991: }
1.54 matthew 992: my @order = sort { lc($cache->{$a.$sortBy}) cmp lc($cache->{$b.$sortBy}) ||
993: lc($cache->{$a.':fullname'}) cmp lc($cache->{$b.':fullname'}) }
1.29 stredwic 994: @sorted1Students;
1.27 stredwic 995:
996: return \@order;
997: }
998:
1.32 stredwic 999: =pod
1000:
1001: =item &SpaceColumns()
1002:
1003: Determines the width of all the columns in the chart. It is based on
1004: the max of the data for that column and its header.
1005:
1006: =over 4
1007:
1008: Input: $students, $studentInformation, $headings, $ChartDB
1009:
1010: $students: An array pointer to a list of students (username:domain)
1011:
1012: $studentInformatin: The type of data for the student information. It is
1013: used as part of the key in $CacheData.
1014:
1015: $headings: The name of the student information columns.
1016:
1017: $ChartDB: The name of the cache database which is opened for read/write.
1018:
1019: Output: None - All data stored in cache.
1020:
1021: =back
1022:
1023: =cut
1024:
1025: sub SpaceColumns {
1026: my ($students,$studentInformation,$headings,$cache)=@_;
1027:
1028: # Initialize Lengths
1029: for(my $index=0; $index<(scalar @$headings); $index++) {
1030: my @titleLength=split(//,$headings->[$index]);
1031: $cache->{$studentInformation->[$index].':columnWidth'}=
1032: scalar @titleLength;
1033: }
1034:
1035: foreach my $name (@$students) {
1036: foreach (@$studentInformation) {
1037: my @dataLength=split(//,$cache->{$name.':'.$_});
1038: my $length=(scalar @dataLength);
1039: if($length > $cache->{$_.':columnWidth'}) {
1040: $cache->{$_.':columnWidth'}=$length;
1041: }
1042: }
1043: }
1044:
1045: return;
1046: }
1047:
1.27 stredwic 1048: sub PrepareData {
1.38 stredwic 1049: my ($c, $cacheDB, $studentInformation, $headings,$r)=@_;
1.27 stredwic 1050:
1051: # Test for access to the cache data
1052: my $courseID=$ENV{'request.course.id'};
1053: my $isRecalculate=0;
1.29 stredwic 1054: if(defined($ENV{'form.Recalculate'})) {
1.27 stredwic 1055: $isRecalculate=1;
1056: }
1057:
1.55 minaeibi 1058: my $isCached = &Apache::loncoursedata::TestCacheData($cacheDB,
1.29 stredwic 1059: $isRecalculate);
1.27 stredwic 1060: if($isCached < 0) {
1061: return "Unable to tie hash to db file.";
1062: }
1063:
1064: # Download class list information if not using cached data
1065: my %cache;
1.38 stredwic 1066: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT(),0640)) {
1.29 stredwic 1067: return "Unable to tie hash to db file.";
1068: }
1069:
1.50 stredwic 1070: # if(!$isCached) {
1.27 stredwic 1071: my $processTopResourceMapReturn=
1.50 stredwic 1072: &Apache::loncoursedata::ProcessTopResourceMap(\%cache, $c);
1.27 stredwic 1073: if($processTopResourceMapReturn ne 'OK') {
1074: untie(%cache);
1075: return $processTopResourceMapReturn;
1076: }
1.50 stredwic 1077: # }
1.27 stredwic 1078:
1.29 stredwic 1079: if($c->aborted()) {
1080: untie(%cache);
1081: return 'aborted';
1082: }
1.27 stredwic 1083:
1.29 stredwic 1084: my $classlist=&Apache::loncoursedata::DownloadClasslist($courseID,
1085: $cache{'ClasslistTimestamp'},
1086: $c);
1087: foreach (keys(%$classlist)) {
1088: if(/^(con_lost|error|no_such_host)/i) {
1.27 stredwic 1089: untie(%cache);
1090: return "Error getting student data.";
1091: }
1.29 stredwic 1092: }
1.27 stredwic 1093:
1.29 stredwic 1094: if($c->aborted()) {
1095: untie(%cache);
1096: return 'aborted';
1097: }
1098:
1099: # Active is a temporary solution, remember to change
1100: Apache::loncoursedata::ProcessClasslist(\%cache,$classlist,$courseID,$c);
1101: if($c->aborted()) {
1102: untie(%cache);
1103: return 'aborted';
1104: }
1.27 stredwic 1105:
1.29 stredwic 1106: &ProcessFormData(\%cache);
1107: my $students = &SortStudents(\%cache);
1.32 stredwic 1108: &SpaceColumns($students, $studentInformation, $headings, \%cache);
1109: $cache{'updateTime:columnWidth'}=24;
1.27 stredwic 1110:
1.48 stredwic 1111: my $download = $cache{'download'};
1112: my $downloadAll = $cache{'DownloadAll'};
1113: my @allStudents=();
1114: if($download ne 'false') {
1.29 stredwic 1115: $cache{'download'} = 'false';
1.48 stredwic 1116: } elsif($downloadAll ne 'false') {
1117: $cache{'DownloadAll'} = 'false';
1118: if($downloadAll eq 'sorted') {
1119: @allStudents = @$students;
1120: } else {
1121: @allStudents = split(':::', $cache{'NamesOfStudents'});
1122: }
1123: }
1124:
1125: untie(%cache);
1126:
1127: if($download ne 'false') {
1128: my @who = ($download);
1.55 minaeibi 1129: if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'false',
1130: $cacheDB, 'true',
1.41 stredwic 1131: 'false', $courseID,
1132: $r, $c) ne 'OK') {
1133: return 'Stop at download individual';
1134: }
1.48 stredwic 1135: } elsif($downloadAll ne 'false') {
1.55 minaeibi 1136: if(&Apache::loncoursedata::DownloadStudentCourseData(\@allStudents,
1137: 'false',
1138: $cacheDB, 'true',
1.41 stredwic 1139: 'true', $courseID,
1140: $r, $c) ne 'OK') {
1141: return 'Stop at download all';
1.27 stredwic 1142: }
1.29 stredwic 1143: }
1144:
1145: return ('OK', $students);
1.27 stredwic 1146: }
1147:
1.60 matthew 1148: sub DisplayClasslist {
1149: my ($r)=@_;
1150: #
1151: my @Fields = ('fullname','username','domain','id','section');
1152: #
1153: my $Str='';
1154: $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";
1155: $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";
1156: foreach my $field (@Fields) {
1157: $Str .= '<th><a href="/adm/statistics?sort='.$field.'">'.$field.
1158: '</a></th>';
1159: }
1160: $Str .= '</tr>'."\n";
1161: #
1162: my $alternate = 0;
1163: foreach my $student (@Students) {
1164: my $sname = $student->{'username'}.':'.$student->{'domain'};
1165: if($alternate) {
1166: $Str .= '<tr bgcolor="#ffffe6">';
1167: } else {
1168: $Str .= '<tr bgcolor="#ffffc6">';
1169: }
1170: $alternate = ($alternate + 1) % 2;
1171: #
1172: foreach my $field (@Fields) {
1173: $Str .= '<td>';
1174: if ($field eq 'fullname') {
1175: $Str .= '<a href="/adm/statistics?reportSelected=';
1176: $Str .= &Apache::lonnet::escape('Student Assessment');
1177: $Str .= '&StudentAssessmentStudent=';
1.61 matthew 1178: $Str .= &Apache::lonnet::escape($sname).'">';
1.60 matthew 1179: $Str .= $student->{$field}.' ';
1180: $Str .= '</a>';
1181: } else {
1182: $Str .= $student->{$field};
1183: }
1184: $Str .= '</td>';
1185: }
1186: $Str .= "</tr>\n";
1187: }
1188: $Str .= '</table></td></tr></table>'."\n";
1189: #
1190: $r->print($Str);
1191: $r->rflush();
1192: #
1193: return;
1194: }
1195:
1.29 stredwic 1196: sub BuildClasslist {
1.39 stredwic 1197: my ($cacheDB,$students,$studentInformation,$headings,$r)=@_;
1.29 stredwic 1198:
1199: my %cache;
1.38 stredwic 1200: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
1.29 stredwic 1201: return '<html><body>Unable to tie database.</body></html>';
1.1 albertel 1202: }
1203:
1.55 minaeibi 1204: # my $Ptr = '';
1205: # $Ptr .= '<table border="0"><tbody>';
1206: # $Ptr .= '<tr><td align="right"><b>Select Sections</b>';
1207: # $Ptr .= '</td>'."\n";
1208: # $Ptr .= '<td align="left">'."\n";
1209: # my @sectionsSelected = split(':',$cache{'sectionsSelected'});
1210: # my @sections = split(':',$cache{'sectionList'});
1211: # $Ptr .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections,
1212: # \@sectionsSelected,
1213: # 'Statistics');
1214: # $Ptr .= '</td></tr></table><br>';
1215: # $r->print($Ptr);
1216: # $r->rflush();
1217: # my %mySections = ();
1218: # foreach (@sections) { $mySections{$_} = 'True'; }
1219: # $r->print("<br>$cache{'sectionsSelected'}<br>");
1220:
1.29 stredwic 1221: my $Str='';
1222: $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";
1223: $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";
1224:
1225: my $displayString = '<td align="left"><a href="/adm/statistics?';
1226: $displayString .= 'sort=LINKDATA">DISPLAYDATA </a></td>'."\n";
1.55 minaeibi 1227: $Str .= &Apache::lonhtmlcommon::CreateHeadings(\%cache,
1.39 stredwic 1228: $studentInformation,
1.32 stredwic 1229: $headings, $displayString);
1.29 stredwic 1230: $Str .= '</tr>'."\n";
1.39 stredwic 1231:
1.29 stredwic 1232: my $alternate=0;
1233: foreach (@$students) {
1.55 minaeibi 1234: # if ($mySections{$cache{$_.':'.'section'}} ne 'True') {next;}
1.29 stredwic 1235: my ($username, $domain) = split(':', $_);
1236: if($alternate) {
1.32 stredwic 1237: $Str .= '<tr bgcolor="#ffffe6">';
1.29 stredwic 1238: } else {
1.32 stredwic 1239: $Str .= '<tr bgcolor="#ffffc6">';
1.29 stredwic 1240: }
1241: $alternate = ($alternate + 1) % 2;
1242: foreach my $data (@$studentInformation) {
1.32 stredwic 1243: $Str .= '<td>';
1.29 stredwic 1244: if($data eq 'fullname') {
1245: $Str .= '<a href="/adm/statistics?reportSelected=';
1.30 stredwic 1246: $Str .= &Apache::lonnet::escape('Student Assessment');
1247: $Str .= '&StudentAssessmentStudent=';
1248: $Str .= &Apache::lonnet::escape($cache{$_.':'.$data}).'">';
1.32 stredwic 1249: $Str .= $cache{$_.':'.$data}.' ';
1.29 stredwic 1250: $Str .= '</a>';
1.32 stredwic 1251: } elsif($data eq 'updateTime') {
1252: $Str .= '<a href="/adm/statistics?reportSelected=';
1253: $Str .= &Apache::lonnet::escape('Class list');
1254: $Str .= '&download='.$_.'">';
1255: $Str .= $cache{$_.':'.$data}.' ';
1256: $Str .= ' </a>';
1257: } else {
1258: $Str .= $cache{$_.':'.$data}.' ';
1.29 stredwic 1259: }
1260:
1.32 stredwic 1261: $Str .= '</td>'."\n";
1.29 stredwic 1262: }
1.1 albertel 1263: }
1.29 stredwic 1264:
1.32 stredwic 1265: $Str .= '</tr>'."\n";
1.29 stredwic 1266: $Str .= '</table></td></tr></table>'."\n";
1.39 stredwic 1267: $r->print($Str);
1268: $r->rflush();
1.29 stredwic 1269:
1.27 stredwic 1270: untie(%cache);
1.1 albertel 1271:
1.39 stredwic 1272: return;
1.1 albertel 1273: }
1274:
1.33 stredwic 1275: sub CreateMainMenu {
1276: my ($status, $reports)=@_;
1277:
1278: my $Str = '';
1279:
1280: $Str .= '<table border="0"><tbody><tr>'."\n";
1.63 matthew 1281: $Str .= '<td></td>'."\n";
1.57 minaeibi 1282: $Str .= '<td align="center"><b>Select a Report</b></td>'."\n";
1283: $Str .= '<td align="center"><b>Student Status</b></td></tr>'."\n";
1.33 stredwic 1284: $Str .= '<tr>'."\n";
1285: $Str .= '<td align="center"><input type="submit" name="Refresh" ';
1.63 matthew 1286: $Str .= 'value="Update Display" /></td>'."\n";
1.33 stredwic 1287: $Str .= '<td align="center">';
1288: $Str .= '<select name="reportSelected" onchange="document.';
1289: $Str .= 'Statistics.submit()">'."\n";
1290:
1291: foreach (sort(keys(%$reports))) {
1292: next if($_ eq 'reportSelected');
1293: $Str .= '<option name="'.$_.'"';
1294: if($reports->{'reportSelected'} eq $reports->{$_}) {
1295: $Str .= ' selected=""';
1296: }
1297: $Str .= '>'.$reports->{$_}.'</option>'."\n";
1298: }
1299: $Str .= '</select></td>'."\n";
1300:
1301: $Str .= '<td align="center">';
1302: $Str .= &Apache::lonhtmlcommon::StatusOptions($status, 'Statistics');
1303: $Str .= '</td>'."\n";
1304:
1305: $Str .= '</tr></tbody></table>'."\n";
1306: $Str .= '<hr>'."\n";
1307:
1308: return $Str;
1309: }
1310:
1.29 stredwic 1311: sub BuildStatistics {
1312: my ($r)=@_;
1313:
1314: my $c = $r->connection;
1.32 stredwic 1315: my @studentInformation=('fullname','section','id','domain','username',
1316: 'updateTime');
1317: my @headings=('Full Name', 'Section', 'PID', 'Domain', 'User Name',
1318: 'Last Updated');
1.55 minaeibi 1319: my $spacing = ' ';
1.52 minaeibi 1320:
1.29 stredwic 1321: my %reports = ('classlist' => 'Class list',
1322: 'problem_statistics' => 'Problem Statistics',
1323: 'student_assessment' => 'Student Assessment',
1.58 minaeibi 1324: 'percentage' => 'Correct-problems Plot',
1.40 minaeibi 1325: # 'activitylog' => 'Activity Log',
1.29 stredwic 1326: 'reportSelected' => 'Class list');
1.27 stredwic 1327:
1328: my %cache;
1.29 stredwic 1329: my $courseID=$ENV{'request.course.id'};
1330: my $cacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
1331: "_$ENV{'user.domain'}_$courseID\_statistics.db";
1332:
1.47 www 1333: $r->print(&Apache::lonhtmlcommon::Title('Course Statistics and Charts'));
1.41 stredwic 1334:
1.55 minaeibi 1335: my ($returnValue, $students) = &PrepareData($c, $cacheDB,
1336: \@studentInformation,
1.38 stredwic 1337: \@headings,$r);
1.29 stredwic 1338: if($returnValue ne 'OK') {
1.41 stredwic 1339: $r->print($returnValue."\n".'</body></html>');
1.29 stredwic 1340: return OK;
1341: }
1.41 stredwic 1342: if(!$c->aborted()) {
1.55 minaeibi 1343: &Apache::loncoursedata::CheckForResidualDownload($cacheDB,
1.41 stredwic 1344: 'true', 'true',
1345: $courseID,
1346: $r, $c);
1347: }
1.29 stredwic 1348:
1349: my $GoToPage;
1.38 stredwic 1350: if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
1.29 stredwic 1351: $GoToPage = $cache{'reportSelected'};
1352: $reports{'reportSelected'} = $cache{'reportSelected'};
1.55 minaeibi 1353: if(defined($cache{'reportKey'}) &&
1354: !exists($reports{$cache{'reportKey'}}) &&
1.37 stredwic 1355: $cache{'reportKey'} ne 'false') {
1356: $reports{$cache{'reportKey'}} = $cache{'reportSelected'};
1357: }
1.29 stredwic 1358:
1359: if(defined($cache{'OptionResponses'})) {
1.46 stredwic 1360: $reports{'problem_analysis'} = 'Option Response Analysis';
1.29 stredwic 1361: }
1362:
1363: $r->print('<form name="Statistics" ');
1364: $r->print('method="post" action="/adm/statistics">');
1.33 stredwic 1365: $r->print(&CreateMainMenu($cache{'Status'}, \%reports));
1.39 stredwic 1366: $r->rflush();
1.29 stredwic 1367: untie(%cache);
1368: } else {
1.27 stredwic 1369: $r->print('<html><body>Unable to tie database.</body></html>');
1.29 stredwic 1370: return OK;
1371: }
1372:
1373: if($GoToPage eq 'Activity Log') {
1.30 stredwic 1374: &Apache::lonproblemstatistics::Activity();
1.29 stredwic 1375: } elsif($GoToPage eq 'Problem Statistics') {
1.55 minaeibi 1376: &Apache::lonproblemstatistics::BuildProblemStatisticsPage($cacheDB,
1377: $students,
1378: $courseID,
1.36 minaeibi 1379: $c,$r);
1.46 stredwic 1380: } elsif($GoToPage eq 'Option Response Analysis') {
1.39 stredwic 1381: &Apache::lonproblemanalysis::BuildProblemAnalysisPage($cacheDB, $r);
1.29 stredwic 1382: } elsif($GoToPage eq 'Student Assessment') {
1.62 matthew 1383: &Apache::lonstudentassessment::BuildStudentAssessmentPage($r, $c);
1.29 stredwic 1384: } elsif($GoToPage eq 'Analyze') {
1.55 minaeibi 1385: &Apache::lonproblemanalysis::BuildAnalyzePage($cacheDB, $students,
1.39 stredwic 1386: $courseID, $r);
1.40 minaeibi 1387: } elsif($GoToPage eq 'DoDiffGraph' || $GoToPage eq 'PercentWrongGraph') {
1.43 stredwic 1388: my $courseDescription = $ENV{'course.'.$courseID.'.description'};
1389: $courseDescription =~ s/\ /"_"/eg;
1390: &Apache::lonproblemstatistics::BuildGraphicChart($GoToPage, $cacheDB,
1391: $courseDescription,
1.45 stredwic 1392: $students, $courseID,
1393: $r, $c);
1.29 stredwic 1394: } elsif($GoToPage eq 'Class list') {
1.60 matthew 1395: &DisplayClasslist($r);
1396: # &BuildClasslist($cacheDB, $students, \@studentInformation,
1397: # \@headings, $r);
1.58 minaeibi 1398: } elsif($GoToPage eq 'Correct-problems Plot') {
1.49 stredwic 1399: &Apache::lonpercentage::BuildPercentageGraph($cacheDB, $students,
1400: $courseID, $c, $r);
1.27 stredwic 1401: }
1402:
1403: $r->print('</form>'."\n");
1.29 stredwic 1404: $r->print("\n".'</body>'."\n".'</html>');
1405: $r->rflush();
1.27 stredwic 1406:
1.29 stredwic 1407: return OK;
1.27 stredwic 1408: }
1.1 albertel 1409:
1410: # ================================================================ Main Handler
1411:
1412: sub handler {
1.31 minaeibi 1413: my $r=shift;
1.34 stredwic 1414:
1415: # $jr = $r;
1.51 www 1416:
1417: my $loaderror=&Apache::lonnet::overloaderror($r);
1418: if ($loaderror) { return $loaderror; }
1419: $loaderror=
1420: &Apache::lonnet::overloaderror($r,
1421: $ENV{'course.'.$ENV{'request.course.id'}.'.home'});
1422: if ($loaderror) { return $loaderror; }
1.1 albertel 1423:
1.27 stredwic 1424: unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
1425: $ENV{'user.error.msg'}=
1426: $r->uri.":vgr:0:0:Cannot view grades for complete course";
1.55 minaeibi 1427: return HTTP_NOT_ACCEPTABLE;
1.27 stredwic 1428: }
1429:
1430: # Set document type for header only
1431: if($r->header_only) {
1432: if ($ENV{'browser.mathml'}) {
1433: $r->content_type('text/xml');
1434: } else {
1435: $r->content_type('text/html');
1436: }
1437: &Apache::loncommon::no_cache($r);
1438: $r->send_http_header;
1439: return OK;
1440: }
1441:
1442: unless($ENV{'request.course.fn'}) {
1.1 albertel 1443: my $requrl=$r->uri;
1.27 stredwic 1444: $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";
1.55 minaeibi 1445: return HTTP_NOT_ACCEPTABLE;
1.27 stredwic 1446: }
1.1 albertel 1447:
1.27 stredwic 1448: $r->content_type('text/html');
1449: $r->send_http_header;
1.1 albertel 1450:
1.60 matthew 1451: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.61 matthew 1452: ['sort',
1453: 'StudentAssessmentStudent']);
1.60 matthew 1454:
1.59 matthew 1455: &PrepareClasslist($r);
1.60 matthew 1456:
1457: &PrepareCourseData($r);
1.59 matthew 1458:
1.29 stredwic 1459: &BuildStatistics($r);
1.27 stredwic 1460:
1461: return OK;
1.1 albertel 1462: }
1463: 1;
1.59 matthew 1464:
1465: =pod
1466:
1467: =back
1468:
1469: =cut
1470:
1.1 albertel 1471: __END__
1.31 minaeibi 1472:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>