version 1.15, 2004/06/04 21:42:19
|
version 1.27, 2006/08/18 15:15:38
|
Line 28
|
Line 28
|
package Apache::lonsubmissiontimeanalysis; |
package Apache::lonsubmissiontimeanalysis; |
|
|
use strict; |
use strict; |
use Apache::lonnet(); |
use Apache::lonnet; |
use Apache::loncommon(); |
use Apache::loncommon(); |
use Apache::lonhtmlcommon(); |
use Apache::lonhtmlcommon(); |
use Apache::loncoursedata(); |
use Apache::loncoursedata(); |
Line 37 use Apache::lonstathelpers;
|
Line 37 use Apache::lonstathelpers;
|
use Apache::lonlocal; |
use Apache::lonlocal; |
use HTML::Entities(); |
use HTML::Entities(); |
use Time::Local(); |
use Time::Local(); |
use Spreadsheet::WriteExcel(); |
|
|
|
my $plotcolors = ['#33ff00', |
my $plotcolors = ['#33ff00', |
'#ff33cc', '#990000', '#aaaa66', '#663399', '#ff9933', |
'#ff33cc', '#990000', '#aaaa66', '#663399', '#ff9933', |
Line 79 sub BuildSubmissionTimePage {
|
Line 78 sub BuildSubmissionTimePage {
|
&Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status'); |
&Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status'); |
$r->rflush(); |
$r->rflush(); |
# |
# |
if (! exists($ENV{'form.problemchoice'}) || |
if (! exists($env{'form.problemchoice'}) || |
exists($ENV{'form.SelectAnother'})) { |
exists($env{'form.SelectAnother'})) { |
$r->print('<input type="submit" name="" value="'. |
my $submit_button = '<input type="submit" name="" value="'. |
&mt('Graph Problem Submission Times').'" />'); |
&mt('Graph Problem Submission Times').'" />'; |
$r->print(' 'x5); |
$r->print($submit_button.' 'x5); |
$r->print('<h3>'.&mt('Please select a problem to analyze').'</h3>'); |
$r->print('<h3>'.&mt('Please select a problem to analyze').'</h3>'); |
$r->print(&Apache::lonstathelpers::ProblemSelector('.')); |
$r->print(&Apache::lonstathelpers::problem_selector('.', |
|
$submit_button)); |
} else { |
} else { |
foreach my $button (@SubmitButtons) { |
foreach my $button (@SubmitButtons) { |
$r->print('<input type="submit" name="'.$button->{'name'}.'" '. |
$r->print('<input type="submit" name="'.$button->{'name'}.'" '. |
Line 99 sub BuildSubmissionTimePage {
|
Line 99 sub BuildSubmissionTimePage {
|
# |
# |
# Determine which problem we are to analyze |
# Determine which problem we are to analyze |
my $current_problem = &Apache::lonstathelpers::get_target_from_id |
my $current_problem = &Apache::lonstathelpers::get_target_from_id |
($ENV{'form.problemchoice'}); |
($env{'form.problemchoice'}); |
# |
# |
my ($prev,$curr,$next) = |
my ($navmap,$prev,$curr,$next) = |
&Apache::lonstathelpers::get_prev_curr_next($current_problem, |
&Apache::lonstathelpers::get_prev_curr_next($current_problem, |
'.', |
'.', |
'part'); |
'part'); |
if (exists($ENV{'form.PrevProblemAnalysis'}) && defined($prev)) { |
if (exists($env{'form.PrevProblemAnalysis'}) && defined($prev)) { |
$current_problem = $prev; |
$current_problem = $prev; |
} elsif (exists($ENV{'form.NextProblemAnalysis'}) && defined($next)) { |
} elsif (exists($env{'form.NextProblemAnalysis'}) && defined($next)) { |
$current_problem = $next; |
$current_problem = $next; |
} else { |
} else { |
$current_problem = $curr; |
$current_problem = $curr; |
} |
} |
# |
# |
# Store the current problem choice and send it out in the form |
# Store the current problem choice and send it out in the form |
$ENV{'form.problemchoice'} = |
$env{'form.problemchoice'} = |
&Apache::lonstathelpers::make_target_id($current_problem); |
&Apache::lonstathelpers::make_target_id($current_problem); |
$r->print('<input type="hidden" name="problemchoice" value="'. |
$r->print('<input type="hidden" name="problemchoice" value="'. |
$ENV{'form.problemchoice'}.'" />'); |
$env{'form.problemchoice'}.'" />'); |
# |
# |
$r->print('<hr />'); |
$r->print('<hr />'); |
$r->rflush(); |
$r->rflush(); |
Line 126 sub BuildSubmissionTimePage {
|
Line 126 sub BuildSubmissionTimePage {
|
if (! defined($resource)) { |
if (! defined($resource)) { |
$r->print('resource is undefined'); |
$r->print('resource is undefined'); |
} else { |
} else { |
$r->print('<h1>'.$resource->{'title'}.'</h1>'); |
$r->print('<h1>'.$resource->compTitle.'</h1>'); |
$r->print('<h3>'.$resource->{'src'}.'</h3>'); |
$r->print('<h3>'.$resource->src.'</h3>'); |
|
$r->print('<h4>'. |
|
&Apache::lonstatistics::section_and_enrollment_description(). |
|
'</h4>'); |
$r->rflush(); |
$r->rflush(); |
$r->print(&Apache::lonstathelpers::render_resource($resource)); |
$r->print(&Apache::lonstathelpers::render_resource($resource)); |
$r->print('<br />'); |
$r->print('<br />'); |
$r->rflush(); |
$r->rflush(); |
$r->print(&analyze_times($r,$resource,\@Students, |
$r->print(&analyze_times($r,$resource->symb,\@Students, |
$current_problem->{'part'})); |
$current_problem->{'part'})); |
} |
} |
$r->print('<hr />'); |
$r->print('<hr />'); |
Line 158 sub get_week_start {
|
Line 161 sub get_week_start {
|
} |
} |
|
|
sub analyze_times { |
sub analyze_times { |
my ($r,$resource,$students,$part) = @_; |
my ($r,$symb,$students,$part) = @_; |
|
my $htmltable; |
# |
# |
# Convenience arrays |
# Convenience arrays |
my @FullWeekDay = (qw/Sunday Monday Tuesday Wednesday Thursday Friday |
my @FullWeekDay = (qw/Sunday Monday Tuesday Wednesday Thursday Friday |
Line 169 sub analyze_times {
|
Line 173 sub analyze_times {
|
my $html; # holds results of analysis |
my $html; # holds results of analysis |
# Get the data |
# Get the data |
my $SubData = &Apache::loncoursedata::get_response_time_data |
my $SubData = &Apache::loncoursedata::get_response_time_data |
($students,$resource->{'symb'},$part); |
([&Apache::lonstatistics::get_selected_sections()], |
|
[&Apache::lonstatistics::get_selected_groups()], |
|
$Apache::lonstatistics::enrollment_status, |
|
$symb,$part); |
if (! defined($SubData) || ! ref($SubData)) { |
if (! defined($SubData) || ! ref($SubData)) { |
$html.= '<h2>There is no submission data for this problem</h2>'; |
$html.= '<h2>There is no submission data for this problem at all</h2>'; |
return $html; |
return $html; |
} |
} |
my $NumSub = scalar(@{$SubData}); |
my $NumSub = scalar(@{$SubData}); |
Line 192 sub analyze_times {
|
Line 199 sub analyze_times {
|
my $endtime = $day_start; |
my $endtime = $day_start; |
# |
# |
# Initialize loop variables |
# Initialize loop variables |
my $max; |
my $max; # The sum of @Ydata |
my @Ydata=(0); |
my @Ydata=(0); # number of submissions |
my @AnsData=(0); |
my @AnsData=(0); # number of correct submissions |
my @Xlabel=($WeekDay[$wday]); |
my @Xlabel=($WeekDay[$wday]); # Labels of itmes |
my $cumulative_answers = 0; |
my @BinEnd; # The end time of each bin |
|
my $cumulative_answers = 0; # The sum of @AnsData |
|
my %students; # which students have attempted the problem? |
# |
# |
foreach my $row (@$SubData) { |
foreach my $row (@$SubData) { |
my $subtime = &get_time_from_row($row); |
my $subtime = &get_time_from_row($row); |
while ($subtime > $endtime && $endtime < time) { |
while ($subtime > $endtime && $endtime < time) { |
# Create a new bin |
# Create a new bin |
$bincount++; |
$bincount++; |
$Ydata[$bincount]=0; |
$Ydata[$bincount] = 0; |
$AnsData[$bincount]=$AnsData[$bincount-1]; |
$AnsData[$bincount] = 0; |
$endtime += $binsize; |
$endtime += $binsize; |
|
push(@BinEnd,$endtime); |
if ($bincount % (86400/$binsize) == 0) { |
if ($bincount % (86400/$binsize) == 0) { |
$wday++; |
$wday++; |
$wday %= 7; |
$wday %= 7; |
Line 218 sub analyze_times {
|
Line 228 sub analyze_times {
|
$max = $Ydata[$bincount] if ($max < $Ydata[$bincount]); |
$max = $Ydata[$bincount] if ($max < $Ydata[$bincount]); |
$AnsData[$bincount] += &successful_submission($row); |
$AnsData[$bincount] += &successful_submission($row); |
$cumulative_answers += &successful_submission($row); |
$cumulative_answers += &successful_submission($row); |
|
$students{$row->[&Apache::loncoursedata::RT_student_id()]}++; |
} |
} |
foreach my $maximum (10,15,20,25,30,40,50,60,70,80,90,100, |
# |
120,150,200,250,300,350,400,450,500, |
# Pad the data to a full day |
600,700,800,900,1000,1100,1200,1500,2000, |
|
2500,3000,4000,5000) { |
|
if ($max < $maximum) { |
|
$max = $maximum; |
|
last; |
|
} |
|
} |
|
while ($bincount % $bins_per_day != 0) { |
while ($bincount % $bins_per_day != 0) { |
$bincount++; |
$bincount++; |
$Ydata[$bincount]=0; |
$Ydata[$bincount]=0; |
$AnsData[$bincount]=$AnsData[$bincount-1]; |
$AnsData[$bincount]=0; |
$endtime += $binsize; |
$endtime += $binsize; |
|
push(@BinEnd,$endtime); |
if ($bincount % (86400/$binsize) == 0) { |
if ($bincount % (86400/$binsize) == 0) { |
$wday ++; |
$wday ++; |
$wday %= 7; |
$wday %= 7; |
Line 241 sub analyze_times {
|
Line 246 sub analyze_times {
|
$Xlabel[$bincount] = ''; |
$Xlabel[$bincount] = ''; |
} |
} |
} |
} |
my $numstudents = scalar(@$students); |
my $numstudents = scalar(keys(%students)); |
for (my $i=0;$i<=$#AnsData;$i++) { |
# |
$AnsData[$i] = int(100*($AnsData[$i]/$numstudents)); |
# Determine a nice maximum value to use |
|
foreach my $maximum (10,15,20,25,30,40,50,60,70,80,90,100, |
|
120,150,200,250,300,350,400,450,500, |
|
600,700,800,900,1000,1100,1200,1500,2000, |
|
2500,3000,4000,5000) { |
|
if ($max < $maximum) { |
|
$max = $maximum; |
|
last; |
|
} |
|
} |
|
# |
|
# Build the data table |
|
$htmltable = '<p>'. |
|
'<table rules="groups" frame="border" '. |
|
'summary="Student submission data">'. |
|
'<thead>'. |
|
'<tr>'. |
|
'<th valign="bottom">'.&mt('Begin').'</th>'. |
|
'<th>'.(' 'x3).'</th>'. |
|
'<th valign="bottom">'.&mt('End').'</th>'. |
|
'<th valign="bottom">'.&mt('Submissions (plotted)').'</th>'. |
|
'<th>'.(' 'x3).'</th>'. |
|
'<th valign="bottom">'.&mt('Correct Submissions (not plotted)').'</th>'. |
|
'<th>'.(' 'x3).'</th>'. |
|
'<th valign="bottom">'.&mt('Cumulative Correct of those attempting the problem (not plotted)').'</th>'. |
|
'<th>'.(' 'x3).'</th>'. |
|
'<th valign="bottom">'.&mt('Cumulative Percent Correct of those attempting the problem (not plotted)').'</th>'. |
|
'<th>'.(' 'x3).'</th>'. |
|
'<th valign="bottom">'.&mt('Cumulative Percent Correct of selected students (plotted)').'</th>'. |
|
'</tr>'. |
|
'</thead>'. |
|
'<tbody>'; |
|
my @CumulativeCorrect=(0); |
|
my @corr_as_percent_of_selected; |
|
my @corr_as_percent_of_answering; |
|
for (my $i=0;$i<=$#Ydata;$i++) { |
|
$CumulativeCorrect[$i]=$CumulativeCorrect[-1]+$AnsData[$i]; |
|
$corr_as_percent_of_answering[$i] = |
|
sprintf('%3.1f',100*$CumulativeCorrect[$i]/$numstudents); |
|
$corr_as_percent_of_selected[$i] = |
|
sprintf('%3.1f',100*$CumulativeCorrect[$i]/scalar(@$students)); |
|
if ($Ydata[$i] != 0) { |
|
next if (! defined($BinEnd[$i]) || $BinEnd[$i] == 0); |
|
$htmltable .= |
|
'<tr>'. |
|
'<td align="right"><nobr>'. |
|
&Apache::lonlocal::locallocaltime($BinEnd[$i]-$binsize). |
|
'</nobr></td>'. |
|
'<td> </td>'. |
|
'<td align="right"><nobr>'. |
|
&Apache::lonlocal::locallocaltime($BinEnd[$i]).'</td>'. |
|
'</nobr></td>'. |
|
'<td align="right">'.$Ydata[$i].(' 'x3).'</td>'. |
|
'<td> </td>'. |
|
'<td align="right">'.$AnsData[$i].(' 'x3).'</td>'. |
|
'<td> </td>'. |
|
'<td align="right">'.$CumulativeCorrect[$i].'</td>'. |
|
'<td> </td>'. |
|
'<td align="right">'.$corr_as_percent_of_answering[$i].'</td>'. |
|
'<td> </td>'. |
|
'<td align="right">'.$corr_as_percent_of_selected[$i].'</td>'. |
|
'</tr>'.$/; |
|
} |
} |
} |
my $title = 'Number of Submissions and Number Correct'; |
$htmltable .= '</tbody></table></p>'; |
|
# |
|
# Build the plot |
|
my $title = '';#'Number of Submissions and Number Correct'; |
my $xlabel; |
my $xlabel; |
(undef,undef,undef,$mday,$month,$year,$wday) = localtime($day_start); |
(undef,undef,undef,$mday,$month,$year,$wday) = localtime($day_start); |
$xlabel .= $FullWeekDay[$wday].' '. |
$xlabel .= $FullWeekDay[$wday].' '. |
Line 257 sub analyze_times {
|
Line 327 sub analyze_times {
|
if ($width < 250) { |
if ($width < 250) { |
$width = 250; |
$width = 250; |
} |
} |
|
# |
$html .= &Apache::loncommon::DrawXYYGraph($title, |
$html .= &Apache::loncommon::DrawXYYGraph($title, |
$xlabel, |
$xlabel, |
'Submissions vs Time', |
'Submissions vs Time', |
$plotcolors, |
$plotcolors, |
\@Xlabel, |
\@Xlabel, |
\@Ydata, |
\@Ydata,0,$max, |
0,$max, |
\@corr_as_percent_of_selected,0,100, |
\@AnsData, |
|
0,100, |
|
(xskip => $bins_per_day, |
(xskip => $bins_per_day, |
x_ticks => $bins_per_day, |
x_ticks => $bins_per_day, |
x_tick_offset => $bins_per_day, |
x_tick_offset => $bins_per_day, |
Line 276 sub analyze_times {
|
Line 345 sub analyze_times {
|
'data.2.label'=>'Percent correct', |
'data.2.label'=>'Percent correct', |
) |
) |
); |
); |
$html .= '<br />'; |
$html .= '<br />'.$htmltable; |
return $html; |
return $html; |
} |
} |
|
|
Line 286 sub successful_submission {
|
Line 355 sub successful_submission {
|
return $row->[&Apache::loncoursedata::RT_awarded()]; |
return $row->[&Apache::loncoursedata::RT_awarded()]; |
} |
} |
return undef; |
return undef; |
return 0; |
|
} |
} |
|
|
sub get_time_from_row { |
sub get_time_from_row { |
Line 322 sub Process_Row {
|
Line 390 sub Process_Row {
|
sub CreateInterface { |
sub CreateInterface { |
## |
## |
## Environment variable initialization |
## Environment variable initialization |
if (! exists$ENV{'form.AnalyzeOver'}) { |
if (! exists$env{'form.AnalyzeOver'}) { |
$ENV{'form.AnalyzeOver'} = 'Tries'; |
$env{'form.AnalyzeOver'} = 'Tries'; |
} |
} |
## |
## |
## Build the menu |
## Build the menu |
my $Str = ''; |
my $Str = ''; |
$Str .= &Apache::lonhtmlcommon::breadcrumbs(undef,'Submission Time Plots'); |
$Str .= &Apache::lonhtmlcommon::breadcrumbs('Submission Time Plots'); |
$Str .= '<p>'; |
$Str .= '<p>'; |
$Str .= '<table cellspacing="5">'."\n"; |
$Str .= '<table cellspacing="5">'."\n"; |
$Str .= '<tr>'; |
$Str .= '<tr>'; |
$Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>'; |
$Str .= '<th align="center">'.&mt('Sections').'</th>'; |
$Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>'; |
$Str .= '<th align="center">'.&mt('Groups').'</th>'; |
|
$Str .= '<th align="center">'.&mt('Access Status').'</th>'; |
$Str .= '</tr>'."\n"; |
$Str .= '</tr>'."\n"; |
## |
## |
## |
## |
$Str .= '<tr><td align="center">'."\n"; |
$Str .= '<tr><td align="center">'."\n"; |
$Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5); |
$Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',4); |
|
$Str .= '</td>'; |
|
# |
|
$Str .= '<td align="center">'."\n"; |
|
$Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',4); |
$Str .= '</td>'; |
$Str .= '</td>'; |
# |
# |
$Str .= '<td align="center">'; |
$Str .= '<td align="center">'; |
$Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5); |
$Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,4); |
$Str .= '</td>'; |
$Str .= '</td>'; |
|
# |
$Str .= '</tr>'."\n"; |
$Str .= '</tr>'."\n"; |
$Str .= '</table>'."\n"; |
$Str .= '</table>'."\n"; |
# |
# |