Annotation of loncom/interface/lonstatistics.pm, revision 1.67
1.1 albertel 1: # The LearningOnline Network with CAPA
2: #
1.67 ! matthew 3: # $Id: lonstatistics.pm,v 1.66 2003/04/18 15:50:55 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;
1.66 matthew 54: use Apache::lonmysql;
1.59 matthew 55: =over 4
56:
57: =cut
58:
1.55 minaeibi 59: package Apache::lonstatistics;
1.1 albertel 60:
1.30 stredwic 61: use strict;
1.1 albertel 62: use Apache::Constants qw(:common :http);
1.61 matthew 63: use vars qw(
64: @FullClasslist
65: @Students
66: @Sections
67: @SelectedSections
68: %StudentData
69: @StudentDataOrder
70: @SelectedStudentData
71: $top_map
72: @Sequences
73: @SelectedMaps
74: @Assessments);
75:
1.1 albertel 76: use Apache::lonnet();
77: use Apache::lonhomework;
1.12 minaeibi 78: use Apache::loncommon;
1.29 stredwic 79: use Apache::loncoursedata;
80: use Apache::lonhtmlcommon;
1.61 matthew 81: use Apache::lonproblemanalysis();
82: use Apache::lonproblemstatistics();
83: use Apache::lonstudentassessment();
1.49 stredwic 84: use Apache::lonpercentage;
1.66 matthew 85: use Apache::lonmysql;
1.65 matthew 86: use Time::HiRes;
1.60 matthew 87:
88: #######################################################
89: #######################################################
90:
91: =pod
92:
93: =item Package Variables
94:
95: =item @FullClasslist The full classlist
96:
97: =item @Students The students we are concerned with for this invocation
98:
99: =item @Sections The sections available in this class
100:
101: =item $curr_student The student currently being examined
102:
103: =item $prev_student The student previous in the classlist
104:
105: =item $next_student The student next in the classlist
106:
107: =over
108:
109: =cut
110:
111: #######################################################
112: #######################################################
113: #
114: # Classlist variables
115: #
1.59 matthew 116: my $curr_student;
117: my $prev_student;
118: my $next_student;
119:
120: #######################################################
121: #######################################################
122:
123: =pod
124:
125: =item &clear_classlist_variables()
126:
127: undef the following package variables:
128:
129: =over
130:
1.60 matthew 131: =item @FullClasslist
132:
133: =item @Students
1.59 matthew 134:
1.60 matthew 135: =item @Sections
1.59 matthew 136:
1.60 matthew 137: =item @SelectedSections
1.59 matthew 138:
1.61 matthew 139: =item %StudentData
140:
141: =item @StudentDataOrder
142:
143: =item @SelectedStudentData
144:
1.60 matthew 145: =item $curr_student
1.59 matthew 146:
1.60 matthew 147: =item $prev_student
1.59 matthew 148:
1.60 matthew 149: =item $next_student
1.59 matthew 150:
151: =back
152:
153: =cut
154:
155: #######################################################
156: #######################################################
157: sub clear_classlist_variables {
158: undef(@FullClasslist);
159: undef(@Students);
160: undef(@Sections);
1.60 matthew 161: undef(@SelectedSections);
1.61 matthew 162: undef(%StudentData);
163: undef(@SelectedStudentData);
1.59 matthew 164: undef($curr_student);
165: undef($prev_student);
166: undef($next_student);
167: }
168:
169: #######################################################
170: #######################################################
171:
172: =pod
173:
174: =item &PrepareClasslist()
175:
176: Build up the classlist information. The classlist information is kept in
177: the following package variables:
178:
179: =over
180:
1.60 matthew 181: =item @FullClasslist
182:
183: =item @Students
1.59 matthew 184:
1.60 matthew 185: =item @Sections
1.59 matthew 186:
1.60 matthew 187: =item @SelectedSections
1.59 matthew 188:
1.61 matthew 189: =item %StudentData
190:
191: =item @SelectedStudentData
192:
1.60 matthew 193: =item $curr_student
1.59 matthew 194:
1.60 matthew 195: =item $prev_student
1.59 matthew 196:
1.60 matthew 197: =item $next_student
1.59 matthew 198:
199: =back
200:
201: $curr_student, $prev_student, and $next_student may not be defined, depending
202: upon the calling context.
203:
204: =cut
205:
206: #######################################################
207: #######################################################
208: sub PrepareClasslist {
209: my $r = shift;
210: my %Sections;
211: &clear_classlist_variables();
212: #
213: # Retrieve the classlist
214: my $cid = $ENV{'request.course.id'};
215: my $cdom = $ENV{'course.'.$cid.'.domain'};
216: my $cnum = $ENV{'course.'.$cid.'.num'};
217: my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cid,
218: $cdom,$cnum);
1.60 matthew 219: if (exists($ENV{'form.Section'})) {
1.59 matthew 220: if (ref($ENV{'form.Section'})) {
1.61 matthew 221: @SelectedSections = @{$ENV{'form.Section'}};
222: } elsif ($ENV{'form.Section'} !~ /^\s*$/) {
223: @SelectedSections = ($ENV{'form.Section'});
224: }
225: }
226: @SelectedSections = ('all') if (! @SelectedSections);
227: foreach (@SelectedSections) {
228: if ($_ eq 'all') {
229: @SelectedSections = ('all');
1.59 matthew 230: }
231: }
1.61 matthew 232: #
233: # Set up %StudentData
234: @StudentDataOrder = qw/fullname username domain id section status/;
235: foreach my $field (@StudentDataOrder) {
236: $StudentData{$field}->{'title'} = $field;
1.63 matthew 237: $StudentData{$field}->{'base_width'} = length($field);
1.61 matthew 238: $StudentData{$field}->{'width'} =
239: $StudentData{$field}->{'base_width'};
240: }
241:
1.59 matthew 242: #
243: # Process the classlist
244: while (my ($student,$student_data) = each (%$classlist)) {
245: my $studenthash = ();
246: for (my $i=0; $i< scalar(@$field_names);$i++) {
1.61 matthew 247: my $field = $field_names->[$i];
248: # Store the data
249: $studenthash->{$field}=$student_data->[$i];
250: # Keep track of the width of the fields
251: next if (! exists($StudentData{$field}));
1.63 matthew 252: my $length = length($student_data->[$i]);
1.61 matthew 253: if ($StudentData{$field}->{'width'} < $length) {
254: $StudentData{$field}->{'width'} = $length;
255: }
1.59 matthew 256: }
257: push (@FullClasslist,$studenthash);
258: #
259: # Build up a list of sections
260: my $section = $studenthash->{'section'};
1.60 matthew 261: if (! defined($section) || $section =~/^\s*$/ || $section == -1) {
262: $studenthash->{'section'} = 'none';
263: $section = $studenthash->{'section'};
264: }
1.59 matthew 265: $Sections{$section}++;
266: #
267: # Only put in the list those students we are interested in
1.60 matthew 268: foreach my $sect (@SelectedSections) {
1.61 matthew 269: if (($sect eq 'all') || ($section eq $sect)) {
1.60 matthew 270: push (@Students,$studenthash);
271: last;
272: }
1.59 matthew 273: }
274: }
275: #
276: # Put the consolidated section data in the right place
1.60 matthew 277: @Sections = sort {$a cmp $b} keys(%Sections);
1.61 matthew 278: unshift(@Sections,'all'); # Put 'all' at the front of the list
1.59 matthew 279: #
280: # Sort the Students
281: my $sortby = 'fullname';
1.60 matthew 282: $sortby = $ENV{'form.sort'} if (exists($ENV{'form.sort'}));
283: my @TmpStudents = sort { $a->{$sortby} cmp $b->{$sortby} ||
284: $a->{'fullname'} cmp $b->{'fullname'} } @Students;
285: @Students = @TmpStudents;
1.59 matthew 286: #
287: # Now deal with that current student thing....
288: if (exists($ENV{'form.StudentAssessmentStudent'})) {
289: my ($current_uname,$current_dom) =
290: split(':',$ENV{'form.StudentAssessmentStudent'});
291: my $i;
292: for ($i = 0; $i<=$#Students; $i++) {
293: next if (($Students[$i]->{'username'} ne $current_uname) ||
294: ($Students[$i]->{'domain'} ne $current_dom));
1.60 matthew 295: $curr_student = $Students[$i];
1.59 matthew 296: last; # If we get here, we have our student.
297: }
298: if ($i == 0) {
299: $prev_student = 'none';
300: } else {
301: $prev_student = $Students[$i-1];
302: }
303: if ($i == $#Students) {
304: $next_student = 'none';
305: } else {
306: $next_student = $Students[$i+1];
307: }
308: }
1.61 matthew 309: #
310: if (exists($ENV{'form.StudentData'})) {
311: if (ref($ENV{'form.StudentData'}) eq 'ARRAY') {
312: @SelectedStudentData = @{$ENV{'form.StudentData'}};
313: } else {
314: @SelectedStudentData = ($ENV{'form.StudentData'});
315: }
316: } else {
317: @SelectedStudentData = ('fullname');
318: }
319: foreach (@SelectedStudentData) {
320: if ($_ eq 'all') {
321: @SelectedStudentData = ('all');
322: last;
323: }
324: }
325: #
326: return;
327: }
328:
329: #######################################################
330: #######################################################
331:
332: =pod
333:
334: =item ¤t_student()
335:
336: Returns a pointer to a hash containing data about the currently
337: selected student.
338:
339: =cut
340:
341: #######################################################
342: #######################################################
343: sub current_student {
344: if (defined($curr_student)) {
345: return $curr_student;
346: } else {
347: return 'All Students';
348: }
349: }
350:
351: #######################################################
352: #######################################################
353:
354: =pod
355:
356: =item &previous_student()
357:
358: Returns a pointer to a hash containing data about the student prior
359: in the list of students. Or something.
360:
361: =cut
362:
363: #######################################################
364: #######################################################
365: sub previous_student {
366: if (defined($prev_student)) {
367: return $prev_student;
368: } else {
369: return 'No Student Selected';
370: }
1.59 matthew 371: }
372:
373: #######################################################
374: #######################################################
1.61 matthew 375:
376: =pod
377:
378: =item &next_student()
379:
380: Returns a pointer to a hash containing data about the next student
381: to be viewed.
382:
383: =cut
384:
385: #######################################################
386: #######################################################
387: sub next_student {
388: if (defined($next_student)) {
389: return $next_student;
390: } else {
391: return 'No Student Selected';
392: }
393: }
1.60 matthew 394:
395: #######################################################
396: #######################################################
397:
398: =pod
399:
400: =item &clear_sequence_variables()
401:
402: =cut
403:
404: #######################################################
405: #######################################################
406: sub clear_sequence_variables {
407: undef($top_map);
408: undef(@Sequences);
409: undef(@Assessments);
410: }
411:
412: #######################################################
413: #######################################################
414:
415: =pod
416:
1.61 matthew 417: =item &SetSelectedMaps($elementname)
418:
419: Sets the @SelectedMaps array from $ENV{'form.'.$elementname};
420:
421: =cut
422:
423: #######################################################
424: #######################################################
425: sub SetSelectedMaps {
426: my $elementname = shift;
427: if (exists($ENV{'form.'.$elementname})) {
428: if (ref($ENV{'form.'.$elementname})) {
429: @SelectedMaps = @{$ENV{'form.'.$elementname}};
430: } else {
431: @SelectedMaps = ($ENV{'form.'.$elementname});
432: }
433: } else {
434: @SelectedMaps = ('all');
435: }
1.64 matthew 436: }
437:
438:
439: #######################################################
440: #######################################################
441:
442: =pod
443:
444: =item &Sequences_with_Assess()
445:
446: Returns an array containing the subset of @Sequences which contain
447: assessments.
448:
449: =cut
450:
451: #######################################################
452: #######################################################
453: sub Sequences_with_Assess {
454: my @Sequences_to_Show;
455: foreach my $map_symb (@SelectedMaps) {
456: foreach my $sequence (@Sequences) {
457: next if ($sequence->{'symb'} ne $map_symb && $map_symb ne 'all');
458: next if ($sequence->{'num_assess'} < 1);
459: push (@Sequences_to_Show,$sequence);
460: }
461: }
462: return @Sequences_to_Show;
1.61 matthew 463: }
464:
465: #######################################################
466: #######################################################
467:
468: =pod
469:
1.60 matthew 470: =item &PrepareCourseData($r)
471:
472: =cut
473:
474: #######################################################
475: #######################################################
476: sub PrepareCourseData {
477: my ($r) = @_;
478: &clear_sequence_variables();
1.61 matthew 479: my ($top,$sequences,$assessments) =
480: &Apache::loncoursedata::get_sequence_assessment_data();
1.60 matthew 481: if (! defined($top) || ! ref($top)) {
482: # There has been an error, better report it
483: &Apache::lonnet::logthis('top is undefined');
484: return;
485: }
486: $top_map = $top if (ref($top));
487: @Sequences = @{$sequences} if (ref($sequences) eq 'ARRAY');
1.61 matthew 488: @Assessments = @{$assessments} if (ref($assessments) eq 'ARRAY');
489: #
490: # Compute column widths
491: foreach my $seq (@Sequences) {
1.63 matthew 492: my $name_length = length($seq->{'title'});
1.61 matthew 493: my $num_parts = $seq->{'num_assess_parts'};
494: #
495: # The number of columns needed for the summation text:
496: # " 1/5" = 1+3 columns, " 10/99" = 1+5 columns
1.63 matthew 497: my $sum_length = 1+1+2*(length($num_parts));
1.61 matthew 498: my $num_col = $num_parts+$sum_length;
499: if ($num_col < $name_length) {
500: $num_col = $name_length;
501: }
502: $seq->{'base_width'} = $name_length;
503: $seq->{'width'} = $num_col;
504: }
505: return;
506: }
507:
508: #######################################################
509: #######################################################
1.60 matthew 510:
511: =pod
512:
1.61 matthew 513: =item &log_sequence($sequence,$recursive,$padding)
514:
515: Write data about the sequence to a logfile. If $recursive is not
516: undef the data is written recursively. $padding is used for recursive
517: calls.
518:
519: =cut
520:
521: #######################################################
522: #######################################################
523: sub log_sequence {
524: my ($seq,$recursive,$padding) = @_;
525: $padding = '' if (! defined($padding));
526: if (ref($seq) ne 'HASH') {
527: &Apache::lonnet::logthis('log_sequence passed bad sequnce');
528: return;
529: }
530: &Apache::lonnet::logthis($padding.'sequence '.$seq->{'title'});
531: while (my($key,$value) = each(%$seq)) {
532: next if ($key eq 'contents');
533: if (ref($value) eq 'ARRAY') {
534: for (my $i=0;$i< scalar(@$value);$i++) {
535: &Apache::lonnet::logthis($padding.$key.'['.$i.']='.
536: $value->[$i]);
537: }
538: } else {
539: &Apache::lonnet::logthis($padding.$key.'='.$value);
540: }
541: }
542: if (defined($recursive)) {
543: &Apache::lonnet::logthis($padding.'-'x20);
544: &Apache::lonnet::logthis($padding.'contains:');
545: foreach my $item (@{$seq->{'contents'}}) {
546: if ($item->{'type'} eq 'container') {
547: &log_sequence($item,$recursive,$padding.' ');
548: } else {
549: &Apache::lonnet::logthis($padding.'title = '.$item->{'title'});
550: while (my($key,$value) = each(%$item)) {
551: next if ($key eq 'title');
552: if (ref($value) eq 'ARRAY') {
553: for (my $i=0;$i< scalar(@$value);$i++) {
554: &Apache::lonnet::logthis($padding.$key.'['.$i.']='.
555: $value->[$i]);
556: }
557: } else {
558: &Apache::lonnet::logthis($padding.$key.'='.$value);
559: }
560: }
561: }
1.60 matthew 562: }
1.61 matthew 563: &Apache::lonnet::logthis($padding.'end contents of '.$seq->{'title'});
564: &Apache::lonnet::logthis($padding.'-'x20);
1.60 matthew 565: }
1.61 matthew 566: return;
567: }
568:
569: ##############################################
570: ##############################################
571:
572: =pod
573:
574: =item &StudentDataSelect($elementname,$status,$numvisible,$selected)
575:
576: Returns html for a selection box allowing the user to choose one (or more)
577: of the fields of student data available (fullname, username, id, section, etc)
578:
579: =over 4
580:
581: =item $elementname The name of the HTML form element
582:
583: =item $status 'multiple' or 'single' selection box
584:
585: =item $numvisible The number of options to be visible
586:
587: =back
1.60 matthew 588:
589: =cut
590:
1.61 matthew 591: ##############################################
592: ##############################################
593: sub StudentDataSelect {
594: my ($elementname,$status,$numvisible)=@_;
595: if ($numvisible < 1) {
596: return;
597: }
598: #
599: # Build the form element
600: my $Str = "\n";
601: $Str .= '<select name="'.$elementname.'" ';
602: if ($status ne 'single') {
603: $Str .= 'multiple="true" ';
604: }
605: $Str .= 'size="'.$numvisible.'" >'."\n";
606: #
607: # Deal with 'all'
608: $Str .= ' <option value="all" ';
609: foreach (@SelectedStudentData) {
610: if ($_ eq 'all') {
611: $Str .= 'selected ';
612: last;
613: }
614: }
615: $Str .= ">all</option>\n";
616: #
617: # Loop through the student data fields
618: foreach my $item (@StudentDataOrder) {
619: $Str .= ' <option value="'.$item.'" ';
620: foreach (@SelectedStudentData) {
621: if ($item eq $_ ) {
622: $Str .= 'selected ';
623: last;
624: }
625: }
626: $Str .= '>'.$item."</option>\n";
627: }
628: $Str .= "</select>\n";
629: return $Str;
1.60 matthew 630: }
631:
632: ##############################################
633: ##############################################
634:
635: =pod
636:
1.61 matthew 637: =item &MapSelect($elementname,$status,$numvisible,$restriction)
1.60 matthew 638:
639: Returns html for a selection box allowing the user to choose one (or more)
640: of the sequences in the course. The values of the sequences are the symbs.
641: If the top sequence is selected, the value 'top' will result.
642:
643: =over 4
644:
645: =item $elementname The name of the HTML form element
646:
647: =item $status 'multiple' or 'single' selection box
648:
649: =item $numvisible The number of options to be visible
650:
651: =item $restriction Code reference to subroutine which returns true or
652: false. The code must expect a reference to a sequence data structure.
653:
654: =back
655:
656: =cut
657:
658: ##############################################
659: ##############################################
660: sub MapSelect {
1.61 matthew 661: my ($elementname,$status,$numvisible,$restriction)=@_;
1.60 matthew 662: if ($numvisible < 1) {
663: return;
664: }
665: #
666: # Set up array of selected items
1.61 matthew 667: &SetSelectedMaps($elementname);
1.60 matthew 668: #
669: # Set up the restriction call
670: if (! defined($restriction)) {
671: $restriction = sub { 1; };
672: }
673: #
674: # Build the form element
675: my $Str = "\n";
676: $Str .= '<select name="'.$elementname.'" ';
677: if ($status ne 'single') {
678: $Str .= 'multiple="true" ';
679: }
680: $Str .= 'size="'.$numvisible.'" >'."\n";
681: #
1.61 matthew 682: # Deal with 'all'
683: foreach (@SelectedMaps) {
684: if ($_ eq 'all') {
685: @SelectedMaps = ('all');
686: last;
687: }
688: }
689: #
690: # Put in option for 'all'
691: $Str .= ' <option value="all" ';
692: foreach (@SelectedMaps) {
693: if ($_ eq 'all') {
694: $Str .= 'selected ';
695: last;
696: }
697: }
698: $Str .= ">all</option>\n";
699: #
1.60 matthew 700: # Loop through the sequences
1.61 matthew 701: foreach my $seq (@Sequences) {
702: next if (! $restriction->($seq));
703: $Str .= ' <option value="'.$seq->{'symb'}.'" ';
704: foreach (@SelectedMaps) {
705: if ($seq->{'symb'} eq $_) {
1.60 matthew 706: $Str .= 'selected ';
707: last;
708: }
709: }
1.61 matthew 710: $Str .= '>'.$seq->{'title'}."</option>\n";
1.60 matthew 711: }
712: $Str .= "</select>\n";
713: return $Str;
714: }
715:
716: ##############################################
717: ##############################################
718:
719: =pod
720:
721: =item &SectionSelect($elementname,$status,$numvisible)
722:
723: Returns html for a selection box allowing the user to choose one (or more)
724: of the sections in the course.
725:
726: =over 4
727:
728: =item $elementname The name of the HTML form element
729:
730: =item $status 'multiple' or 'single' selection box
731:
732: =item $numvisible The number of options to be visible
733:
734: =item $selected Array ref to the names of the already selected sections.
735: If undef, $ENV{'form.'.$elementname} is used.
736: If $ENV{'form.'.$elementname} is also empty, none will be selected.
737:
738: =item $restriction Code reference to subroutine which returns true or
739: false. The code must expect a reference to a sequence data structure.
740:
741: =back
742:
743: =cut
744:
745: ##############################################
746: ##############################################
747: sub SectionSelect {
748: my ($elementname,$status,$numvisible)=@_;
749: if ($numvisible < 1) {
750: return;
751: }
752: #
753: # Build the form element
754: my $Str = "\n";
755: $Str .= '<select name="'.$elementname.'" ';
756: if ($status ne 'single') {
757: $Str .= 'multiple="true" ';
758: }
759: $Str .= 'size="'.$numvisible.'" >'."\n";
760: #
761: # Loop through the sequences
762: foreach my $s (@Sections) {
763: $Str .= ' <option value="'.$s.'" ';
764: foreach (@SelectedSections) {
1.61 matthew 765: if ($s eq $_) {
1.60 matthew 766: $Str .= 'selected ';
767: last;
768: }
769: }
770: $Str .= '>'.$s."</option>\n";
771: }
772: $Str .= "</select>\n";
773: return $Str;
774: }
775:
1.61 matthew 776: ##################################################
777: ##################################################
1.60 matthew 778: sub DisplayClasslist {
779: my ($r)=@_;
780: #
781: my @Fields = ('fullname','username','domain','id','section');
782: #
783: my $Str='';
784: $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";
785: $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";
786: foreach my $field (@Fields) {
1.65 matthew 787: $Str .= '<th><a href="/adm/statistics?reportSelected=classlist&sort='.$field.'">'.$field.
1.60 matthew 788: '</a></th>';
789: }
790: $Str .= '</tr>'."\n";
791: #
792: my $alternate = 0;
1.65 matthew 793: foreach my $student (@Students) { # @Students is a package variable
1.60 matthew 794: my $sname = $student->{'username'}.':'.$student->{'domain'};
795: if($alternate) {
796: $Str .= '<tr bgcolor="#ffffe6">';
797: } else {
798: $Str .= '<tr bgcolor="#ffffc6">';
799: }
800: $alternate = ($alternate + 1) % 2;
801: #
802: foreach my $field (@Fields) {
803: $Str .= '<td>';
804: if ($field eq 'fullname') {
805: $Str .= '<a href="/adm/statistics?reportSelected=';
1.65 matthew 806: $Str .= &Apache::lonnet::escape('student_assessment');
1.60 matthew 807: $Str .= '&StudentAssessmentStudent=';
1.61 matthew 808: $Str .= &Apache::lonnet::escape($sname).'">';
1.60 matthew 809: $Str .= $student->{$field}.' ';
810: $Str .= '</a>';
811: } else {
812: $Str .= $student->{$field};
813: }
814: $Str .= '</td>';
815: }
816: $Str .= "</tr>\n";
817: }
818: $Str .= '</table></td></tr></table>'."\n";
819: #
820: $r->print($Str);
821: $r->rflush();
822: #
823: return;
824: }
825:
1.65 matthew 826: ##############################################
827: ##############################################
1.33 stredwic 828: sub CreateMainMenu {
1.65 matthew 829: my ($status,$reports,$current)=@_;
830: #
1.33 stredwic 831: my $Str = '';
1.65 matthew 832: #
1.33 stredwic 833: $Str .= '<table border="0"><tbody><tr>'."\n";
1.63 matthew 834: $Str .= '<td></td>'."\n";
1.67 ! matthew 835: $Str .= '<td></td>'."\n";
1.57 minaeibi 836: $Str .= '<td align="center"><b>Select a Report</b></td>'."\n";
837: $Str .= '<td align="center"><b>Student Status</b></td></tr>'."\n";
1.33 stredwic 838: $Str .= '<tr>'."\n";
1.65 matthew 839: #
1.67 ! matthew 840: $Str .= '<td align="center">'.
! 841: '<input type="submit" name="Refresh" value="Update Display" />'.
! 842: "</td>\n";
! 843: $Str .= '<td align="center">'.
! 844: '<input type="submit" name="ClearCache" value="Clear Caches" />'.
! 845: "</td>\n";
1.65 matthew 846: #
1.33 stredwic 847: $Str .= '<td align="center">';
1.65 matthew 848: $Str .= '<select name="reportSelected" >'."\n";
1.33 stredwic 849: foreach (sort(keys(%$reports))) {
1.65 matthew 850: $Str .= '<option value="'.$_.'"';
851: if($current eq $_) {
852: $Str .= ' selected';
1.33 stredwic 853: }
854: $Str .= '>'.$reports->{$_}.'</option>'."\n";
855: }
856: $Str .= '</select></td>'."\n";
1.65 matthew 857: #
1.33 stredwic 858: $Str .= '<td align="center">';
859: $Str .= &Apache::lonhtmlcommon::StatusOptions($status, 'Statistics');
860: $Str .= '</td>'."\n";
1.65 matthew 861: #
1.33 stredwic 862: $Str .= '</tr></tbody></table>'."\n";
863: $Str .= '<hr>'."\n";
1.65 matthew 864: #
1.33 stredwic 865: return $Str;
866: }
867:
1.65 matthew 868: ##############################################
869: ##############################################
1.1 albertel 870: sub handler {
1.31 minaeibi 871: my $r=shift;
1.65 matthew 872: my $c = $r->connection();
873: #
874: # Check for overloading
1.51 www 875: my $loaderror=&Apache::lonnet::overloaderror($r);
876: if ($loaderror) { return $loaderror; }
877: $loaderror=
878: &Apache::lonnet::overloaderror($r,
879: $ENV{'course.'.$ENV{'request.course.id'}.'.home'});
880: if ($loaderror) { return $loaderror; }
1.65 matthew 881: #
882: # Check for access
1.27 stredwic 883: unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
884: $ENV{'user.error.msg'}=
885: $r->uri.":vgr:0:0:Cannot view grades for complete course";
1.55 minaeibi 886: return HTTP_NOT_ACCEPTABLE;
1.27 stredwic 887: }
1.65 matthew 888: #
1.27 stredwic 889: # Set document type for header only
890: if($r->header_only) {
891: if ($ENV{'browser.mathml'}) {
892: $r->content_type('text/xml');
893: } else {
894: $r->content_type('text/html');
895: }
896: &Apache::loncommon::no_cache($r);
897: $r->send_http_header;
898: return OK;
899: }
1.65 matthew 900: #
901: # Send the header
1.27 stredwic 902: $r->content_type('text/html');
903: $r->send_http_header;
1.65 matthew 904: #
905: # Extract form elements from query string
1.60 matthew 906: &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
1.65 matthew 907: ['sort','reportSelected',
1.61 matthew 908: 'StudentAssessmentStudent']);
1.65 matthew 909: if (! exists($ENV{'form.reportSelected'})) {
910: $ENV{'form.reportSelected'} = 'student_assessment';
911: }
912: #
913: # Give the LON-CAPA page header
914: $r->print(&Apache::lonhtmlcommon::Title('Course Statistics and Charts'));
915: $r->rflush();
916: #
1.66 matthew 917: if (! &Apache::lonmysql::verify_sql_connection()) {
918: my $serveradmin = $r->dir_config('lonAdmEMail');
919: $r->print(<<END);
920: <h2><font color="Red">Unable to connect to database!</font></h2>
921: <p>
922: Please notify the server administrator <b>$serveradmin</b>.
923: </p><p>
924: Course Statistics and Charts cannot be retrieved until the database is
925: restarted. Your data is intact but cannot be displayed at this time.
926: </p>
927: </body>
928: </html>
929: END
930: return;
1.67 ! matthew 931: }
! 932: #
! 933: # Clean out the caches
! 934: if (exists($ENV{'form.ClearCache'})) {
! 935: &Apache::loncoursedata::delete_caches($ENV{'requres.course.id'});
1.66 matthew 936: }
937: #
1.65 matthew 938: # Set up the statistics and chart environment
1.59 matthew 939: &PrepareClasslist($r);
1.60 matthew 940: &PrepareCourseData($r);
1.65 matthew 941: #
942: # Begin form output
943: $r->print('<form name="Statistics" ');
944: $r->print('method="post" action="/adm/statistics">');
945: #
946: # Print main menu
947: my %reports = ('classlist' => 'Class list',
948: 'problem_statistics' => 'Problem Statistics',
1.66 matthew 949: 'student_assessment' => 'Problem Status Chart',
1.65 matthew 950: 'percentage' => 'Correct-problems Plot',
951: 'option_response' => 'Option Response Analysis',
952: # 'activitylog' => 'Activity Log',
953: );
954: $r->print(&CreateMainMenu($ENV{'form.status'},
955: \%reports,$ENV{'form.reportSelected'}));
956: $r->rflush();
957: #
958: my $GoToPage = $ENV{'form.reportSelected'};
959: if($GoToPage eq 'activitylog') {
960: # &Apache::lonproblemstatistics::Activity();
961: } elsif($GoToPage eq 'problem_statistics') {
962: &Apache::lonproblemstatistics::BuildProblemStatisticsPage($r,$c);
963: } elsif($GoToPage eq 'option_response') {
964: # &Apache::lonproblemanalysis::BuildProblemAnalysisPage($r,$c);
965: } elsif($GoToPage eq 'student_assessment') {
966: &Apache::lonstudentassessment::BuildStudentAssessmentPage($r,$c);
967: } elsif($GoToPage eq 'DoDiffGraph' || $GoToPage eq 'PercentWrongGraph') {
968: # &Apache::lonproblemstatistics::BuildGraphicChart($r,$c);
969: } elsif($GoToPage eq 'classlist') {
970: &DisplayClasslist($r);
971: } elsif($GoToPage eq 'Correct-problems Plot') {
972: # &Apache::lonpercentage::BuildPercentageGraph($r,$c);
973: }
974: #
975: $r->print("</form>\n");
976: $r->print("</body>\n</html>\n");
977: $r->rflush();
978: #
1.27 stredwic 979: return OK;
1.1 albertel 980: }
1.65 matthew 981:
1.1 albertel 982: 1;
1.59 matthew 983:
1.65 matthew 984: #######################################################
985: #######################################################
986:
1.59 matthew 987: =pod
988:
989: =back
990:
991: =cut
1.65 matthew 992:
993: #######################################################
994: #######################################################
1.59 matthew 995:
1.1 albertel 996: __END__
1.31 minaeibi 997:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>