Annotation of loncom/interface/statistics/lonproblemanalysis.pm, revision 1.36
1.1 stredwic 1: # The LearningOnline Network with CAPA
2: #
1.33 matthew 3:
1.36 ! matthew 4: # $Id: lonproblemanalysis.pm,v 1.35 2003/10/14 14:23:14 matthew Exp $
1.1 stredwic 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28:
1.11 minaeibi 29: package Apache::lonproblemanalysis;
1.1 stredwic 30:
31: use strict;
32: use Apache::lonnet();
1.25 matthew 33: use Apache::loncommon();
1.7 stredwic 34: use Apache::lonhtmlcommon();
1.23 matthew 35: use Apache::loncoursedata();
36: use Apache::lonstatistics;
37: use Apache::lonlocal;
1.2 stredwic 38:
1.1 stredwic 39: sub BuildProblemAnalysisPage {
1.23 matthew 40: my ($r,$c)=@_;
1.24 matthew 41: $r->print('<h2>'.&mt('Option Response Problem Analysis').'</h2>');
1.25 matthew 42: $r->print(&CreateInterface());
1.28 matthew 43: #
44: my @Students = @Apache::lonstatistics::Students;
45: #
1.33 matthew 46: if (exists($ENV{'form.updatecaches'}) ||
47: (exists($ENV{'form.firstanalysis'}) &&
48: $ENV{'form.firstanalysis'} ne 'no')) {
49: &Apache::lonstatistics::Gather_Full_Student_Data($r);
50: }
51: if (! exists($ENV{'form.firstanalysis'})) {
52: $r->print('<input type="hidden" name="firstanalysis" value="yes" />');
53: } else {
54: $r->print('<input type="hidden" name="firstanalysis" value="no" />');
55: }
56: if (exists($ENV{'form.problemchoice'}) &&
57: ! exists($ENV{'form.SelectAnother'})) {
1.31 matthew 58: $r->print('<input type="submit" name="ProblemAnalysis" value="'.
59: &mt('Analyze Problem Again').'" />');
60: $r->print(' 'x5);
61: $r->print('<input type="submit" name="ClearCache" value="'.
62: &mt('Clear Caches').'" />');
63: $r->print(' 'x5);
1.33 matthew 64: $r->print('<input type="submit" name="updatecaches" value="'.
65: &mt('Update Student Data').'" />');
66: $r->print(' 'x5);
1.31 matthew 67: $r->print('<input type="hidden" name="problemchoice" value="'.
68: $ENV{'form.problemchoice'}.'" />');
69: $r->print('<input type="submit" name="SelectAnother" value="'.
70: &mt('Choose a different resource').'" />');
71: $r->print(' 'x5);
72: #
1.25 matthew 73: $r->print('<hr />');
1.23 matthew 74: #
1.25 matthew 75: my ($symb,$part,$resid) = &get_problem_symb(
1.23 matthew 76: &Apache::lonnet::unescape($ENV{'form.problemchoice'})
77: );
1.28 matthew 78: #
1.23 matthew 79: my $resource = &get_resource_from_symb($symb);
80: if (defined($resource)) {
1.25 matthew 81: my %Data = &get_problem_data($resource->{'src'});
82: my $ORdata = $Data{$part.'.'.$resid};
83: ##
1.26 matthew 84: ## Render the problem
1.25 matthew 85: my $base;
86: ($base,undef) = ($resource->{'src'} =~ m|(.*/)[^/]*$|);
87: $base = "http://".$ENV{'SERVER_NAME'}.$base;
1.26 matthew 88: my $rendered_problem =
89: &Apache::lonnet::ssi_body($resource->{'src'});
1.30 matthew 90: $rendered_problem =~ s/<\s*form\s*/<nop /g;
91: $rendered_problem =~ s|(<\s*/form\s*>)|<\/nop>|g;
1.26 matthew 92: $r->print('<table bgcolor="ffffff"><tr><td>'.
1.25 matthew 93: '<base href="'.$base.'" />'.
1.26 matthew 94: $rendered_problem.
95: '</td></tr></table>');
1.25 matthew 96: ##
97: ## Analyze the problem
1.26 matthew 98: my $PerformanceData =
99: &Apache::loncoursedata::get_optionresponse_data
1.28 matthew 100: (\@Students,$symb,$resid);
1.26 matthew 101: if (defined($PerformanceData) &&
102: ref($PerformanceData) eq 'ARRAY') {
1.36 ! matthew 103: if ($ENV{'form.AnalyzeOver'} eq 'Tries') {
1.33 matthew 104: my $analysis_html = &tries_analysis($PerformanceData,
105: $ORdata);
106: $r->print($analysis_html);
1.36 ! matthew 107: } elsif ($ENV{'form.AnalyzeOver'} eq 'Time') {
1.33 matthew 108: my $analysis_html = &time_analysis($PerformanceData,
1.28 matthew 109: $ORdata);
1.26 matthew 110: $r->print($analysis_html);
1.28 matthew 111: } else {
112: $r->print('<h2>'.
113: &mt('The analysis you have selected is '.
114: 'not supported at this time').
115: '</h2>');
116: }
1.26 matthew 117: } else {
118: $r->print('<h2>'.
119: &mt('There is no student data for this problem.').
120: '</h2>');
121: }
1.23 matthew 122: } else {
123: $r->print('resource is undefined');
1.7 stredwic 124: }
1.23 matthew 125: $r->print('<hr />');
1.25 matthew 126: } else {
1.31 matthew 127: $r->print('<input type="submit" name="ProblemAnalysis" value="'.
128: &mt('Analyze Problem').'" />');
129: $r->print(' 'x5);
1.27 matthew 130: $r->print('<h3>'.&mt('Please select a problem to analyze').'</h3>');
1.31 matthew 131: $r->print(&OptionResponseProblemSelector());
1.1 stredwic 132: }
133: }
134:
1.25 matthew 135:
1.33 matthew 136: #########################################################
137: #########################################################
138: ##
139: ## Misc interface routines use by analysis code
140: ##
141: #########################################################
142: #########################################################
143: sub build_foil_index {
144: my ($ORdata) = @_;
1.36 ! matthew 145: my %Foildata = %{$ORdata->{'Foils'}};
! 146: my @Foils = sort(keys(%Foildata));
! 147: my %Concepts;
1.25 matthew 148: foreach my $foilid (@Foils) {
1.36 ! matthew 149: push(@{$Concepts{$Foildata{$foilid}->{'Concept'}}},
! 150: $foilid);
! 151: }
! 152: undef(@Foils);
! 153: # Having gathered the concept information in a hash, we now translate it
! 154: # into an array because we need to be consistent about order.
! 155: # Also put the foils in order, too.
! 156: my $sortfunction = sub {
! 157: my %Numbers = (one => 1,
! 158: two => 2,
! 159: three => 3,
! 160: four => 4,
! 161: five => 5,
! 162: six => 6,
! 163: seven => 7,
! 164: eight => 8,
! 165: nine => 9,
! 166: ten => 10,);
! 167: my $a1 = $a;
! 168: my $b1 = $b;
! 169: if (exists($Numbers{$a})) {
! 170: $a1 = $Numbers{$a};
! 171: }
! 172: if (exists($Numbers{$b})) {
! 173: $b1 = $Numbers{$b};
! 174: }
! 175: $a1 cmp $b1;
! 176: };
! 177: my @Concepts;
! 178: foreach my $concept (sort $sortfunction (keys(%Concepts))) {
! 179: push(@Concepts,{name => $concept,
! 180: foils => [@{$Concepts{$concept}}]});
! 181: push(@Foils,(@{$Concepts{$concept}}));
1.25 matthew 182: }
1.31 matthew 183: #
184: # Build up the table of row labels.
185: my $table = '<table border="1" >'."\n";
1.36 ! matthew 186: $table .= '<tr>'.
! 187: '<th>'.&mt('Concept Number').'</th>'.
! 188: '<th>'.&mt('Concept').'</th>'.
! 189: '<th>'.&mt('Foil Number').'</th>'.
! 190: '<th>'.&mt('Foil Name').'</th>'.
! 191: '<th>'.&mt('Foil Text').'</th>'.
! 192: '<th>'.&mt('Correct Value').'</th>'.
! 193: "</tr>\n";
! 194: my $conceptindex = 1;
! 195: my $foilindex = 1;
! 196: foreach my $concept (@Concepts) {
! 197: my @FoilsInConcept = @{$concept->{'foils'}};
! 198: my $firstfoil = shift(@FoilsInConcept);
! 199: $table .= '<tr>'.
! 200: '<td>'.$conceptindex.'</td>'.
! 201: '<td>'.$concept->{'name'}.'</td>'.
! 202: '<td>'.$foilindex++.'</td>'.
! 203: '<td>'.$Foildata{$firstfoil}->{'name'}.'</td>'.
! 204: '<td>'.$Foildata{$firstfoil}->{'text'}.'</td>'.
! 205: '<td>'.$Foildata{$firstfoil}->{'value'}.'</td>'.
! 206: "</tr>\n";
! 207: foreach my $foilid (@FoilsInConcept) {
! 208: $table .= '<tr>'.
! 209: '<td></td>'.
! 210: '<td></td>'.
! 211: '<td>'.$foilindex.'</td>'.
! 212: '<td>'.$Foildata{$foilid}->{'name'}.'</td>'.
! 213: '<td>'.$Foildata{$foilid}->{'text'}.'</td>'.
! 214: '<td>'.$Foildata{$foilid}->{'value'}.'</td>'.
! 215: "</tr>\n";
! 216: } continue {
! 217: $foilindex++;
! 218: }
1.31 matthew 219: } continue {
1.36 ! matthew 220: $conceptindex++;
1.25 matthew 221: }
1.31 matthew 222: $table .= "</table>\n";
1.36 ! matthew 223: return ($table,\@Foils,\@Concepts);
1.33 matthew 224: }
225:
226: #########################################################
227: #########################################################
228: ##
229: ## Tries Analysis
230: ##
231: #########################################################
232: #########################################################
233: sub tries_analysis {
234: my ($PerformanceData,$ORdata) = @_;
235: my $mintries = 1;
236: my $maxtries = $ENV{'form.NumPlots'};
237: my %ResponseData = &analyze_option_data_by_tries($PerformanceData,
1.36 ! matthew 238: $mintries,$maxtries);
! 239: my ($table,$Foils,$Concepts) = &build_foil_index($ORdata);
1.31 matthew 240: #
241: # Compute the data neccessary to make the plots
1.25 matthew 242: my @PlotData;
1.36 ! matthew 243: my $xlabel;
! 244: if ($ENV{'form.AnalyzeAs'} eq 'Foils') {
! 245: $xlabel = 'Foil Number';
! 246: foreach my $foilid (@$Foils) {
! 247: for (my $i=$mintries;$i<=$maxtries;$i++) {
! 248: #
! 249: # Gather the per-attempt data
! 250: my $percent;
! 251: if ($ResponseData{$foilid}->[$i]->{'total'} == 0) {
! 252: $percent = 0;
! 253: } else {
! 254: $percent = $ResponseData{$foilid}->[$i]->{'correct'} /
! 255: $ResponseData{$foilid}->[$i]->{'total'};
! 256: }
! 257: push (@{$PlotData[$i]->{'total'}},
! 258: $ResponseData{$foilid}->[$i]->{'total'});
! 259: push (@{$PlotData[$i]->{'good'}},100 * $percent);
! 260: push (@{$PlotData[$i]->{'bad'}}, 100 *(1-$percent));
! 261: }
! 262: }
! 263: } else {
! 264: # Concept analysis
! 265: $xlabel = 'Concept Number';
! 266: foreach my $concept (@$Concepts) {
! 267: for (my $i=$mintries;$i<=$maxtries;$i++) {
! 268: #
! 269: # Gather the per-attempt data
! 270: my ($correct,$incorrect,$total);
! 271: foreach my $foil (@{$concept->{'foils'}}) {
! 272: $correct += $ResponseData{$foil}->[$i]->{'correct'};
! 273: $incorrect += $ResponseData{$foil}->[$i]->{'incorrect'};
! 274: $total += $ResponseData{$foil}->[$i]->{'total'};
! 275: }
! 276: push (@{$PlotData[$i]->{'correct'}}, $correct);
! 277: push (@{$PlotData[$i]->{'incorrect'}},$incorrect);
! 278: push (@{$PlotData[$i]->{'total'}}, $total);
! 279: my $percent;
! 280: if ($total == 0) {
! 281: $percent = 0;
! 282: } else {
! 283: $percent = $correct/$total;
! 284: }
! 285: push (@{$PlotData[$i]->{'good'}},100*$percent);
! 286: push (@{$PlotData[$i]->{'bad'}},100*(1-$percent));
! 287: }
1.25 matthew 288: }
289: }
1.31 matthew 290: #
291: # Build a table for the plots
292: $table .= "<table>\n";
293: my @Plots;
1.25 matthew 294: for (my $i=$mintries;$i<=$maxtries;$i++) {
1.36 ! matthew 295: my $minstu = $PlotData[$i]->{'total'}->[0];
! 296: my $maxstu = $PlotData[$i]->{'total'}->[0];
! 297: foreach my $count (@{$PlotData[$i]->{'total'}}) {
! 298: if ($minstu > $count) {
! 299: $minstu = $count;
1.27 matthew 300: }
1.36 ! matthew 301: if ($maxstu < $count) {
! 302: $maxstu = $count;
1.27 matthew 303: }
304: }
1.28 matthew 305: $maxstu = 0 if (! $maxstu);
306: $minstu = 0 if (! $minstu);
1.35 matthew 307: my $title;
1.27 matthew 308: if ($maxstu == $minstu) {
1.35 matthew 309: $title = 'Attempt '.$i.', '.$maxstu.' students';
1.27 matthew 310: } else {
1.35 matthew 311: $title = 'Attempt '.$i.', '.$minstu.'-'.$maxstu.' students';
1.27 matthew 312: }
1.35 matthew 313: my $graphlink = &Apache::loncommon::DrawGraph($title,
1.36 ! matthew 314: $xlabel,
1.35 matthew 315: 'Percent Correct',
316: 100,
317: $PlotData[$i]->{'good'},
318: $PlotData[$i]->{'bad'});
1.31 matthew 319: push(@Plots,$graphlink);
1.25 matthew 320: }
1.31 matthew 321: #
322: # Should this be something the user can set? Too many dialogs!
323: my $plots_per_row = 2;
324: while (my $plotlink = shift(@Plots)) {
325: $table .= '<tr><td>'.$plotlink.'</td>';
326: for (my $i=1;$i<$plots_per_row;$i++) {
327: if ($plotlink = shift(@Plots)) {
328: $table .= '<td>'.$plotlink.'</td>';
329: } else {
330: $table .= '<td></td>';
331: }
332: }
333: $table .= "</tr>\n";
1.25 matthew 334: }
1.31 matthew 335: $table .= "</table>\n";
1.25 matthew 336: return ($table);
337: }
338:
339: sub analyze_option_data_by_tries {
1.26 matthew 340: my ($PerformanceData,$mintries,$maxtries) = @_;
1.25 matthew 341: my %Trydata;
342: $mintries = 1 if (! defined($mintries) || $mintries < 1);
343: $maxtries = $mintries if (! defined($maxtries) || $maxtries < $mintries);
1.26 matthew 344: foreach my $row (@$PerformanceData) {
345: next if (! defined($row));
1.25 matthew 346: my ($grading,$submission,$time,$tries) = @$row;
347: my @Foilgrades = split('&',$grading);
348: my @Foilsubs = split('&',$submission);
349: for (my $numtries = 1; $numtries <= $maxtries; $numtries++) {
350: if ($tries == $numtries) {
351: foreach my $foilgrade (@Foilgrades) {
352: my ($foilid,$correct) = split('=',$foilgrade);
353: if ($correct) {
354: $Trydata{$foilid}->[$numtries]->{'correct'}++;
355: } else {
356: $Trydata{$foilid}->[$numtries]->{'incorrect'}++;
357: }
358: }
359: }
360: }
361: }
362: foreach my $foilid (keys(%Trydata)) {
363: foreach my $tryhash (@{$Trydata{$foilid}}) {
364: next if ((! exists($tryhash->{'correct'}) &&
365: ! exists($tryhash->{'incorrect'})) ||
366: ($tryhash->{'correct'} < 1 &&
367: $tryhash->{'incorrect'} < 1));
1.27 matthew 368: $tryhash->{'total'} = $tryhash->{'correct'} +
1.36 ! matthew 369: $tryhash->{'incorrect'};
1.25 matthew 370: }
371: }
372: return %Trydata;
373: }
374:
1.33 matthew 375: #########################################################
376: #########################################################
377: ##
378: ## Time Analysis
379: ##
380: #########################################################
381: #########################################################
382: sub time_analysis {
383: my ($PerformanceData,$ORdata) = @_;
384: my $num_plots = $ENV{'form.NumPlots'};
1.36 ! matthew 385: my ($table,$Foils,$Concepts) = &build_foil_index($ORdata);
1.33 matthew 386: my $num_data = scalar(@$PerformanceData)-1;
387: my $percent = sprintf('%2f',100/$num_plots);
388: for (my $i=0;$i<$num_plots;$i++) {
1.34 matthew 389: my $starttime = &Apache::lonhtmlcommon::get_date_from_form
390: ('startdate_'.$i);
391: my $endtime = &Apache::lonhtmlcommon::get_date_from_form
392: ('enddate_'.$i);
393: my ($begin_index,$end_index,$plottitle,$plothtml,$data);
394: if (! defined($starttime) || ! defined($endtime)) {
395: $begin_index = $i*int($num_data/$num_plots);
396: $end_index = ($i+1)*int($num_data/$num_plots);
397: my $lownum = sprintf('%2.1f',$i*$percent);
398: $lownum =~ s/(\.0)$//;
399: my $highnum = sprintf('%2.1f',($i+1)*$percent);
400: $highnum =~ s/(\.0)$//;
401: $plottitle = $lownum.'% to '.$highnum.'% of submissions';
402: } else {
403: my $j;
404: while (++$j < scalar(@$PerformanceData)) {
405: last if ($PerformanceData->[$j]->[2] > $starttime);
406: }
407: $begin_index = $j;
408: while (++$j < scalar(@$PerformanceData)) {
409: last if ($PerformanceData->[$j]->[2] > $endtime);
410: }
411: $end_index = $j;
1.35 matthew 412: $plottitle = 'Tries plot '.($i+1);
1.34 matthew 413: }
414: ($plothtml,$starttime,$endtime,$data) =
1.33 matthew 415: &analyze_option_data_by_time($PerformanceData,
416: $begin_index,$end_index,
1.34 matthew 417: $plottitle,
1.36 ! matthew 418: @$Foils);
1.34 matthew 419: my $startdateform = &Apache::lonhtmlcommon::date_setter
420: ('Statistics','startdate_'.$i,$starttime);
421: my $enddateform = &Apache::lonhtmlcommon::date_setter
422: ('Statistics','enddate_'.$i,$endtime);
423: $plothtml.= "<br />\n".
424: "<b>Start Time</b>: "." ".$startdateform."<br />\n".
425: "<b>End Time</b> : "." ".$enddateform."<br />\n";
1.33 matthew 426: $table.=$plothtml;
427: }
428: return $table;
429: }
430:
431: sub analyze_option_data_by_time {
432: my ($PerformanceData,$begin_index,$end_index,$description,@Foils) = @_;
433: my %TimeData;
434: #
435: # Get the start and end times for this segment of the plot
436: my $starttime = $PerformanceData->[$begin_index]->[2];
437: my $endtime = $PerformanceData->[$end_index ]->[2];
438: #
439: # Compute the number getting the foils correct or incorrects
440: for (my $i=$begin_index;$i<=$end_index;$i++) {
441: my $row = $PerformanceData->[$i];
442: next if (! defined($row));
443: my ($grading,$submission,$time,$tries) = @$row;
444: my @Foilgrades = split('&',$grading);
445: my @Foilsubs = split('&',$submission);
446: foreach my $foilgrade (@Foilgrades) {
447: my ($foilid,$correct) = split('=',$foilgrade);
448: if ($correct) {
449: $TimeData{$foilid}->{'correct'}++;
450: } else {
451: $TimeData{$foilid}->{'incorrect'}++;
452: }
453: }
454: }
455: #
456: # Compute the total and percent correct
457: my @Plotdata1;
458: my @Plotdata2;
459: foreach my $foilid (@Foils) {
460: if (! exists($TimeData{$foilid}->{'correct'})) {
461: $TimeData{$foilid}->{'correct'} = 0;
462: }
463: if (! exists($TimeData{$foilid}->{'incorrect'})) {
464: $TimeData{$foilid}->{'incorrect'} = 0;
465: }
466: $TimeData{$foilid}->{'total'} = $TimeData{$foilid}->{'correct'} +
467: $TimeData{$foilid}->{'incorrect'};
468: $TimeData{$foilid}->{'percent_corr'} = 100 *
469: $TimeData{$foilid}->{'correct'} /
470: $TimeData{$foilid}->{'total'};
471: push (@Plotdata1, $TimeData{$foilid}->{'percent_corr'});
472: push (@Plotdata2,100-$TimeData{$foilid}->{'percent_corr'});
473: }
474: #
475: # Create the plot
476: my $graphlink = &Apache::loncommon::DrawGraph
477: ($description,#'Time Interval Analysis',
478: 'Foil Number',
479: 'Percent Correct / Incorrect',
480: 100,
481: \@Plotdata1,\@Plotdata2);
482: #
483: return ($graphlink,$starttime,$endtime,\%TimeData);
1.1 stredwic 484: }
485:
1.33 matthew 486: #########################################################
487: #########################################################
488: ##
489: ## Interface
490: ##
491: #########################################################
492: #########################################################
1.23 matthew 493: sub CreateInterface {
1.28 matthew 494: ##
495: ## Environment variable initialization
1.36 ! matthew 496: if (! exists$ENV{'form.AnalyzeOver'}) {
! 497: $ENV{'form.AnalyzeOver'} = 'Tries';
1.28 matthew 498: }
499: ##
500: ## Build the menu
1.7 stredwic 501: my $Str = '';
1.23 matthew 502: $Str .= '<table cellspacing="5">'."\n";
503: $Str .= '<tr>';
504: $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
505: $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
1.31 matthew 506: # $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
507: $Str .= '<td align="center"> </td>';
1.23 matthew 508: $Str .= '</tr>'."\n";
1.31 matthew 509: ##
510: ##
1.23 matthew 511: $Str .= '<tr><td align="center">'."\n";
512: $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
1.28 matthew 513: $Str .= '</td>';
514: #
515: $Str .= '<td align="center">';
1.23 matthew 516: $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
1.28 matthew 517: $Str .= '</td>';
518: #
1.31 matthew 519: # $Str .= '<td align="center">';
1.23 matthew 520: my $only_seq_with_assessments = sub {
521: my $s=shift;
522: if ($s->{'num_assess'} < 1) {
523: return 0;
524: } else {
525: return 1;
526: }
527: };
1.31 matthew 528: &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
1.23 matthew 529: $only_seq_with_assessments);
1.36 ! matthew 530: ##
! 531: ##
1.28 matthew 532: $Str .= '<td>';
1.36 ! matthew 533: { # These braces are here to organize the code, not scope it.
! 534: {
! 535: $Str .= '<nobr>'.&mt('Analyze Over ');
! 536: $Str .='<select name="AnalyzeOver" >';
! 537: $Str .= '<option value="Tries" ';
! 538: if (! exists($ENV{'form.AnalyzeOver'}) ||
! 539: $ENV{'form.AnalyzeOver'} eq 'Tries'){
! 540: # Default to Tries
! 541: $Str .= ' selected ';
! 542: }
! 543: $Str .= '>'.&mt('Tries').'</option>';
! 544: $Str .= '<option value="Time" ';
! 545: $Str .= ' selected ' if ($ENV{'form.AnalyzeOver'} eq 'Time');
! 546: $Str .= '>'.&mt('Time').'</option>';
! 547: $Str .= '</select></nobr><br />';
! 548: }
! 549: {
! 550: $Str .= '<nobr>'.&mt('Analyze as ');
! 551: $Str .='<select name="AnalyzeAs" >';
! 552: $Str .= '<option value="Concepts" ';
! 553: if (! exists($ENV{'form.AnalyzeAs'}) ||
! 554: $ENV{'form.AnalyzeAs'} eq 'Concepts'){
! 555: # Default to Concepts
! 556: $Str .= ' selected ';
! 557: }
! 558: $Str .= '>'.&mt('Concepts').'</option>';
! 559: $Str .= '<option value="Foils" ';
! 560: $Str .= ' selected ' if ($ENV{'form.AnalyzeAs'} eq 'Foils');
! 561: $Str .= '>'.&mt('Foils').'</option>';
! 562: $Str .= '</select></nobr><br />';
! 563: }
! 564: {
! 565: $Str .= '<br /><nobr>'.&mt('Number of Plots:');
! 566: $Str .= '<select name="NumPlots">';
! 567: if (! exists($ENV{'form.NumPlots'})
! 568: || $ENV{'form.NumPlots'} < 1
! 569: || $ENV{'form.NumPlots'} > 20) {
! 570: $ENV{'form.NumPlots'} = 5;
! 571: }
! 572: foreach my $i (1,2,3,4,5,6,7,8,10,15,20) {
! 573: $Str .= '<option value="'.$i.'" ';
! 574: if ($ENV{'form.NumPlots'} == $i) { $Str.=' selected '; }
! 575: $Str .= '>'.$i.'</option>';
! 576: }
! 577: $Str .= '</select></nobr>';
! 578: }
1.28 matthew 579: }
580: $Str .= '</td>';
1.36 ! matthew 581: ##
! 582: ##
1.28 matthew 583: $Str .= '</tr>'."\n";
1.23 matthew 584: $Str .= '</table>'."\n";
585: return ($Str);
586: }
587:
588: sub OptionResponseProblemSelector {
589: my $Str;
590: $Str = "\n<table>\n";
591: foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
592: next if ($seq->{'num_assess'}<1);
593: my $seq_str = '';
594: foreach my $res (@{$seq->{'contents'}}) {
595: # &Apache::lonnet::logthis('checking '.$res->{'title'});
1.26 matthew 596: next if ($res->{'type'} ne 'assessment');
1.23 matthew 597: foreach my $part (@{$res->{'parts'}}) {
598: my $partdata = $res->{'partdata'}->{$part};
599: if (! exists($partdata->{'option'}) ||
600: $partdata->{'option'} == 0) {
601: next;
602: }
603: for (my $i=0;$i<scalar(@{$partdata->{'ResponseTypes'}});$i++){
604: my $respid = $partdata->{'ResponseIds'}->[$i];
605: my $resptype = $partdata->{'ResponseTypes'}->[$i];
606: if ($resptype eq 'option') {
1.25 matthew 607: my $value = &Apache::lonnet::escape($res->{'symb'}.':'.$part.':'.$respid);
1.23 matthew 608: my $checked = '';
609: if ($ENV{'form.problemchoice'} eq $value) {
610: $checked = 'checked ';
611: }
612: $seq_str .= '<tr><td>'.
613: '<input type="radio" name="problemchoice" value="'.$value.'" '.$checked.'/>'.
614: '</td><td>'.
615: '<a href="'.$res->{'src'}.'">'.$res->{'title'}.'</a> ';
616: if ($partdata->{'option'} > 1) {
617: $seq_str .= &mt('response').' '.$respid;
618: }
619: $seq_str .= "</td></tr>\n";
1.11 minaeibi 620: }
621: }
622: }
623: }
1.23 matthew 624: if ($seq_str ne '') {
625: $Str .= '<tr><td> </td><td><b>'.$seq->{'title'}.'</b></td>'.
626: "</tr>\n".$seq_str;
627: }
1.11 minaeibi 628: }
1.23 matthew 629: $Str .= "</table>\n";
630: return $Str;
1.33 matthew 631: }
632:
633: #########################################################
634: #########################################################
635: ##
636: ## Misc functions
637: ##
638: #########################################################
639: #########################################################
640: sub get_problem_symb {
641: my $problemstring = shift();
642: my ($symb,$partid,$resid) = ($problemstring=~ /^(.*):([^:]*):([^:]*)$/);
643: return ($symb,$partid,$resid);
1.11 minaeibi 644: }
645:
1.23 matthew 646: sub get_resource_from_symb {
647: my ($symb) = @_;
648: foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
649: foreach my $res (@{$seq->{'contents'}}) {
650: if ($res->{'symb'} eq $symb) {
651: return $res;
1.2 stredwic 652: }
1.1 stredwic 653: }
654: }
1.23 matthew 655: return undef;
1.1 stredwic 656: }
657:
1.25 matthew 658: sub get_problem_data {
659: my ($url) = @_;
660: # my $Answ=&Apache::lonnet::ssi($URI,('grade_target' => 'analyze',
661: # 'grade_username' => $sname,
662: # 'grade_domain' => $sdom,
663: # 'grade_courseid' => $cid,
664: # 'grade_symb' => $symb));
665: my $Answ=&Apache::lonnet::ssi($url,('grade_target' => 'analyze'));
1.23 matthew 666: (my $garbage,$Answ)=split(/_HASH_REF__/,$Answ,2);
1.25 matthew 667: my %Answer;
1.23 matthew 668: %Answer=&Apache::lonnet::str2hash($Answ);
1.25 matthew 669: # &Apache::lonnet::logthis('keys of %Answer = '.join(', ',(keys(%Answer))));
670: # &Apache::lonnet::logthis('$Answer{parts} = '.
671: # join(', ',@{$Answer{'parts'}}));
672: my %Partdata;
673: foreach my $part (@{$Answer{'parts'}}) {
674: while (my($key,$value) = each(%Answer)) {
675: next if ($key !~ /^$part/);
676: $key =~ s/^$part\.//;
677: if (ref($value) eq 'ARRAY') {
678: if ($key eq 'options') {
679: $Partdata{$part}->{'Options'}=$value;
1.36 ! matthew 680: &Apache::lonnet::logthis('Options = '.join(', ',@$value));
1.25 matthew 681: } elsif ($key eq 'concepts') {
682: $Partdata{$part}->{'Concepts'}=$value;
683: } elsif ($key =~ /^concept\.(.*)$/) {
684: my $concept = $1;
685: foreach my $foil (@$value) {
1.36 ! matthew 686: $Partdata{$part}->{'Foils'}->{$foil}->{'Concept'}=
! 687: $concept;
1.25 matthew 688: }
689: }
1.26 matthew 690: # &Apache::lonnet::logthis($part.' '.$key.' (array) = '.
691: # join(', ',@$value));
1.25 matthew 692: } else {
693: $value =~ s/^\s*//g;
694: $value =~ s/\s*$//g;
695: if ($key=~ /^foil\.text\.(.*)$/) {
696: my $foil = $1;
1.36 ! matthew 697: $Partdata{$part}->{'Foils'}->{$foil}->{'name'}=$foil;
! 698: $Partdata{$part}->{'Foils'}->{$foil}->{'text'}=$value;
1.25 matthew 699: } elsif ($key =~ /^foil\.value\.(.*)$/) {
700: my $foil = $1;
1.36 ! matthew 701: $Partdata{$part}->{'Foils'}->{$foil}->{'value'}=$value;
1.25 matthew 702: }
1.36 ! matthew 703: # &Apache::lonnet::logthis($part.' '.$key.' = '.$value);
1.25 matthew 704: }
705: }
1.23 matthew 706: }
707:
1.25 matthew 708: # my $parts='';
709: # foreach my $elm (@{$Answer{"parts"}}) {
710: # $parts.="$elm,";
711: # }
712: # chop($parts);
713: # my $conc='';
714: # foreach my $elm (@{$Answer{"$parts.concepts"}}) {
715: # $conc.="$elm@";
716: # }
717: # chop($conc);
718: #
719: # @Concepts=split(/\@/,$conc);
720: # foreach my $concept (@{$Answer{"$parts.concepts"}}) {
721: # foreach my $foil (@{$Answer{"$parts.concept.$concept"}}) {
722: # $foil_to_concept{$foil} = $concept;
723: # #$ConceptData{$foil} = $Answer{"$parts.foil.value.$foil"};
724: # }
725: # }
726: # return $symb;
727: return %Partdata;
1.1 stredwic 728: }
729:
1.23 matthew 730: 1;
1.1 stredwic 731:
732: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>