File:
[LON-CAPA] /
loncom /
interface /
statistics /
lonproblemstatistics.pm
Revision
1.41:
download - view:
text,
annotated -
select for diffs
Tue Mar 25 23:00:40 2003 UTC (21 years, 3 months ago) by
matthew
Branches:
MAIN
CVS tags:
HEAD
Removed GDBM_File dependence.
Removed &InitializeProblemStatistics, &ExtractStudentData, &SortDivideByTries,
&SortProblems, and &CalculateStatistics.
Added: &CreateInterface and shamelessly ripped off &OutputDescriptions and
&CreateAndParseOutputSelect from lonstudentassessment.pm.
Added &Gather_Student_Data to ensure the student data is up to date.
Rewrote &BuildProblemStatisticsPage to call &CreateInterface,
&Gather_Student_Data, and the proper output functions.
Added &output_html_grouped_by_sequence
Added &output_html_ungrouped which is not fully implemented at this time.
1: # The LearningOnline Network with CAPA
2: #
3: # $Id: lonproblemstatistics.pm,v 1.41 2003/03/25 23:00:40 matthew Exp $
4: #
5: # Copyright Michigan State University Board of Trustees
6: #
7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
8: #
9: # LON-CAPA is free software; you can redistribute it and/or modify
10: # it under the terms of the GNU General Public License as published by
11: # the Free Software Foundation; either version 2 of the License, or
12: # (at your option) any later version.
13: #
14: # LON-CAPA is distributed in the hope that it will be useful,
15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: # GNU General Public License for more details.
18: #
19: # You should have received a copy of the GNU General Public License
20: # along with LON-CAPA; if not, write to the Free Software
21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: #
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: # (Navigate problems for statistical reports
28: #
29: ###
30:
31: package Apache::lonproblemstatistics;
32:
33: use strict;
34: use Apache::lonnet();
35: use Apache::lonhtmlcommon;
36: use Apache::loncoursedata;
37: use Apache::lonstatistics;
38:
39: #######################################################
40: #######################################################
41:
42: sub CreateInterface {
43: my $Str = '';
44: $Str .= '<table cellspacing="5">'."\n";
45: $Str .= '<tr>';
46: $Str .= '<td align="center"><b>Sections</b></td>';
47: $Str .= '<td align="center"><b>Sequences and Folders</b></td>';
48: $Str .= '<td align="center"><b>Output</b></td>';
49: $Str .= '</tr>'."\n";
50: #
51: $Str .= '<tr><td align="center">'."\n";
52: $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
53: $Str .= '</td><td align="center">';
54: #
55: my $only_seq_with_assessments = sub {
56: my $s=shift;
57: if ($s->{'num_assess'} < 1) {
58: return 0;
59: } else {
60: return 1;
61: }
62: };
63: $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
64: $only_seq_with_assessments);
65: $Str .= '</td><td>'."\n";
66: $Str .= &CreateAndParseOutputSelector();
67: $Str .= '</td></tr>'."\n";
68: $Str .= '</table>'."\n";
69: return $Str;
70: }
71:
72: #######################################################
73: #######################################################
74:
75: =pod
76:
77: =item &CreateAndParseOutputSelector()
78:
79: =cut
80:
81: #######################################################
82: #######################################################
83: my $output_mode;
84: my $show;
85:
86: my @OutputOptions =
87: (
88: { name => 'problem statistics grouped by sequence',
89: value => 'HTML problem statistics grouped',
90: description => 'Output statistics for the problem parts.',
91: mode => 'html',
92: show => 'grouped',
93: },
94: { name => 'problem statistics ungrouped',
95: value => 'HTML problem statistics ungrouped',
96: description => 'Output statistics for the problem parts.',
97: mode => 'html',
98: show => 'ungrouped',
99: },
100: { name => 'problem statistics, Excel',
101: value => 'Excel problem statistics',
102: description => 'Output statistics for the problem parts '.
103: 'in an Excel workbook',
104: mode => 'excel',
105: show => 'all',
106: },
107: { name => 'Degree of Difficulty Plot',
108: value => 'plot deg diff',
109: description => 'Generate a plot of the degree of difficulty of each '.
110: 'problem part.',
111: mode => 'plot',
112: show => 'deg of diff',
113: },
114: { name => 'Percent Wrong Plot',
115: value => 'plot per wrong',
116: description => 'Generate a plot showing the percent of students who '.
117: 'were unable to complete each problem part',
118: mode => 'plot',
119: show => 'per wrong',
120: },
121: );
122:
123: sub OutputDescriptions {
124: my $Str = '';
125: $Str .= "<h2>Output Modes</h2>\n";
126: $Str .= "<dl>\n";
127: foreach my $outputmode (@OutputOptions) {
128: $Str .=" <dt>".$outputmode->{'name'}."</dt>\n";
129: $Str .=" <dd>".$outputmode->{'description'}."</dd>\n";
130: }
131: $Str .= "</dl>\n";
132: return $Str;
133: }
134:
135: sub CreateAndParseOutputSelector {
136: my $Str = '';
137: my $elementname = 'outputmode';
138: #
139: # Format for output options is 'mode, restrictions';
140: my $selected = 'html, with links';
141: if (exists($ENV{'form.'.$elementname})) {
142: if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) {
143: $selected = $ENV{'form.'.$elementname}->[0];
144: } else {
145: $selected = $ENV{'form.'.$elementname};
146: }
147: }
148: #
149: # Set package variables describing output mode
150: $output_mode = 'html';
151: $show = 'all';
152: foreach my $option (@OutputOptions) {
153: next if ($option->{'value'} ne $selected);
154: $output_mode = $option->{'mode'};
155: $show = $option->{'show'};
156: }
157: #
158: # Build the form element
159: $Str = qq/<select size="5" name="$elementname">/;
160: foreach my $option (@OutputOptions) {
161: $Str .= "\n".' <option value="'.$option->{'value'}.'"';
162: $Str .= " selected " if ($option->{'value'} eq $selected);
163: $Str .= ">".$option->{'name'}."<\/option>";
164: }
165: $Str .= "\n</select>";
166: return $Str;
167: }
168:
169: ###############################################
170: ###############################################
171:
172: ###############################################
173: ###############################################
174: sub Gather_Student_Data {
175: my ($r) = @_;
176: my $c = $r->connection();
177: #
178: my @Sequences = &Apache::lonstatistics::Sequences_with_Assess();
179: #
180: my @Students = @Apache::lonstatistics::Students;
181: #
182: # Open the progress window
183: my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
184: ($r,'Statistics Compilation Status',
185: 'Statistics Compilation Progress', scalar(@Students));
186: #
187: while (my $student = shift @Students) {
188: return if ($c->aborted());
189: my ($status,undef) = &Apache::loncoursedata::ensure_current_data
190: ($student->{'username'},$student->{'domain'},
191: $ENV{'request.course.id'});
192: &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
193: 'last student');
194: }
195: &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
196: $r->rflush();
197: }
198:
199: ###############################################
200: ###############################################
201:
202: ###############################################
203: ###############################################
204: sub BuildProblemStatisticsPage {
205: my ($r,$c)=@_;
206: #
207: $output_mode = 'html';
208: $show = 'grouped';
209: #
210: $r->print(&CreateInterface());
211: $r->print('<input type="hidden" name="statsfirstcall" value="no" />');
212: $r->print('<input type="hidden" name="sortby" value="'.$ENV{'form.sortby'}.
213: '" />');
214: if (! exists($ENV{'form.statsfirstcall'})) {
215: return;
216: }
217: #
218: &Gather_Student_Data($r);
219: #
220: #
221: if ($output_mode eq 'html') {
222: $r->print("<h2>".
223: $ENV{'course.'.$ENV{'request.course.id'}.'.description'}.
224: "</h2>\n");
225: $r->print("<h3>".localtime(time)."</h3>");
226: $r->rflush();
227: if ($show eq 'grouped') {
228: &output_html_grouped_by_sequence($r);
229: } elsif ($show eq 'ungrouped') {
230: &output_html_ungrouped($r);
231: }
232: } else {
233: $r->print("<h1>Not implemented</h1>");
234: }
235: return;
236: }
237:
238: sub output_html_grouped_by_sequence {
239: my ($r) = @_;
240: #$r->print(&ProblemStatisticsLegend());
241: my @Header = ("Title","Part","#Stdnts","Tries","Mod",
242: "Mean","#YES","#yes","%Wrng","DoDiff",
243: "S.D.","Skew.");#,"D.F.1st","D.F.2nd");
244: # #FFFFE6 #EEFFCC #DDFFFF FFDDDD #DDFFDD #FFDDFF
245: foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()) {
246: next if ($sequence->{'num_assess'}<1);
247: $r->print("<h3>".$sequence->{'title'}."</h3>");
248: $r->print('<table border="0"><tr><td bgcolor="#777777">'."\n");
249: $r->print('<table border="0" cellpadding="3">'."\n");
250: $r->print('<tr bgcolor="#FFFFE6"><th>'.
251: join("</th><th>",@Header)."</th></tr>\n");
252: foreach my $resource (@{$sequence->{'contents'}}) {
253: next if ($resource->{'type'} ne 'assessment');
254: foreach my $part (@{$resource->{'parts'}}) {
255: if ($part == 0) {
256: $part = ' ';
257: }
258: my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD,
259: $SKEW) = &Apache::loncoursedata::get_problem_statistics
260: (undef,$resource->{'symb'},$part,
261: $ENV{'request.course.id'});
262: my $wrongpercent = 0;
263: if (defined($num) && $num > 0) {
264: $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10;
265: }
266: $r->print('<tr>'.&statistics_html_table_data
267: ($resource,$part,$num,$tries,$mod,$mean,$Solved,
268: $solved,$wrongpercent,$DegOfDiff,$STD,$SKEW).
269: "</tr>\n");
270: }
271: }
272: $r->print("</table>\n");
273: $r->print("</td></tr></table>\n");
274: $r->rflush();
275: }
276: #
277: return;
278: }
279:
280:
281: ###############################################
282: ###############################################
283:
284: ###############################################
285: ###############################################
286: sub output_html_ungrouped {
287: my ($r) = @_;
288: #
289: my $sortby = $ENV{'form.sortby'};
290: if (! defined($sortby) || $sortby eq '') {
291: $sortby = 'sequence';
292: }
293: #
294: my $show_container = 0;
295: #$r->print(&ProblemStatisticsLegend());
296: my @Header = ("Title","Part","#Stdnts","Tries","Mod",
297: "Mean","#YES","#yes","%Wrng","DoDiff",
298: "S.D.","Skew.");#,"D.F.1st","D.F.2nd");
299: # #FFFFE6 #EEFFCC #DDFFFF FFDDDD #DDFFDD #FFDDFF
300: my @Sequences = &Apache::lonstatistics::Sequences_with_Assess();
301: if (@Sequences > 1) {
302: unshift(@Header,"Container");
303: $show_container = 1;
304: }
305: #
306: $r->print('<table border="0"><tr><td bgcolor="#777777">'."\n");
307: $r->print('<table border="0" cellpadding="3">'."\n");
308: my $Str = '';
309: foreach (@Header) {
310: $Str .= '<th>'.
311: '<a href="javascript:document.Statistics.sortby.value='."'$_'".
312: ';document.Statistics.submit();">'.
313: $_.'</a></th>';
314: }
315: $r->print('<tr bgcolor="#FFFFE6">'.$Str."</tr>\n");
316: $r->rflush();
317: #
318: foreach my $sequence (@Sequences) {
319: next if ($sequence->{'num_assess'}<1);
320: foreach my $resource (@{$sequence->{'contents'}}) {
321: next if ($resource->{'type'} ne 'assessment');
322: foreach my $part (@{$resource->{'parts'}}) {
323: my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD,
324: $SKEW) = &Apache::loncoursedata::get_problem_statistics
325: (undef,$resource->{'symb'},$part,
326: $ENV{'request.course.id'});
327: if ($part == 0) {
328: $part = ' ';
329: }
330: my $wrongpercent = 0;
331: if (defined($num) && $num > 0) {
332: $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10;
333: }
334: if ($show_container) {
335: $r->print('<tr>'.
336: '<td bgcolor="#FFFFE6">'.$sequence->{'title'}.
337: '</td>'.
338: &statistics_html_table_data
339: ($resource,$part,$num,$tries,$mod,$mean,$Solved,
340: $solved,$wrongpercent,$DegOfDiff,$STD,$SKEW).
341: "</tr>\n");
342: } else {
343: $r->print('<tr>'.&statistics_html_table_data
344: ($resource,$part,$num,$tries,$mod,$mean,$Solved,
345: $solved,$wrongpercent,$DegOfDiff,$STD,$SKEW).
346: "</tr>\n");
347: }
348: }
349: }
350: }
351: $r->print("</table>\n");
352: $r->print("</td></tr></table>\n");
353: $r->rflush();
354: #
355: return;
356: }
357:
358: ###############################################
359: ###############################################
360:
361: ###############################################
362: ###############################################
363: sub statistics_html_table_data {
364: my ($resource,$part,$num,$tries,$mod,$mean,$Solved,$solved,$wrongpercent,
365: $DegOfDiff,$STD,$SKEW) = @_;
366: my $row = '';
367: $row .= '<td bgcolor="#FFFFE6">'.
368: '<a href="'.$resource->{'src'}.'" target="_blank" >'.
369: $resource->{'title'}.'</a>'.
370: '</td>';
371: $row .= '<td bgcolor="#FFFFE6">'.$part.'</td>' if (defined($part));
372: foreach ($num,$tries) {
373: $row .= '<td bgcolor="#EEFFCC" align="right">'.$_.'</td>';
374: }
375: foreach ($mod,$mean) {
376: $row .= '<td bgcolor="#DDFFFF" align="right">'.
377: sprintf("%5.2f",$_).'</td>';
378: }
379: foreach ($Solved,$solved) {
380: $row .= '<td bgcolor="#DDFFFF" align="right">'.$_.'</td>';
381: }
382: foreach ($wrongpercent) {
383: $row .= '<td bgcolor="#DDFFFF" align="right">'.
384: sprintf("%5.1f",$_).'</td>';
385: }
386: foreach ($DegOfDiff,$STD,$SKEW) {
387: $row .= '<td bgcolor="#FFDDDD" align="right">'.
388: sprintf("%5.2f",$_).'</td>';
389: }
390: return $row;
391: }
392:
393:
394: ###############################################
395: ###############################################
396:
397: sub BuildGraphicChart {
398: my ($graph,$cacheDB,$courseDescription,$students,$courseID,$r,$c)=@_;
399: my %cache;
400: my $max;
401: my $title = '';
402: if($graph eq 'DoDiffGraph') {
403: $title = 'Degree-of-Difficulty';
404: } else {
405: $title = 'Wrong-Percentage';
406: }
407: my $currentSequence = -1;
408: my $sortProblems = 'Sort Within Sequence';
409: my ($result, $orderedProblems) =
410: &InitializeProblemStatistics($cacheDB, $students, $courseID, $c, $r);
411: if($result ne 'OK') {
412: return;
413: }
414: my @values = ();
415: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
416: return 'Unable to tie database.7';
417: }
418: foreach(@$orderedProblems) {
419: my ($sequence,$problem,$part)=split(':', $_);
420: if($cache{'StatisticsMaps'} ne 'All Maps' &&
421: $cache{'StatisticsMaps'} ne $cache{$sequence.':title'}) {
422: next;
423: }
424: if( $currentSequence == -1 ||
425: ($sortProblems eq 'Sort Within Sequence' &&
426: $currentSequence != $sequence)) {
427: if($currentSequence != -1) {
428: &DrawGraph(\@values,$courseDescription,$title,$max,$r);
429: }
430: if($sortProblems eq 'Sort Within Sequence') {
431: $r->print('<br><b>'.$cache{$sequence.':title'}.'</b>'."\n");
432: }
433: $currentSequence = $sequence;
434: @values = ();
435: $max=0;
436: }
437: my $data = 0;
438: if($graph eq 'DoDiffGraph') {
439: $data = sprintf("%.2f", $cache{$_.':degreeOfDifficulty'}),
440: } else {
441: $data = sprintf("%.1f", $cache{$_.':percentWrong'}),
442: }
443: if($max < $data) {
444: $max = $data;
445: }
446: push(@values, $data);
447: }
448: untie(%cache);
449: &DrawGraph(\@values,$courseDescription,$title,$max,$r);
450: return;
451: }
452:
453: sub DrawGraph {
454: my ($values,$courseDescription,$title,$Max,$r)=@_;
455: my $sendValues = join(',', @$values);
456: my $sendCount = scalar(@$values);
457: $r->print("<br>The Maximum Value is: $Max");
458: if ( $Max > 1 ) {
459: if ($Max % 10) {
460: if ( int($Max) < $Max ) {
461: $Max++;
462: $Max = int($Max);
463: }
464: }
465: #(10 - $Max % 10);
466: } else { $Max = 1; }
467: my @GData = ('','Problem_number',$title,$Max,$sendCount,$sendValues);
468: # $r->print('</form>'."\n");
469: $r->print('<br>'."\n");
470: $r->print('<IMG src="/cgi-bin/graph.png?'.
471: (join('&', @GData)).'" border="1" />');
472: # $r->print('<form>'."\n");
473: $r->print('<br>'."\n");
474: }
475:
476: #---- Problem Statistics Web Page ---------------------------------------
477: sub CreateProblemStatisticsTableHeading {
478: my ($headings,$r)=@_;
479: my $Str='';
480: $Str .= '<tr>'."\n";
481: $Str .= '<th bgcolor="#ffffe6">P#</th>'."\n";
482: foreach(@$headings) {
483: $Str .= '<th bgcolor="#ffffe6">';
484: $Str .= '<a href="/adm/statistics?reportSelected=';
485: $Str .= &Apache::lonnet::escape('Problem Statistics');
486: $Str .= '&ProblemStatisticsSort=';
487: $Str .= &Apache::lonnet::escape($_).'">'.$_.'</a> </th>'."\n";
488: }
489: $Str .= "\n".'</tr>'."\n";
490: return $Str;
491: }
492:
493: sub BuildStatisticsTable {
494: my ($cache,$displayFormat,$sortProblems,$orderedProblems,$headings,
495: $r,$color)=@_;
496: my $count = 1;
497: my $currentSequence = -1;
498: foreach(@$orderedProblems) {
499: my ($sequence,$problem,$part)=split(':', $_);
500: if($cache->{'StatisticsMaps'} ne 'All Maps' &&
501: $cache->{'StatisticsMaps'} ne $cache->{$sequence.':title'}) {
502: next;
503: }
504: if($currentSequence == -1 ||
505: ($sortProblems eq 'Sort Within Sequence' &&
506: $currentSequence != $sequence)) {
507: if($displayFormat ne 'Display CSV Format') {
508: if($currentSequence ne -1) {
509: $r->print('</table>');
510: $r->print('</td></tr></table><br>');
511: }
512: if($sortProblems eq 'Sort Within Sequence') {
513: $r->print('<b>'.$cache->{$sequence.':title'}.'</b>');
514: }
515: $r->print('<table border="0"><tr><td bgcolor="#777777">'."\n");
516: $r->print('<table border="0" cellpadding="3">'."\n");
517: $r->print(&CreateProblemStatisticsTableHeading($headings, $r));
518: } else {
519: if($sortProblems eq 'Sort Within Sequence') {
520: $r->print('"'.$cache->{$sequence.':title'}.'"');
521: }
522: $r->print('<br>');
523: }
524: $currentSequence = $sequence;
525: }
526: my $ref = '<a href="'.$cache->{$problem.':source'}.
527: '" target="_blank">'.$cache->{$problem.':title'}.'</a>';
528: my $title = $cache->{$problem.':title'};
529: if($part != 0) {
530: $title .= ' Part '.$part;
531: }
532: my $source = $cache->{$problem.':source'};
533: my $tableData = join('&', $ref, $title, $source,
534: $cache->{$_.':studentCount'},
535: $cache->{$_.':totalTries'},
536: $cache->{$_.':maxTries'},
537: $cache->{$_.':mean'},
538: $cache->{$_.':correct'},
539: $cache->{$_.':correctByOverride'},
540: $cache->{$_.':percentWrong'},
541: $cache->{$_.':degreeOfDifficulty'},
542: $cache->{$_.':standardDeviation'},
543: $cache->{$_.':skewness'},
544: $cache->{$_.':discriminationFactor1'},
545: $cache->{$_.':discriminationFactor2'});
546: &TableRow($displayFormat,$tableData,$count,$r,$color);
547: $count++;
548: }
549: if($displayFormat ne 'Display CSV Format') {
550: $r->print('</table>'."\n");
551: $r->print('</td></tr></table>');
552: } else {
553: $r->print('<br>');
554: }
555: return;
556: }
557:
558: sub TableRow {
559: my ($displayFormat,$Str,$RealIdx,$r,$color)=@_;
560: my($ref,$title,$source,$StdNo,$TotalTries,$MxTries,$Avg,$YES,$Override,
561: $Wrng,$DoD,$SD,$Sk,$_D1,$_D2)=split(/\&/,$Str);
562: my $Ptr;
563: if($displayFormat eq 'Display CSV Format') {
564: $Ptr='"'.$RealIdx.'",'."\n".
565: '"'.$title.'",'."\n".
566: '"'.$source.'",'."\n".
567: '"'.$StdNo.'",'."\n".
568: '"'.$TotalTries.'",'."\n".
569: '"'.$MxTries.'",'."\n".
570: '"'.$Avg.'",'."\n".
571: '"'.$YES.'",'."\n".
572: '"'.$Override.'",'."\n".
573: '"'.$Wrng.'",'."\n".
574: '"'.$DoD.'",'."\n".
575: '"'.$SD.'",'."\n".
576: '"'.$Sk.'",'."\n".
577: '"'.$_D1.'",'."\n".
578: '"'.$_D2.'"'."\n".
579: "<br>\n";
580: $r->print("\n".$Ptr);
581: } else {
582: $Ptr='<tr>'."\n".
583: '<td bgcolor="#ffffe6">'.$RealIdx.'</td>'."\n".
584: '<td bgcolor="#ffffe6">'.$ref.'</td>'."\n".
585: '<td bgcolor='.$color->{"yellow"}.'> '.$StdNo.'</td>'."\n".
586: '<td bgcolor='.$color->{"yellow"}.'>'.$TotalTries.'</td>'."\n".
587: '<td bgcolor='.$color->{"yellow"}.'>'.$MxTries.'</td>'."\n".
588: '<td bgcolor='.$color->{"gb"}.'>'.$Avg.'</td>'."\n".
589: '<td bgcolor='.$color->{"gb"}.'> '.$YES.'</td>'."\n".
590: '<td bgcolor='.$color->{"gb"}.'> '.$Override.'</td>'."\n".
591: '<td bgcolor='.$color->{"red"}.'> '.$Wrng.'</td>'."\n".
592: '<td bgcolor='.$color->{"red"}.'> '.$DoD.'</td>'."\n".
593: '<td bgcolor='.$color->{"green"}.'> '.$SD.'</td>'."\n".
594: '<td bgcolor='.$color->{"green"}.'> '.$Sk.'</td>'."\n".
595: '<td bgcolor='.$color->{"purple"}.'> '.$_D1.'</td>'."\n".
596: '<td bgcolor='.$color->{"purple"}.'> '.$_D2.'</td>'."\n";
597: $r->print($Ptr.'</tr>'."\n");
598: }
599: return;
600: }
601:
602: # For loading the colored table for display or un-colored for print
603: sub setbgcolor {
604: my $PrintTable=shift;
605: my %color;
606: if ($PrintTable){
607: $color{"gb"}="#FFFFFF";
608: $color{"red"}="#FFFFFF";
609: $color{"yellow"}="#FFFFFF";
610: $color{"green"}="#FFFFFF";
611: $color{"purple"}="#FFFFFF";
612: } else {
613: $color{"gb"}="#DDFFFF";
614: $color{"red"}="#FFDDDD";
615: $color{"yellow"}="#EEFFCC";
616: $color{"green"}="#DDFFDD";
617: $color{"purple"}="#FFDDFF";
618: }
619: return \%color;
620: }
621:
622: sub ProblemStatisticsButtons {
623: my ($displayFormat, $displayLegend, $sortProblems)=@_;
624: my $Ptr = '<tr><td></td><td align="left">';
625: $Ptr .= '<input type="submit" name="DoDiffGraph" ';
626: $Ptr .= 'value="Plot Degree of Difficulty" />'."\n";
627: $Ptr .= '</td><td align="left">';
628: $Ptr .= '<input type="submit" name="PercentWrongGraph" ';
629: $Ptr .= 'value="Plot Percent Wrong" />'."\n";
630: $Ptr .= '</td></tr><tr><td></td><td>'."\n";
631: $Ptr .= '<input type="submit" name="SortProblems" ';
632: if($sortProblems eq 'Sort All Problems') {
633: $Ptr .= 'value="Sort Within Sequence" />'."\n";
634: } else {
635: $Ptr .= 'value="Sort All Problems" />'."\n";
636: }
637: $Ptr .= '</td><td align="left">';
638: $Ptr .= '<input type="submit" name="DisplayLegend" ';
639: if($displayLegend eq 'Show Legend') {
640: $Ptr .= 'value="Hide Legend" />'."\n";
641: } else {
642: $Ptr .= 'value="Show Legend" />'."\n";
643: }
644: $Ptr .= '</td><td align="left">';
645: $Ptr .= '<input type="submit" name="DisplayCSVFormat" ';
646: if($displayFormat eq 'Display CSV Format') {
647: $Ptr .= 'value="Display Table Format" />'."\n";
648: } else {
649: $Ptr .= 'value="Display CSV Format" />'."\n";
650: }
651: $Ptr .= '</td></tr>';
652: return $Ptr;
653: }
654:
655: sub ProblemStatisticsLegend {
656: my $Ptr = '';
657: $Ptr = '<table border="0">';
658: $Ptr .= '<tr><td>';
659: $Ptr .= '<b>#Stdnts</b></td>';
660: $Ptr .= '<td>Total number of students attempted the problem.';
661: $Ptr .= '</td></tr><tr><td>';
662: $Ptr .= '<b>Tries</b></td>';
663: $Ptr .= '<td>Total number of tries for solving the problem.';
664: $Ptr .= '</td></tr><tr><td>';
665: $Ptr .= '<b>Mod</b></td>';
666: $Ptr .= '<td>Largest number of tries for solving the problem by a student.';
667: $Ptr .= '</td></tr><tr><td>';
668: $Ptr .= '<b>Mean</b></td>';
669: $Ptr .= '<td>Average number of tries. [ Tries / #Stdnts ]';
670: $Ptr .= '</td></tr><tr><td>';
671: $Ptr .= '<b>#YES</b></td>';
672: $Ptr .= '<td>Number of students solved the problem correctly.';
673: $Ptr .= '</td></tr><tr><td>';
674: $Ptr .= '<b>#yes</b></td>';
675: $Ptr .= '<td>Number of students solved the problem by override.';
676: $Ptr .= '</td></tr><tr><td>';
677: $Ptr .= '<b>%Wrong</b></td>';
678: $Ptr .= '<td>Percentage of students who tried to solve the problem ';
679: $Ptr .= 'but is still incorrect. [ 100*((#Stdnts-(#YES+#yes))/#Stdnts) ]';
680: $Ptr .= '</td></tr><tr><td>';
681: $Ptr .= '<b>DoDiff</b></td>';
682: $Ptr .= '<td>Degree of Difficulty of the problem. ';
683: $Ptr .= '[ 1 - ((#YES+#yes) / Tries) ]';
684: $Ptr .= '</td></tr><tr><td>';
685: $Ptr .= '<b>S.D.</b></td>';
686: $Ptr .= '<td>Standard Deviation of the tries. ';
687: $Ptr .= '[ sqrt(sum((Xi - Mean)^2)) / (#Stdnts-1) ';
688: $Ptr .= 'where Xi denotes every student\'s tries ]';
689: $Ptr .= '</td></tr><tr><td>';
690: $Ptr .= '<b>Skew.</b></td>';
691: $Ptr .= '<td>Skewness of the students tries.';
692: $Ptr .= '[(sqrt( sum((Xi - Mean)^3) / #Stdnts)) / (S.D.^3)]';
693: $Ptr .= '</td></tr><tr><td>';
694: $Ptr .= '<b>Dis.F.</b></td>';
695: $Ptr .= '<td>Discrimination Factor: A Standard for evaluating the ';
696: $Ptr .= 'problem according to a Criterion<br>';
697: $Ptr .= '<b>[Criterion to group students into %27 Upper Students - ';
698: $Ptr .= 'and %27 Lower Students]</b><br>';
699: $Ptr .= '<b>1st Criterion</b> for Sorting the Students: ';
700: $Ptr .= '<b>Sum of Partial Credit Awarded / Total Number of Tries</b><br>';
701: $Ptr .= '<b>2nd Criterion</b> for Sorting the Students: ';
702: $Ptr .= '<b>Total number of Correct Answers / Total Number of Tries</b>';
703: $Ptr .= '</td></tr>';
704: $Ptr .= '<tr><td><b>Disc.</b></td>';
705: $Ptr .= '<td>Number of Students had at least one discussion.';
706: $Ptr .= '</td></tr></table>';
707: return $Ptr;
708: }
709:
710: #---- END Problem Statistics Web Page ----------------------------------------
711:
712: 1;
713: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>