version 1.94, 2004/10/15 16:50:30
|
version 1.96, 2004/10/27 17:47:13
|
Line 993 sub OR_tries_analysis {
|
Line 993 sub OR_tries_analysis {
|
} # End of concept loops |
} # End of concept loops |
# |
# |
# Build a table for the plots |
# Build a table for the plots |
my $analysis_html = "<table>\n"; |
my $analysis_html = "<br /><table>\n"; |
my $optionkey = &build_option_index($ORdata); |
my $optionkey = &build_option_index($ORdata); |
my $num_concepts = 1; |
my $num_concepts = 1; |
if (defined($Concepts)) { $num_concepts = scalar(@$Concepts); } |
if (defined($Concepts)) { $num_concepts = scalar(@$Concepts); } |
Line 1028 sub OR_tries_analysis {
|
Line 1028 sub OR_tries_analysis {
|
} |
} |
} |
} |
# |
# |
my $title; |
|
my $count = $response_data{'_total'}->[$try]; |
|
$title = 'Attempt '.$try.' (N='.$count.')'; |
|
$concept_graph = &Apache::loncommon::DrawBarGraph |
$concept_graph = &Apache::loncommon::DrawBarGraph |
($title,'Concept Number','Percent Correct', |
('Correct Concepts','Concept Number','Percent Correct', |
100,$plotcolors,undef,\@concept_plot_data); |
100,$plotcolors,undef,\@concept_plot_data); |
} |
} |
# |
# |
# Create Foil Plots |
# Create Foil Plots |
my $count = $response_data{'_total'}->[$try]; |
my $data_count = $response_data{'_total'}->[$try]; |
my $title = 'Attempt '.$try.' (N='.$count.')'; |
my $correct = $response_data{'_correct'}->[$try]; |
my @Datasets; |
my @Datasets; |
foreach my $option ('_correct',@{$ORdata->{'_Options'}}) { |
foreach my $option ('_correct',@{$ORdata->{'_Options'}}) { |
next if (! exists($foil_plot[$try]->{$option})); |
next if (! exists($foil_plot[$try]->{$option})); |
Line 1070 sub OR_tries_analysis {
|
Line 1067 sub OR_tries_analysis {
|
} |
} |
# |
# |
my $correct_graph = &Apache::loncommon::DrawBarGraph |
my $correct_graph = &Apache::loncommon::DrawBarGraph |
($title,'Foil Number','Percent Correct', |
('Correct Statements','Statement','% Answered Correct', |
100,$plotcolors,\@Labels,$Datasets[0]); |
100,$plotcolors,\@Labels,$Datasets[0]); |
|
|
# |
# |
Line 1079 sub OR_tries_analysis {
|
Line 1076 sub OR_tries_analysis {
|
for (my $i=0; $i< scalar(@{$Datasets[0]});$i++) { |
for (my $i=0; $i< scalar(@{$Datasets[0]});$i++) { |
$Datasets[0]->[$i]=0; |
$Datasets[0]->[$i]=0; |
} |
} |
$count = $response_data{'_total'}->[$try] - |
my $count = $response_data{'_total'}->[$try] - |
$response_data{'_correct'}->[$try]; |
$response_data{'_correct'}->[$try]; |
$title = 'Attempt '.$try.' (N='.$count.')'; |
|
my $incorrect_graph = &Apache::loncommon::DrawBarGraph |
my $incorrect_graph = &Apache::loncommon::DrawBarGraph |
($title,'Foil Number','% Option Chosen Incorrectly', |
('Incorrect Statements','Statement','% Chosen Incorrectly', |
100,$plotcolors,\@Labels,@Datasets); |
100,$plotcolors,\@Labels,@Datasets); |
$analysis_html.= |
$analysis_html.= |
|
'<tr><td colspan="4" align="center">'. |
|
'<font size="+1">'. |
|
&mt('Attempt [_1], [_2] submissions, [_3] correct, [_4] incorrect', |
|
$try,$data_count,$correct,$data_count-$correct). |
|
'</font>'.'</td></tr>'.$/. |
'<tr>'. |
'<tr>'. |
'<td>'.$concept_graph.'</td>'. |
'<td>'.$concept_graph.'</td>'. |
'<td>'.$correct_graph.'</td>'. |
'<td>'.$correct_graph.'</td>'. |
Line 1103 sub OR_analyze_by_tries {
|
Line 1104 sub OR_analyze_by_tries {
|
my %Trydata; |
my %Trydata; |
$mintries = 1 if (! defined($mintries) || $mintries < 1); |
$mintries = 1 if (! defined($mintries) || $mintries < 1); |
$maxtries = $mintries if (! defined($maxtries) || $maxtries < $mintries); |
$maxtries = $mintries if (! defined($maxtries) || $maxtries < $mintries); |
|
my @students; |
foreach my $row (@$PerformanceData) { |
foreach my $row (@$PerformanceData) { |
next if (! defined($row)); |
next if (! defined($row)); |
my $tries = &get_tries_from_row($row); |
my $tries = &get_tries_from_row($row); |
my %Row = &Process_OR_Row($row); |
my %Row = &Process_OR_Row($row); |
next if (! %Row); |
next if (! %Row); |
|
my $student_id = $row->[&Apache::loncoursedata::RD_student_id()]; |
|
$students[$tries]->{$student_id}++; |
while (my ($foilid,$href) = each(%Row)) { |
while (my ($foilid,$href) = each(%Row)) { |
if (! ref($href)) { |
if (! ref($href)) { |
$Trydata{$foilid}->[$tries] += $href; |
$Trydata{$foilid}->[$tries] += $href; |
Line 1118 sub OR_analyze_by_tries {
|
Line 1122 sub OR_analyze_by_tries {
|
} |
} |
} |
} |
} |
} |
|
for (my $try=$mintries;$try<=$maxtries;$try++) { |
|
$Trydata{'_studentcount'}->[$try] = scalar(keys(%{$students[$try]})); |
|
} |
return %Trydata; |
return %Trydata; |
} |
} |
|
|
Line 1142 sub OR_time_analysis {
|
Line 1149 sub OR_time_analysis {
|
# |
# |
my $num_plots = $ENV{'form.NumPlots'}; |
my $num_plots = $ENV{'form.NumPlots'}; |
my $num_data = scalar(@$performance_data)-1; |
my $num_data = scalar(@$performance_data)-1; |
my $percent = sprintf('%2f',100/$num_plots); |
|
# |
# |
|
my $current_index; |
$table .= "<table>\n"; |
$table .= "<table>\n"; |
for (my $i=0;$i<$num_plots;$i++) { |
for (my $i=0;$i<$num_plots;$i++) { |
## |
## |
Line 1154 sub OR_time_analysis {
|
Line 1161 sub OR_time_analysis {
|
if (! defined($starttime) || ! defined($endtime)) { |
if (! defined($starttime) || ! defined($endtime)) { |
my $sec_in_day = 86400; |
my $sec_in_day = 86400; |
my $last_sub_time = &get_time_from_row($performance_data->[-1]); |
my $last_sub_time = &get_time_from_row($performance_data->[-1]); |
my ($sday,$smon,$syear); |
my ($sday,$smon,$syear) = |
(undef,undef,undef,$sday,$smon,$syear) = |
(localtime($last_sub_time - $sec_in_day*$i))[3..5]; |
localtime($last_sub_time - $sec_in_day*$i); |
|
$starttime = &Time::Local::timelocal(0,0,0,$sday,$smon,$syear); |
$starttime = &Time::Local::timelocal(0,0,0,$sday,$smon,$syear); |
$endtime = $starttime + $sec_in_day; |
$endtime = $starttime + $sec_in_day; |
if ($i == ($num_plots -1 )) { |
if ($i == ($num_plots -1 )) { |
$starttime = &get_time_from_row($performance_data->[0]); |
$starttime = &get_time_from_row($performance_data->[0]); |
} |
} |
} |
} |
$table .= '<tr><td colspan="4" align="center">'. |
$table .= '<tr><td colspan="4" align="center"><font size="+1">'. |
&mt('Data from [_1] to [_2]', |
&mt('Data from [_1] to [_2]', |
&Apache::lonlocal::locallocaltime($starttime), |
&Apache::lonlocal::locallocaltime($starttime), |
&Apache::lonlocal::locallocaltime($endtime)).'</td></tr>'.$/; |
&Apache::lonlocal::locallocaltime($endtime)). |
|
'</font></td></tr>'.$/; |
my $startdateform = &Apache::lonhtmlcommon::date_setter |
my $startdateform = &Apache::lonhtmlcommon::date_setter |
('Statistics','startdate_'.$i,$starttime); |
('Statistics','startdate_'.$i,$starttime); |
my $enddateform = &Apache::lonhtmlcommon::date_setter |
my $enddateform = &Apache::lonhtmlcommon::date_setter |
Line 1189 sub OR_time_analysis {
|
Line 1196 sub OR_time_analysis {
|
} |
} |
$end_index = $j; |
$end_index = $j; |
## |
## |
my $interval = { |
my ($processed_time_data,$correct,$data_count,$student_count) = |
begin_index => $begin_index, |
&OR_time_process_data($performance_data,$begin_index,$end_index); |
end_index => $end_index, |
## |
startdateform => $startdateform, |
$table .= '<tr><td colspan="4" align="center"><font size="+1">'. |
enddateform => $enddateform, |
&mt('[_1] submissions from [_2] students submitting, [_3] correct, [_4] incorrect', |
}; |
$data_count,$student_count,$correct,$data_count-$correct). |
|
'</font></td></tr>'.$/; |
my $concept_correct_plot = ''; |
my $concept_correct_plot = ''; |
if ($num_concepts > 1) { |
if ($num_concepts > 1) { |
$concept_correct_plot = |
$concept_correct_plot = |
&OR_Concept_Time_Analysis($performance_data, |
&OR_Concept_Time_Analysis($processed_time_data, |
$ORdata,$Concepts, |
$correct,$data_count,$student_count, |
$interval); |
$ORdata,$Concepts); |
} |
} |
my ($foil_correct_plot,$foil_incorrect_plot) = |
my ($foil_correct_plot,$foil_incorrect_plot) = |
&OR_Foil_Time_Analysis($performance_data,$ORdata, |
&OR_Foil_Time_Analysis($processed_time_data, |
$Foils,$Concepts,$interval); |
$correct,$data_count,$student_count, |
|
$ORdata,$Foils,$Concepts); |
$table .= '<tr>'. |
$table .= '<tr>'. |
'<td>'.$concept_correct_plot.'</td>'. |
'<td>'.$concept_correct_plot.'</td>'. |
'<td>'.$foil_correct_plot.'</td>'. |
'<td>'.$foil_correct_plot.'</td>'. |
'<td>'.$foil_incorrect_plot.'</td>'. |
'<td>'.$foil_incorrect_plot.'</td>'. |
'<td align="left" valign="top">'.$foilkey.'</td></tr>'.$/; |
'<td align="left" valign="top">'.$foilkey.'</td></tr>'.$/; |
$table .= '<tr><td colspan="4" align="center">'. |
$table .= '<tr><td colspan="4" align="center">'. |
&mt('Start time: [_1]', |
&mt('Start time: [_1]',$startdateform).'<br />'. |
$interval->{'startdateform'}).'<br />'. |
&mt('End time: [_1]',$enddateform).'</td></tr>'.$/; |
&mt('End time: [_1]', |
|
$interval->{'enddateform'}). |
|
'</td></tr>'.$/; |
|
$table.= '<tr><td colspan="4"> </td></tr>'.$/; |
$table.= '<tr><td colspan="4"> </td></tr>'.$/; |
} |
} |
$table .= '</table>'; |
$table .= '</table>'; |
Line 1224 sub OR_time_analysis {
|
Line 1230 sub OR_time_analysis {
|
} |
} |
|
|
sub OR_Foil_Time_Analysis { |
sub OR_Foil_Time_Analysis { |
my ($performance_data,$ORdata,$Foils,$Concepts,$interval) = @_; |
my ($processed_time_data,$correct,$data_count,$student_count, |
my $analysis_html; |
$ORdata,$Foils,$Concepts) = @_; |
my ($begin_index,$end_index) = ($interval->{'begin_index'}, |
if ($data_count <= 0) { |
$interval->{'end_index'}); |
return ('<h2>'.&mt('There is no data to plot').'</h2>',''); |
my %TimeData; |
|
# |
|
# Compute the number getting the foils correct or incorrects |
|
for (my $j=$begin_index;$j<=$end_index;$j++) { |
|
my $row = $performance_data->[$j]; |
|
next if (! defined($row)); |
|
my %Row = &Process_OR_Row($row); |
|
while (my ($foilid,$href) = each(%Row)) { |
|
if (! ref($href)) { |
|
$TimeData{$foilid} += $href; |
|
next; |
|
} |
|
while (my ($option,$value) = each(%$href)) { |
|
$TimeData{$foilid}->{$option}+=$value; |
|
} |
|
} |
|
} |
} |
|
my $analysis_html; |
my @plotdata; |
my @plotdata; |
my @labels; |
my @labels; |
foreach my $concept (@{$Concepts}) { |
foreach my $concept (@{$Concepts}) { |
foreach my $foil (@{$concept->{'foils'}}) { |
foreach my $foil (@{$concept->{'foils'}}) { |
push(@labels,scalar(@labels)+1); |
push(@labels,scalar(@labels)+1); |
my $total = $TimeData{$foil}->{'_total'}; |
my $total = $processed_time_data->{$foil}->{'_total'}; |
if ($total == 0) { |
if ($total == 0) { |
push(@{$plotdata[0]},0); |
push(@{$plotdata[0]},0); |
} else { |
} else { |
push(@{$plotdata[0]}, |
push(@{$plotdata[0]}, |
100 * $TimeData{$foil}->{'_correct'} / $total); |
100 * $processed_time_data->{$foil}->{'_correct'} / $total); |
} |
} |
my $total_incorrect = $total - $TimeData{$foil}->{'_correct'}; |
my $total_incorrect = $total - $processed_time_data->{$foil}->{'_correct'}; |
for (my $i=0;$i<scalar(@{$ORdata->{'_Options'}});$i++) { |
for (my $i=0;$i<scalar(@{$ORdata->{'_Options'}});$i++) { |
my $option = $ORdata->{'_Options'}->[$i]; |
my $option = $ORdata->{'_Options'}->[$i]; |
if ($total_incorrect == 0) { |
if ($total_incorrect == 0) { |
push(@{$plotdata[$i+1]},0); |
push(@{$plotdata[$i+1]},0); |
} else { |
} else { |
push(@{$plotdata[$i+1]}, |
push(@{$plotdata[$i+1]}, |
100 * $TimeData{$foil}->{$option} / $total_incorrect); |
100 * $processed_time_data->{$foil}->{$option} / $total_incorrect); |
} |
} |
} |
} |
} |
} |
Line 1277 sub OR_Foil_Time_Analysis {
|
Line 1268 sub OR_Foil_Time_Analysis {
|
} |
} |
# |
# |
# Create the plot |
# Create the plot |
my $count = $end_index-$begin_index; |
my $correct_plot = &Apache::loncommon::DrawBarGraph('Correct Statements', |
return ('No data','') if ($count <= 0); |
'Statement Number', |
my $title; |
'Percent Correct', |
if ($count == 0) { |
100, |
$title = 'no submissions'; |
$plotcolors, |
} elsif ($count == 1) { |
undef, |
$title = 'one submission'; |
$plotdata[0]); |
} elsif ($count > 1) { |
|
$title = $count.' submissions'; |
|
} |
|
my $correct_plot = &Apache::loncommon::DrawBarGraph($title, |
|
'Foil Number', |
|
'Percent Correct', |
|
100, |
|
$plotcolors, |
|
undef, |
|
$plotdata[0]); |
|
for (my $j=0; $j< scalar(@{$plotdata[0]});$j++) { |
for (my $j=0; $j< scalar(@{$plotdata[0]});$j++) { |
$plotdata[0]->[$j]=0; |
$plotdata[0]->[$j]=0; |
} |
} |
$count = $end_index-$begin_index-$TimeData{'_correct'}; |
my $incorrect_plot = |
if ($count == 0) { |
&Apache::loncommon::DrawBarGraph('Incorrect Statements', |
$title = 'no submissions'; |
'Statement Number', |
} elsif ($count < 0) { |
'Incorrect Option Choice', |
return ($correct_plot,''); |
100, |
} elsif ($count == 1) { |
$plotcolors, |
$title = 'one submission'; |
undef, |
} else { |
@plotdata); |
$title = $count.' submissions'; |
|
} |
|
my $incorrect_plot = &Apache::loncommon::DrawBarGraph($title, |
|
'Foil Number', |
|
'Incorrect Option Choice', |
|
100, |
|
$plotcolors, |
|
undef, |
|
@plotdata); |
|
return ($correct_plot,$incorrect_plot); |
return ($correct_plot,$incorrect_plot); |
} |
} |
|
|
sub OR_Concept_Time_Analysis { |
sub OR_Concept_Time_Analysis { |
my ($performance_data,$ORdata,$Concepts,$interval) = @_; |
my ($processed_time_data,$correct,$data_count,$student_count, |
## |
$ORdata,$Concepts) = @_; |
## Determine starttime, endtime, startindex, endindex |
return '' if ($data_count == 0); |
my ($begin_index,$end_index) = ($interval->{'begin_index'}, |
|
$interval->{'end_index'}); |
|
my %TimeData; |
|
# |
|
# Compute the number getting the foils correct or incorrects |
|
for (my $j=$begin_index;$j<=$end_index;$j++) { |
|
my $row = $performance_data->[$j]; |
|
next if (! defined($row)); |
|
my %Row = &Process_OR_Row($row); |
|
while (my ($foilid,$href) = each(%Row)) { |
|
if (! ref($href)) { |
|
$TimeData{$foilid} += $href; |
|
next; |
|
} |
|
while (my ($option,$value) = each(%$href)) { |
|
$TimeData{$foilid}->{$option}+=$value; |
|
} |
|
} |
|
} |
|
# |
# |
# Put the data in plottable form |
# Put the data in plottable form |
my @plotdata; |
my @plotdata; |
foreach my $concept (@$Concepts) { |
foreach my $concept (@$Concepts) { |
my ($total,$correct); |
my ($total,$correct); |
foreach my $foil (@{$concept->{'foils'}}) { |
foreach my $foil (@{$concept->{'foils'}}) { |
$total += $TimeData{$foil}->{'_total'}; |
$total += $processed_time_data->{$foil}->{'_total'}; |
$correct += $TimeData{$foil}->{'_correct'}; |
$correct += $processed_time_data->{$foil}->{'_correct'}; |
} |
} |
if ($total == 0) { |
if ($total == 0) { |
push(@plotdata,0); |
push(@plotdata,0); |
Line 1357 sub OR_Concept_Time_Analysis {
|
Line 1310 sub OR_Concept_Time_Analysis {
|
} |
} |
# |
# |
# Create the plot |
# Create the plot |
my $title = ($end_index - $begin_index).' submissions'; |
return &Apache::loncommon::DrawBarGraph('Correct Concepts', |
return &Apache::loncommon::DrawBarGraph($title, |
|
'Concept Number', |
'Concept Number', |
'Percent Correct', |
'Percent Correct', |
100, |
100, |
Line 1367 sub OR_Concept_Time_Analysis {
|
Line 1319 sub OR_Concept_Time_Analysis {
|
\@plotdata); |
\@plotdata); |
} |
} |
|
|
|
sub OR_time_process_data { |
|
my ($performance_data,$begin_index,$end_index)=@_; |
|
my %processed_time_data; |
|
my %distinct_students; |
|
my ($correct,$data_count); |
|
if (($begin_index == $end_index) && |
|
($end_index != scalar(@$performance_data)-1)) { |
|
return undef; |
|
} |
|
# Be sure we include the last one if we are asked for it. |
|
# That we have to correct here (and not when $end_index is |
|
# given a value) should probably be considered a bug. |
|
if ($end_index == scalar(@$performance_data)-1) { |
|
$end_index++; |
|
} |
|
&Apache::lonnet::logthis(' '.$begin_index.':'.$end_index); |
|
my $count; |
|
for (my $i=$begin_index;$i<$end_index;$i++) { |
|
my $attempt = $performance_data->[$i]; |
|
$count++; |
|
next if (! defined($attempt)); |
|
my %attempt = &Process_OR_Row($attempt); |
|
$data_count++; |
|
$correct += $attempt{'_correct'}; |
|
$distinct_students{$attempt->[&Apache::loncoursedata::RD_student_id()]}++; |
|
while (my ($foilid,$href) = each(%attempt)) { |
|
if (! ref($href)) { |
|
$processed_time_data{$foilid} += $href; |
|
next; |
|
} |
|
while (my ($option,$value) = each(%$href)) { |
|
$processed_time_data{$foilid}->{$option}+=$value; |
|
} |
|
} |
|
} |
|
&Apache::lonnet::logthis('count = '.$count); |
|
return (\%processed_time_data,$correct,$data_count, |
|
scalar(keys(%distinct_students))); |
|
} |
|
|
######################################################### |
######################################################### |
######################################################### |
######################################################### |
## |
## |
Line 1671 sub build_option_index {
|
Line 1663 sub build_option_index {
|
my $optionindex = 0; |
my $optionindex = 0; |
my @Rows; |
my @Rows; |
foreach my $option (&mt('correct option chosen'),@{$ORdata->{'_Options'}}) { |
foreach my $option (&mt('correct option chosen'),@{$ORdata->{'_Options'}}) { |
|
my $color = $plotcolors->[$optionindex++]; |
push (@Rows, |
push (@Rows, |
'<tr>'. |
'<tr>'. |
'<td bgcolor="'.$plotcolors->[$optionindex++].'">'. |
'<td bgcolor="'.$color.'">'. |
(' 'x4).'</td>'. |
'<font color="'.$color.'">'.('*'x3).'</font>'.'</td>'. |
'<td>'.&HTML::Entities::encode($option,'<>&"').'</td>'. |
'<td>'.&HTML::Entities::encode($option,'<>&"').'</td>'. |
"</tr>\n"); |
"</tr>\n"); |
} |
} |
Line 1690 sub build_foil_key {
|
Line 1683 sub build_foil_key {
|
my $foil_index = 0; |
my $foil_index = 0; |
my @rows; |
my @rows; |
foreach my $foil (&mt('correct foil chosen'),@{$foils}) { |
foreach my $foil (&mt('correct foil chosen'),@{$foils}) { |
|
my $color = $plotcolors->[$foil_index++]; |
push (@rows, |
push (@rows, |
'<tr>'. |
'<tr>'. |
'<td bgcolor="'.$plotcolors->[$foil_index++].'">'. |
'<td bgcolor="'.$color.'" class="key">'. |
(' 'x4).'</td>'. |
'<font color="'.$color.'">'.('*'x4).'</font></td>'. |
'<td>'.&HTML::Entities::encode($foil,'<>&"'). |
'<td>'.&HTML::Entities::encode($foil,'<>&"'). |
(' 'x2).$extra_data->{$foil}.'</td>'. |
(' 'x2).$extra_data->{$foil}.'</td>'. |
"</tr>\n"); |
"</tr>\n"); |
Line 1846 sub hashify_attempt {
|
Line 1840 sub hashify_attempt {
|
sub Process_OR_Row { |
sub Process_OR_Row { |
my ($row) = @_; |
my ($row) = @_; |
my %RowData; |
my %RowData; |
my $student_id = $row->[&Apache::loncoursedata::RD_student_id()]; |
# my $student_id = $row->[&Apache::loncoursedata::RD_student_id()]; |
my $award = $row->[&Apache::loncoursedata::RD_awarddetail()]; |
my $award = $row->[&Apache::loncoursedata::RD_awarddetail()]; |
my $grading = $row->[&Apache::loncoursedata::RD_response_eval()]; |
my $grading = $row->[&Apache::loncoursedata::RD_response_eval()]; |
my $submission = $row->[&Apache::loncoursedata::RD_submission()]; |
my $submission = $row->[&Apache::loncoursedata::RD_submission()]; |
my $time = $row->[&Apache::loncoursedata::RD_timestamp()]; |
my $time = $row->[&Apache::loncoursedata::RD_timestamp()]; |
my $tries = $row->[&Apache::loncoursedata::RD_tries()]; |
# my $tries = $row->[&Apache::loncoursedata::RD_tries()]; |
return undef if ($award eq 'MISSING_ANSWER'); |
return undef if ($award eq 'MISSING_ANSWER'); |
if ($award =~ /(APPROX_ANS|EXACT_ANS)/) { |
if ($award =~ /(APPROX_ANS|EXACT_ANS)/) { |
$RowData{'_correct'} = 1; |
$RowData{'_correct'} = 1; |