File:
[LON-CAPA] /
loncom /
interface /
statistics /
lonstudentassessment.pm
Revision
1.29:
download - view:
text,
annotated -
select for diffs
Tue Feb 25 20:47:47 2003 UTC (21 years, 5 months ago) by
matthew
Branches:
MAIN
CVS tags:
HEAD
lonstatistics.pm:
POD cleanups
@SelectedSections is set when we read the classlist.
Added variables $top_map, @Sequences, and @Assessments. These are
initialized by &PrepareCourseData($r).
Added &PrepareCourseData($r) which is essentially a wrapper for
&Apache::loncoursedata::get_sequence_assessment_data().
Added &MapSelect() to output a <select> box for sequences. Not tested.
Added &SectionSelect(..) to output a <select> box for sections. Tested.
Added &DisplayClasslist($r) which displays a table of the current classlist
that is sortable by each column. Does not bother with 'update time' as
this should not be an issue for the user. Tested.
Added call to &PrepareCourseData by the handler.
lonpercentage.pm, lonproblemanalysis.pm, lonproblemstatistics.pm,
lonstudentassessment.pm: modified to call &Apache::lonstatistics::SectionSelect
instead of the method in lonhtmlcommon.pm.
1: # The LearningOnline Network with CAPA
2: #
3: # $Id: lonstudentassessment.pm,v 1.29 2003/02/25 20:47:47 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: # LON-CAPA is free software; you can redistribute it and/or modify
9: # it under the terms of the GNU General Public License as published by
10: # the Free Software Foundation; either version 2 of the License, or
11: # (at your option) any later version.
12: #
13: # LON-CAPA is distributed in the hope that it will be useful,
14: # but WITHOUT ANY WARRANTY; without even the implied warranty of
15: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16: # GNU General Public License for more details.
17: #
18: # You should have received a copy of the GNU General Public License
19: # along with LON-CAPA; if not, write to the Free Software
20: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21: #
22: # /home/httpd/html/adm/gpl.txt
23: #
24: # http://www.lon-capa.org/
25: #
26: # (Navigate problems for statistical reports
27: #
28: #######################################################
29: #######################################################
30:
31: =pod
32:
33: =head1 NAME
34:
35: lonstudentassessment
36:
37: =head1 SYNOPSIS
38:
39: Presents assessment data about a student or a group of students.
40:
41: =head1 Subroutines
42:
43: =over 4
44:
45: =cut
46:
47: #######################################################
48: #######################################################
49:
50: package Apache::lonstudentassessment;
51:
52: use strict;
53: use Apache::lonstatistics;
54: use Apache::lonhtmlcommon;
55: use Apache::loncoursedata;
56: use Apache::lonnet; # for logging porpoises
57: use GDBM_File;
58:
59: #######################################################
60: #######################################################
61:
62: =pod
63:
64: =item &BuildStudentAssessmentPage()
65:
66: Inputs:
67:
68: =over 4
69:
70: =item $cacheDB The name of the cache file used to store student data
71:
72: =item $students Array ref containing the name(s) of the students
73: selected for display
74:
75: =item $courseID The ID of the course
76:
77: =item $formName The name of the html form - 'Statistics'
78:
79: =item $headings Array ref of headings to show
80:
81: =item $spacing A string of spaces
82:
83: =item $studentInformation Array ref of possible headings for student info
84: ('fullname','section',...)
85:
86: =item $r Apache Request
87:
88: =item $c Apache Connection
89:
90: =back
91:
92: =cut
93:
94: #######################################################
95: #######################################################
96: sub BuildStudentAssessmentPage {
97: my ($cacheDB,$students,$courseID,$formName,$headings,$spacing,
98: $studentInformation,$r,$c)=@_;
99: my %cache;
100: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
101: $r->print('<html><body>Unable to tie database.</body></html>');
102: return;
103: }
104:
105: # Remove students who don't have the proper section.
106: my @sectionsSelected = split(':',$cache{'sectionsSelected'});
107: for(my $studentIndex=((scalar @$students)-1); $studentIndex>=0;
108: $studentIndex--) {
109: my $value = $cache{$students->[$studentIndex].':section'};
110: my $found = 0;
111: foreach (@sectionsSelected) {
112: if($_ eq 'none') {
113: if($value eq '' || !defined($value) || $value eq ' ') {
114: $found = 1;
115: last;
116: }
117: } else {
118: if($value eq $_) {
119: $found = 1;
120: last;
121: }
122: }
123: }
124: if($found == 0) {
125: splice(@$students, $studentIndex, 1);
126: }
127: }
128: my ($infoHeadings, $infoKeys, $sequenceHeadings, $sequenceKeys,
129: $doNotShow) =
130: &ShouldShowColumns(\%cache, $headings, $studentInformation);
131:
132: my $selectedName = &FindSelectedStudent(\%cache,
133: $cache{'StudentAssessmentStudent'},
134: $students);
135: $r->print(&CreateInterface(\%cache, $selectedName, $students, $formName,
136: $doNotShow));
137: $r->rflush();
138:
139: my $Str = '';
140: if($selectedName eq 'No Student Selected') {
141: $Str .= '<h3><font color=blue>WARNING: ';
142: $Str .= 'Please select a student</font></h3>';
143: $r->print($Str);
144: return;
145: }
146:
147: $r->print(&CreateTableHeadings(\%cache, $spacing, $infoKeys, $infoHeadings,
148: $sequenceKeys, $sequenceHeadings));
149: untie(%cache);
150: if($c->aborted()) { return $Str; }
151:
152: my $selected=0;
153: my $Count = 0;
154: $r->print('<pre>'."\n");
155: foreach (@$students) {
156: if($c->aborted()) { return $Str; }
157: next if ($_ ne $selectedName &&
158: $selectedName ne 'All Students');
159: $selected = 1;
160:
161: my @who = ($_);
162: next if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'true',
163: $cacheDB, 'true',
164: 'false', $courseID,
165: $r, $c) ne 'OK');
166: next if($c->aborted());
167:
168: if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
169: my @before=();
170: my @after=();
171: my @updateColumn=();
172: my $foundUpdate = 0;
173: foreach(@$infoKeys) {
174: if(/updateTime/) {
175: $foundUpdate=1;
176: push(@updateColumn, $_);
177: next;
178: }
179: if($foundUpdate) {
180: push(@after, $_);
181: } else {
182: push(@before, $_);
183: }
184: }
185: $Count++;
186: my $out = '';
187: $out .= sprintf("%3d) ", $Count);
188: if($Count % 2) {
189: $out .= '<bgcolor="#FFFFFF">';
190: } else {
191: $out .= '<bgcolor="#505050">';
192: }
193: my $displayString = $out.'DISPLAYDATA'.$spacing;
194: $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
195: \%cache, $_,
196: \@before,
197: $displayString,
198: 'preformatted'));
199:
200: if($foundUpdate) {
201: $displayString = '';
202: $displayString .= '<a href="/adm/statistics?reportSelected=';
203: $displayString .= &Apache::lonnet::escape('Student Assessment');
204: $displayString .= '&download='.$_.'">';
205: $displayString .= 'DISPLAYDATA</a>'.$spacing;
206: $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
207: \%cache, $_,
208: \@updateColumn,
209: $displayString,
210: 'preformatted'));
211: }
212:
213: $displayString = 'DISPLAYDATA'.$spacing;
214: $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
215: \%cache, $_,
216: \@after,
217: $displayString,
218: 'preformatted'));
219: $r->print(&StudentReport(\%cache, $_, $spacing, $sequenceKeys));
220: $r->print("\n");
221: $r->rflush();
222: untie(%cache);
223: }
224: }
225: $r->print('</pre>'."\n");
226: if($selected == 0) {
227: $Str .= '<h3><font color=blue>WARNING: ';
228: $Str .= 'No Students enrolled OR Please select a student</font></h3>';
229: $r->print($Str);
230: } else {
231: if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
232: $r->print(&StudentAverageTotal(\%cache, $students, $sequenceKeys));
233: untie(%cache);
234: }
235: }
236: return;
237: }
238: #######################################################
239: #######################################################
240:
241: =pod
242:
243: =item &CreateInterface()
244:
245: Called by &BuildStudentAssessmentPage to create the top part of the
246: page which displays the chart.
247:
248: Inputs:
249:
250: =over 4
251:
252: =item $cache The ubiquitous cache
253:
254: =item $selectedName The name of the currently selected student, or
255: 'All Students' or 'No Student Selected'.
256:
257: =item $students Array ref containing the name(s) of the students selected
258: for display.
259:
260: =item $formName The name of the HTML form to use, 'Statistics'
261:
262: =item $doNotShow Array ref containing the names of columns to not show
263:
264: =back
265:
266: Returns: A string containing the HTML for the headers and top table for
267: the chart page.
268:
269: =cut
270:
271: #######################################################
272: #######################################################
273: sub CreateInterface {
274: my($cache,$selectedName,$students,$formName,$doNotShow)=@_;
275:
276: my $Str = '';
277: $Str .= &CreateLegend();
278: $Str .= '<table><tr><td>'."\n";
279: $Str .= '<input type="submit" name="PreviousStudent" ';
280: $Str .= 'value="Previous Student" />'."\n";
281: $Str .= '   '."\n";
282: $Str .= &Apache::lonhtmlcommon::StudentOptions($cache, $students,
283: $selectedName,
284: 'StudentAssessment',
285: $formName);
286: $Str .= "\n".'   '."\n";
287: $Str .= '<input type="submit" name="NextStudent" ';
288: $Str .= 'value="Next Student" />'."\n";
289: $Str .= '</td></tr></table>'."\n";
290: $Str .= '<table cellspacing="5"><tr>'."\n";
291: $Str .= '<td align="center"><b>Select Sections</b>'."\n";
292: $Str .= '</td>'."\n";
293: $Str .= '<td align="center"><b>Select column to view:</b></td>'."\n";
294: $Str .= '<td></td></tr>'."\n";
295:
296: $Str .= '<tr><td align="center">'."\n";
297: my @sections = split(':',$cache->{'sectionList'});
298: my @selectedSections = split(':',$cache->{'sectionsSelected'});
299: $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
300: $Str .= '</td><td align="center">';
301: $Str .= &CreateColumnSelectionBox($doNotShow);
302: $Str .= '</td><td>'."\n";
303: $Str .= '<input type="submit" name="DefaultColumns" ';
304: $Str .= 'value="Default Column Display" />'."\n";
305: $Str .= '</td><td>'."\n";
306: $Str .= '<input type="submit" name="displaymode" ';
307: if (! exists($ENV{'form.displaymode'}) ||
308: lc($ENV{'form.displaymode'}) eq 'display with links') {
309: $Str .= 'value="Display without links" />';
310: # Set the current value, in case it is undefined
311: $ENV{'form.displaymode'} = 'Display with links';
312: } else {
313: $Str .= 'value="Display with links" />';
314: }
315: $Str .= "\n";
316: $Str .= '</td></tr></table>'."\n";
317:
318: return $Str;
319: }
320: #######################################################
321: #######################################################
322:
323: =pod
324:
325: =item &CreateTableHeadings()
326:
327: Create HTML for the columns of student data to show.
328: Called by &BuildStudentAssessmentPage(). Calls
329: &Apache::lonhtmlcommon::CreateHeadings().
330:
331: Inputs:
332:
333: =over 4
334:
335: =item $cache The ubiquitous cache
336:
337: =item $spacing A string of spaces
338:
339: =item $infoKeys Array ref to names of keys to display from the cache
340: which describe students
341:
342: =item $infoHeadings Array ref to headings of columns for student info
343:
344: =item $sequenceKeys Array ref of names of keys to use to retrieve sequence
345: data from the cache
346:
347: =item $sequenceHeadings Array ref of names of sequences used for output.
348:
349: =back
350:
351: Returns: A string containing the HTML of the table headings.
352:
353: =cut
354:
355: #######################################################
356: #######################################################
357: sub CreateTableHeadings {
358: my($cache,$spacing,$infoKeys,$infoHeadings,$sequenceKeys,
359: $sequenceHeadings)=@_;
360:
361: # my $Str = '     ';
362: my $Str = '';
363: $Str .= '<table border="0" cellpadding="0" cellspacing="0">'."\n";
364: $Str .= '<tr>'."\n";
365: $Str .= '<td><pre> </pre></td>'."\n";
366: $Str .= &CreateColumnSelectors($infoHeadings, $sequenceHeadings,
367: $sequenceKeys);
368: $Str .= '<td></td></tr>'."\n";
369:
370: $Str .= '<tr>'."\n";
371: my $displayString = '';
372: $displayString .= '<td><pre> </pre></td>'."\n";
373: $displayString .= '<td align="left"><pre><a href="/adm/statistics?';
374: $displayString .= 'sort=LINKDATA">DISPLAYDATA</a>FORMATTING';
375: $displayString .= $spacing.'</pre></td>'."\n";
376: $Str .= &Apache::lonhtmlcommon::CreateHeadings($cache,
377: $infoKeys,
378: $infoHeadings,
379: $displayString,
380: 'preformatted');
381:
382: $displayString = '<td align="left"><pre>DISPLAYDATAFORMATTING'.$spacing;
383: $displayString .= '</pre></td>'."\n";
384: $Str .= &Apache::lonhtmlcommon::CreateHeadings($cache,
385: $sequenceKeys,
386: $sequenceHeadings,
387: $displayString,
388: 'preformatted');
389:
390: $Str .= '<td><pre>Total Solved/Total Problems</pre></td>';
391: $Str .= '</tr></table>'."\n";
392:
393: return $Str;
394: }
395:
396: #######################################################
397: #######################################################
398:
399: =pod
400:
401: =item &StudentReport()
402:
403: This is the workhorse subroutine - it handles formatting and display of a
404: students performance data. It processes one row of the chart.
405:
406: Input:
407:
408: =over 4
409:
410: =item $cache The ubiquitous cache
411:
412: =item $name The name and domain of the current student in name:domain format
413:
414: =item $spacing A string containing spaces.
415:
416: =item $showSequences Array ref containing the sequences to display
417:
418: =back
419:
420: Output: $Str
421:
422: $Str: Formatted string that is an entire row of the chart. It is a
423: concatenation of student information and student course information.
424:
425: =cut
426:
427: #######################################################
428: #######################################################
429: sub StudentReport {
430: my ($cache,$name,$spacing,$showSequences)=@_;
431: my ($username,$domain)=split(':',$name);
432:
433: my $Str = '';
434: if(defined($cache->{$name.':error'})) {
435: return $Str;
436: }
437: if($cache->{$name.':error'} =~ /course/) {
438: $Str .= '<b><font color="blue">No course data for student </font>';
439: $Str .= '<font color="red">'.$username.'.</font></b><br>';
440: return $Str;
441: }
442:
443: my $hasVersion = 'false';
444: my $hasFinalData = 'false';
445: foreach my $sequence (@$showSequences) {
446: my $hasData = 'false';
447: my $characterCount=0;
448: foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {
449: my $problem = $cache->{$problemID.':problem'};
450: # All grades (except for versionless parts) are displayed as links
451: # to their submission record. Loop through all the parts for the
452: # current problem in the correct order and prepare the output links
453: foreach(split(/\:/,$cache->{$sequence.':'.$problemID.
454: ':parts'})) {
455: if($cache->{$name.':'.$problemID.':NoVersion'} eq 'true' ||
456: $cache->{$name.':'.$problemID.':'.$_.':code'} eq ' ' ||
457: $cache->{$name.':'.$problemID.':'.$_.':code'} eq '') {
458: $Str .= ' ';
459: $characterCount++;
460: next;
461: }
462: $hasVersion = 'true';
463: $hasData = 'true';
464: if (lc($ENV{'form.displaymode'}) ne 'display without links') {
465: $Str .= '<a href="/adm/grades?symb=';
466: $Str .= &Apache::lonnet::escape($problem);
467: $Str .= '&student='.$username.'&domain='.$domain;
468: $Str .= '&command=submission">';
469: }
470: my $code = $cache->{$name.':'.$problemID.':'.$_.':code'};
471: my $tries = $cache->{$name.':'.$problemID.':'.$_.':tries'};
472: if($code eq '*' && $tries < 10 && $tries ne '') {
473: $code = $tries;
474: }
475: $Str .= $code;
476: if (lc($ENV{'form.displaymode'}) ne 'display without links') {
477: $Str .= '</a>';
478: }
479: $characterCount++;
480: }
481: }
482:
483: # Output the number of correct answers for the current sequence.
484: # This part takes up 6 character slots, but is formated right
485: # justified.
486: my $spacesNeeded=$cache->{$sequence.':columnWidth'}-$characterCount;
487: $spacesNeeded -= 3;
488: $Str .= (' 'x$spacesNeeded);
489:
490: # my $outputProblemsCorrect = sprintf("%3d", $cache->{$name.':'.$sequence.
491: # ':problemsCorrect'});
492:
493: my $outputProblemsCorrect = sprintf("%2d/%2d", $cache->{$name.':'.$sequence.
494: ':problemsCorrect'},
495: $characterCount);
496: if($hasData eq 'true') {
497: $Str .= '<font color="#007700">'.$outputProblemsCorrect.'</font>';
498: $hasFinalData = 'true';
499: } else {
500: $Str .= '<font color="#007700"> </font>';
501: }
502: $Str .= $spacing;
503: }
504:
505: # Output the total correct problems over the total number of problems.
506: # I don't like this type of formatting, but it is a solution. Need
507: # a way to dynamically determine the space requirements.
508: my $outputProblemsSolved = sprintf("%4d", $cache->{$name.':problemsSolved'});
509: my $outputTotalProblems = sprintf("%4d", $cache->{$name.':totalProblems'});
510: if($hasFinalData eq 'true') {
511: $Str .= '<font color="#000088">'.$outputProblemsSolved.
512: ' / '.$outputTotalProblems.'</font>';
513: } else {
514: $Str .= '<font color="#000088"> </font>';
515: }
516:
517: if($hasVersion eq 'false') {
518: $Str = '<b><font color="blue">No course data.</font></b>';
519: }
520:
521: return $Str;
522: }
523:
524: #######################################################
525: #######################################################
526:
527: #######################################################
528: #######################################################
529: sub StudentAverageTotal {
530: my ($cache, $students, $sequenceKeys)=@_;
531: my $Str = "\n<b>Summary Tables:</b>\n";
532: my %Correct = ();
533: my $ProblemsSolved = 0;
534: my $TotalProblems = 0;
535: my $StudentCount = 0;
536:
537: foreach my $name (@$students) {
538: $StudentCount++;
539: foreach my $sequence (@$sequenceKeys) {
540: $Correct{$sequence} +=
541: $cache->{$name.':'.$sequence.':problemsCorrect'};
542: }
543: $ProblemsSolved += $cache->{$name.':problemsSolved'};
544: $TotalProblems += $cache->{$name.':totalProblems'};
545: }
546: if ($StudentCount) {
547: $ProblemsSolved = sprintf( "%.2f",
548: $ProblemsSolved/$StudentCount);
549: $TotalProblems /= $StudentCount;
550: } else {
551: $ProblemsSolved = 0;
552: $TotalProblems = 0;
553: }
554:
555: $Str .= '<table border=2 cellspacing="1">'."\n";
556: $Str .= '<tr><td><b>Students Count</b></td><td><b>'.
557: $StudentCount.'</b></td></tr>'."\n";
558: $Str .= '<tr><td><b>Total Problems</b></td><td><b>'.
559: $TotalProblems.'</b></td></tr>'."\n";
560: $Str .= '<tr><td><b>Average Correct</b></td><td><b>'.
561: $ProblemsSolved.'</b></td></tr>'."\n";
562: $Str .= '</table>'."\n";
563:
564: $Str .= '<table border=2 cellspacing="1">'."\n";
565: $Str .= '<tr><th>Title</th><th>Total Problems</th>'.
566: '<th>Average Correct</th></tr>'."\n";
567: foreach my $S(@$sequenceKeys) {
568: my $title=$cache->{$S.':title'};
569: #$Str .= $cache->{$S.':problems'};
570: #my @problems=split(':', $cache->{$S.':problems'});
571: #my $pCount=scalar @problems;
572: my $pCount=MaxSeqPr($cache,@$students[0],$S);
573: my $crr;
574: if ($StudentCount) {
575: $crr=sprintf( "%.2f", $Correct{$S}/$StudentCount );
576: } else {
577: $crr="0.00";
578: }
579: $Str .= '<tr><td>'.$title.
580: '</td><td align=center>'.$pCount.
581: '</td><td align=center>'.$crr.
582: '</td></tr>'."\n";
583: }
584:
585: $Str .= '</table>'."\n";
586:
587: return $Str;
588: }
589:
590: #######################################################
591: #######################################################
592:
593: #######################################################
594: #######################################################
595: sub MaxSeqPr {
596: my ($cache, $name, $sequence)=@_;
597: my $prCount=0;
598: foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {
599: my $problem = $cache->{$problemID.':problem'};
600: foreach(split(/\:/,$cache->{$sequence.':'.$problemID.':parts'})) {
601: if($cache->{$name.':'.$problemID.':NoVersion'} eq 'true' ||
602: $cache->{$name.':'.$problemID.':'.$_.':code'} eq ' ' ||
603: $cache->{$name.':'.$problemID.':'.$_.':code'} eq '') {
604: $prCount++;
605: next;
606: }
607: $prCount++;
608: }
609: }
610: return $prCount;
611: }
612:
613: #######################################################
614: #######################################################
615:
616: =pod
617:
618: =item &CreateLegend()
619:
620: This function returns a formatted string containing the legend for the
621: chart. The legend describes the symbols used to represent grades for
622: problems.
623:
624: =cut
625:
626: #######################################################
627: #######################################################
628: sub CreateLegend {
629: my $Str = "<p><pre>".
630: " 1 correct by student in 1 try\n".
631: " 7 correct by student in 7 tries\n".
632: " * correct by student in more than 9 tries\n".
633: " + correct by hand grading or override\n".
634: " - incorrect by override\n".
635: " . incorrect attempted\n".
636: " # ungraded attempted\n".
637: " not attempted (blank field)\n".
638: " x excused".
639: "</pre><p>";
640: return $Str;
641: }
642:
643: #######################################################
644: #######################################################
645:
646: =pod
647:
648: =item &CreateColumnSelectionBox()
649:
650: If there are columns not being displayed then this selection box is created
651: with a list of those columns. When selections are made and the page
652: refreshed, the columns will be removed from this box and the column is
653: put back in the chart. If there is no columns to select, no row is added
654: to the interface table.
655:
656: =over 4
657: Input: $CacheData, $headings
658:
659: $CacheData: A pointer to a hash tied to the cached data
660:
661: $headings: An array of the names of the columns for the student information.
662: They are used for displaying which columns are missing.
663:
664: Output: $notThere
665:
666: $notThere: The string contains one row of a table. The first column has the
667: name of the selection box. The second contains the selection box
668: which has a size of four.
669:
670: =back
671:
672: =cut
673:
674: #######################################################
675: #######################################################
676: sub CreateColumnSelectionBox {
677: my ($doNotShow)=@_;
678:
679: my $notThere = '';
680: $notThere .= '<select name="ReselectColumns" size="4" ';
681: $notThere .= 'multiple="true">'."\n";
682:
683: for(my $index=0; $index<$doNotShow->{'count'}; $index++) {
684: my $name = $doNotShow->{$index.':name'};
685: $notThere .= '<option value="';
686: $notThere .= $doNotShow->{$index.':id'}.'">';
687: $notThere .= $name.'</option>'."\n";
688: }
689:
690: $notThere .= '</select>';
691:
692: return $notThere;
693: }
694:
695: #######################################################
696: #######################################################
697:
698: =pod
699:
700: =item &CreateColumnSelectors()
701:
702: This function generates the checkboxes above the column headings. The
703: column will be removed if the checkbox is unchecked.
704:
705: =over 4
706:
707: Input: $CacheData, $headings
708:
709: $CacheData: A pointer to a hash tied to the cached data
710:
711: $headings: An array of the names of the columns for the student
712: information. They are used to know what are the student information columns
713:
714: Output: $present
715:
716: $present: The string contains the first row of a table. Each column contains
717: a checkbox which is left justified. Currently left justification is used
718: for consistency of location over the column in which it presides.
719:
720: =back
721:
722: =cut
723:
724: #######################################################
725: #######################################################
726: sub CreateColumnSelectors {
727: my ($infoHeadings, $sequenceHeadings, $sequenceKeys)=@_;
728:
729: my $present = '';
730: for(my $index=0; $index<(scalar @$infoHeadings); $index++) {
731: $present .= '<td align="left">';
732: $present .= '<input type="checkbox" checked="on" ';
733: $present .= 'name="HeadingColumn'.$infoHeadings->[$index].'" />';
734: $present .= '</td>'."\n";
735: }
736:
737: for(my $index=0; $index<(scalar @$sequenceHeadings); $index++) {
738: $present .= '<td align="left">';
739: $present .= '<input type="checkbox" checked="on" ';
740: $present .= 'name="SequenceColumn'.$sequenceKeys->[$index].'" />';
741: $present .= '</td>'."\n";
742: }
743:
744: return $present;
745: }
746:
747: #######################################################
748: #######################################################
749:
750: =pod
751:
752: =back
753:
754: =head1 HELPER FUNCTIONS
755:
756: =over 4
757:
758: =cut
759:
760: #######################################################
761: #######################################################
762: sub FindSelectedStudent {
763: my($cache, $selectedName, $students)=@_;
764:
765: if($selectedName eq 'All Students' ||
766: $selectedName eq 'No Student Selected') {
767: return $selectedName;
768: }
769:
770: for(my $index=0; $index<(scalar @$students); $index++) {
771: my $fullname = $cache->{$students->[$index].':fullname'};
772: if($fullname eq $selectedName) {
773: if($cache->{'StudentAssessmentMove'} eq 'next') {
774: if($index == ((scalar @$students) - 1)) {
775: $selectedName = $students->[0];
776: return $selectedName;
777: } else {
778: $selectedName = $students->[$index+1];
779: return $selectedName;
780: }
781: } elsif($cache->{'StudentAssessmentMove'} eq 'previous') {
782: if($index == 0) {
783: $selectedName = $students->[-1];
784: return $selectedName;
785: } else {
786: $selectedName = $students->[$index-1];
787: return $selectedName;
788: }
789: } else {
790: $selectedName = $students->[$index];
791: return $selectedName;
792: }
793: last;
794: }
795: }
796:
797: return 'No Student Selected';
798: }
799: #######################################################
800: #######################################################
801:
802: =pod
803:
804: =item &ShouldShowColumn()
805:
806: Determine if a specified column should be shown on the chart.
807:
808: =over 4
809:
810: Input: $cache, $test
811:
812: $cache: A pointer to the hash tied to the cached data
813:
814: $test: The form name of the column (heading.$headingIndex) or
815: (sequence.$sequenceIndex)
816:
817: =back
818:
819: =cut
820:
821: #######################################################
822: #######################################################
823: sub ShouldShowColumns {
824: my ($cache,$headings,$cacheKey)=@_;
825:
826: my @infoKeys=();
827: my @infoHeadings=();
828:
829: my @sequenceKeys=();
830: my @sequenceHeadings=();
831:
832: my %doNotShow;
833:
834: my $index;
835: my $count = 0;
836: my $check = '';
837: for($index=0; $index < scalar @$headings; $index++) {
838: $check = 'HeadingColumn'.$headings->[$index];
839: if($cache->{'HeadingsFound'} =~ /$check/) {
840: push(@infoHeadings, $headings->[$index]);
841: push(@infoKeys, $cacheKey->[$index]);
842: } else {
843: $doNotShow{$count.':name'} = $headings->[$index];
844: $doNotShow{$count.':id'} = 'HeadingColumn'.$headings->[$index];
845: $count++;
846: }
847: }
848:
849: foreach my $sequence (split(/\:/,$cache->{'orderedSequences'})) {
850: $check = 'SequenceColumn'.$sequence;
851: if($cache->{'SequencesFound'} eq 'All Sequences' ||
852: $cache->{'SequencesFound'} =~ /$check/) {
853: push(@sequenceHeadings, $cache->{$sequence.':title'});
854: push(@sequenceKeys, $sequence);
855: } else {
856: $doNotShow{$count.':name'} = $cache->{$sequence.':title'};
857: $doNotShow{$count.':id'} = 'SequenceColumn'.$sequence;
858: $count++;
859: }
860: }
861:
862: $doNotShow{'count'} = $count;
863:
864: return (\@infoHeadings, \@infoKeys, \@sequenceHeadings,
865: \@sequenceKeys, \%doNotShow);
866: }
867: 1;
868:
869: #######################################################
870: #######################################################
871:
872: =pod
873:
874: =back
875:
876: =cut
877:
878: #######################################################
879: #######################################################
880:
881: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>