1: # The LearningOnline Network with CAPA
2: #
3: # $Id: loncorrectproblemplot.pm,v 1.2 2004/02/02 21:51:52 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:
28: package Apache::loncorrectproblemplot;
29:
30: use strict;
31: use Apache::lonnet();
32: use Apache::loncommon();
33: use Apache::lonhtmlcommon();
34: use Apache::loncoursedata();
35: use Apache::lonstatistics;
36: use Apache::lonstathelpers;
37: use Apache::lonlocal;
38:
39: my $plotcolors = ['#33ff00',
40: '#ff33cc', '#990000', '#aaaa66', '#663399', '#ff9933',
41: '#66ccff', '#ff9999', '#cccc33', '#660000', '#33cc66',
42: ];
43:
44: my @SubmitButtons = (
45: { name => 'CreatePlot',
46: text => 'Create Plot' },
47: { name => 'ClearCache',
48: text => 'Clear Caches' },
49: { name => 'updatecaches',
50: text => 'Update Student Data' },
51: );
52:
53: sub BuildCorrectProblemsPage {
54: my ($r,$c)=@_;
55: #
56: my %Saveable_Parameters = ('Status' => 'scalar',
57: 'Section' => 'array');
58: &Apache::loncommon::store_course_settings('correct_problems_plot',
59: \%Saveable_Parameters);
60: &Apache::loncommon::restore_course_settings('correct_problems_plot',
61: \%Saveable_Parameters);
62: #
63: &Apache::lonstatistics::PrepareClasslist();
64: #
65: $r->print('<h2>'.&mt('Number of Correct Problems Plot').'</h2>');
66: $r->print(&CreateInterface());
67: #
68: my @Students = @Apache::lonstatistics::Students;
69: #
70: if (@Students < 1) {
71: $r->print('<h2>'.
72: &mt('There are no students in the sections selected').
73: '</h2>');
74: }
75: #
76: &Apache::loncoursedata::clear_internal_caches();
77: if (exists($ENV{'form.ClearCache'}) ||
78: exists($ENV{'form.updatecaches'}) ||
79: (exists($ENV{'form.firstanalysis'}) &&
80: $ENV{'form.firstanalysis'} ne 'no')) {
81: &Apache::lonstatistics::Gather_Full_Student_Data($r);
82: }
83: if (! exists($ENV{'form.firstanalysis'})) {
84: $r->print('<input type="hidden" name="firstanalysis" value="yes" />');
85: } else {
86: $r->print('<input type="hidden" name="firstanalysis" value="no" />');
87: }
88: foreach my $button (@SubmitButtons) {
89: $r->print('<input type="submit" name="'.$button->{'name'}.'" '.
90: 'value="'.&mt($button->{'text'}).'" />');
91: $r->print(' 'x5);
92: }
93: $r->rflush();
94: #
95: # Determine which problem symbs we are to sum over
96: if (exists($ENV{'form.CreatePlot'})) {
97: my @ProblemSymbs;
98: if ($Apache::lonstatistics::SelectedMaps[0] ne 'all') {
99: foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()){
100: foreach my $res (@{$seq->{'contents'}}) {
101: next if ($res->{'type'} ne 'assessment');
102: foreach my $part (@{$res->{'parts'}}) {
103: push(@ProblemSymbs,{symb=>$res->{'symb'},
104: part=>$part});
105: }
106: }
107: }
108: }
109: my $score_data = &Apache::loncoursedata::get_student_scores
110: (\@Apache::lonstatistics::SelectedSections,
111: \@ProblemSymbs,
112: $Apache::lonstatistics::enrollment_status);
113: $r->print(&AnalyzeScoreData($score_data));
114: }
115: return;
116: }
117:
118: #########################################################
119: #########################################################
120:
121: =pod
122:
123: =item & AnalyzeScoreData($score_data)
124:
125: Analyze the result of &Apache::loncoursedata::get_student_scores() and
126: return html with a plot of the data and a table of the values and bins.
127:
128: =cut
129:
130: #########################################################
131: #########################################################
132: sub AnalyzeScoreData {
133: my ($score_data) = @_;
134: #
135: # Basic check first
136: if (@$score_data < 1) {
137: return '<h2>There is no data to plot</h2>';
138: }
139: #
140: # Determine which bins to use
141: my $lowest = $score_data->[0]->[0];
142: $lowest = 0;
143: my $highest = $score_data->[-1]->[0];
144: my $binsize = 1;
145: if ($highest > 50) { $binsize = 2; }
146: if ($highest > 100) { $binsize = 5; }
147: if ($highest > 200) { $binsize = 10; }
148: if ($highest > 500) { $binsize = 20; }
149: if ($highest > 1000) { $binsize = 50; }
150: if ($highest > 2000) { $binsize = 100; }
151: #
152: # Get the data into the bins (destroying $score_data in the process)
153: my @Bins = &bin_data($score_data,$binsize,$lowest,$highest);
154: my @Xdata; my @Ydata; my $max;
155: my $Str = '<table border="1">'."\n".'<tr><th>Range</th><th>Count</th></tr>'."\n";
156: while (my $bin = shift(@Bins)) {
157: push (@Xdata,$bin->{'start'});
158: push (@Ydata,$bin->{'count'});
159: if ($bin->{'count'} > $max) {
160: $max = $bin->{'count'};
161: }
162: $Str.= '<tr><td>'.$bin->{'start'}.' - '.$bin->{'end'}.'</td>'.
163: '<td>'.$bin->{'count'}.'</td></tr>'."\n";
164: }
165: my $title = '';
166: $Str .= "</table><br />\n";
167: $Str = "<br />\n".&Apache::loncommon::DrawBarGraph($title,
168: 'Num Correct Problems',
169: 'Number of students',
170: $max,
171: undef, # colors
172: \@Xdata,
173: \@Ydata).
174: "\n<br />\n".$Str;
175: return $Str;
176: }
177:
178:
179: #########################################################
180: #########################################################
181:
182: =pod
183:
184: =item &bin_data($data,$binsize,$startbin,$endbin)
185:
186: Note: This routine destroys the array of data passed to it.
187:
188: Inputs: $data: array reference - the contents of @$data must
189: be arrays with x and y data. $data = [ [x1,y1],[x2,y2],...];
190: $binsize: Width of bins to put data in
191: $startbin: the starting bin.
192: $endbin: the ending bin.
193: Returns: Array of Bins. Each bin is a hash reference with the following
194: keys: 'start', 'count', and 'end'.
195:
196: =cut
197:
198: #########################################################
199: #########################################################
200: sub bin_data {
201: my ($data,$binsize,$startbin,$endbin)=@_;
202: return () if (! defined($data) || ref($data) ne 'ARRAY');
203: #
204: # Determine bin geometry
205: my $binstart = $startbin;
206: my $binend = $startbin+$binsize;
207: # put the data into bins
208: my @Bins;
209: my $count=0;
210: my $idx=0;
211: while ($idx < scalar(@$data) && ($binend-$endbin)<$binsize) {
212: my $dataset = $data->[$idx++];
213: my ($x,$y) = @{$dataset};
214: while ($x > $binend) {
215: # store the old data
216: push (@Bins,{ start => $binstart,
217: count => $count,
218: end => $binend });
219: # start counting again
220: $binstart += $binsize;
221: $binend += $binsize;
222: $count = 0;
223: }
224: $count+=$y;
225: }
226: return @Bins;
227: }
228:
229: #########################################################
230: #########################################################
231:
232: =pod
233:
234: =item &CreateInterface
235:
236: Inputs: none.
237:
238: Returns: HTML for the correct problems plot interface.
239:
240: =cut
241:
242: #########################################################
243: #########################################################
244: sub CreateInterface {
245: ##
246: ## Environment variable initialization
247: my $Str;
248: $Str .= '<table cellspacing="5">'."\n";
249: $Str .= '<tr>';
250: $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
251: $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
252: $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
253: $Str .= '</tr>'."\n";
254: ##
255: ##
256: $Str .= '<tr><td align="center">'."\n";
257: $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
258: $Str .= '</td>';
259: #
260: $Str .= '<td align="center">';
261: $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
262: $Str .= '</td><td>'."\n";
263: #
264: my $only_seq_with_assessments = sub {
265: my $s=shift;
266: if ($s->{'num_assess'} < 1) {
267: return 0;
268: } else {
269: return 1;
270: }
271: };
272: $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
273: $only_seq_with_assessments);
274: $Str .= '</td><td>'."\n";
275: ##
276: $Str .= '</tr>'."\n";
277: $Str .= '</table>'."\n";
278: return $Str;
279: }
280:
281: 1;
282:
283: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>