Annotation of loncom/interface/statistics/lonproblemanalysis.pm, revision 1.1
1.1 ! stredwic 1: # The LearningOnline Network with CAPA
! 2: # (Publication Handler
! 3: #
! 4: # $Id: lonstatistics.pm,v 1.29 2002/07/22 20:35:05 stredwic Exp $
! 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: # (Navigate problems for statistical reports
! 29: # YEAR=2001
! 30: # 5/5,7/9,7/25/1,8/11,9/13,9/26,10/5,10/9,10/22,10/26 Behrouz Minaei
! 31: # 11/1,11/4,11/16,12/14,12/16,12/18,12/20,12/31 Behrouz Minaei
! 32: # YEAR=2002
! 33: # 1/22,2/1,2/6,2/25,3/2,3/6,3/17,3/21,3/22,3/26,4/7,5/6 Behrouz Minaei
! 34: # 5/12,5/14,5/15,5/19,5/26,7/16 Behrouz Minaei
! 35: #
! 36: ###
! 37:
! 38: package Apache::lonproblemanalysis;
! 39:
! 40: use strict;
! 41: use Apache::lonnet();
! 42: use GDBM_File;
! 43:
! 44: sub BuildProblemAnalysisPage {
! 45: my ($cacheDB)=@_;
! 46:
! 47: my %cache;
! 48: my $Str = '';
! 49: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
! 50: $Str .= '<html><body>Unable to tie database.</body></html>';
! 51: return $Str;
! 52: }
! 53:
! 54: $Str .= &IntervalOptions($cache{'Interval'});
! 55: $Str .= &OptionResponseTable($cache{'OptionResponses'});
! 56:
! 57: untie(%cache);
! 58:
! 59: return $Str;
! 60: }
! 61:
! 62: sub BuildAnalyzePage {
! 63: my ($cacheDB, $students, $courseID)=@_;
! 64:
! 65: my $Str = '';
! 66: my %cache;
! 67: unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
! 68: $Str .= '<html><body>Unable to tie database.</body></html>';
! 69: return $Str;
! 70: }
! 71:
! 72: my $uri = $cache{'AnalyzeURI'},
! 73: my $part = $cache{'AnalyzePart'},
! 74: my $problem = $cache{'AnalyzeProblem'},
! 75: my $title = $cache{'AnalyzeTitle'},
! 76: my $interval = $cache{'Interval'},
! 77:
! 78: my %ConceptData;
! 79: $ConceptData{"Interval"} = $interval;
! 80:
! 81: #Initialize the option response true answers
! 82: my ($Concepts, $foil_to_concept, $answer) = &InitAnalysis($uri, $part,
! 83: $problem,
! 84: $students->[0],
! 85: $courseID);
! 86:
! 87: #compute the intervals
! 88: &Interval($part, $problem, $interval, $Concepts, \%ConceptData);
! 89:
! 90: $title =~ s/\ /"_"/eg;
! 91: $Str .= '<br><b>'.$uri.'</b>';
! 92:
! 93: #Java script Progress window
! 94: &Create_PrgWin();
! 95: &Update_PrgWin("Starting-to-analyze-problem");
! 96: for (my $index=0;$index<(scalar @$students);$index++) {
! 97: &Update_PrgWin($index);
! 98: &OpStatus($problem, $students->[$index], $courseID, $answer);
! 99: }
! 100: &Close_PrgWin();
! 101:
! 102: $Str .= '<br>';
! 103: for (my $k=0; $k<$interval; $k++ ) {
! 104: $Str .= &DrawGraph($k, $title, $Concepts, \%ConceptData);
! 105: }
! 106: for (my $k=0; $k<$interval; $k++ ) {
! 107: $Str .= &DrawTable($k, $Concepts, \%ConceptData);
! 108: }
! 109: #$Apache::lonxml::debug=1;
! 110: #&Apache::lonhomework::showhash(%ConceptData);
! 111: #$Apache::lonxml::debug=0;
! 112: my $Answ=&Apache::lonnet::ssi($uri);
! 113: $Str .= '<br><b>Here you can see the Problem:</b><br>'.$Answ;
! 114:
! 115: untie(%cache);
! 116:
! 117: return $Str;
! 118: }
! 119:
! 120: #---- Problem Analysis Web Page ----------------------------------------------
! 121:
! 122: sub IntervalOptions {
! 123: my ($selectedInterval)=@_;
! 124:
! 125: my $interval = 1;
! 126: for(my $n=1; $n<=7; $n++) {
! 127: if($selectedInterval == $n) {
! 128: $interval = $n;
! 129: }
! 130: }
! 131:
! 132: my $Ptr = '<br><b>Select number of intervals</b>'."\n".
! 133: '<select name="Interval">'."\n";
! 134: for(my $n=1; $n<=7;$ n++) {
! 135: $Ptr .= '<option';
! 136: if($interval == $n) {
! 137: $Ptr .= ' selected';
! 138: }
! 139: $Ptr .= '>'.$n."</option>"."\n";
! 140: }
! 141: $Ptr .= '</select>'."\n";
! 142:
! 143: return $Ptr;
! 144: }
! 145:
! 146: sub OptionResponseTable {
! 147: my ($optionResponses)=@_;
! 148: my $Str = '';
! 149: $Str .= '<br><b> Option Response Problems in this course:</b>'."\n";
! 150: $Str .= '<br><br>'."\n";
! 151: $Str .= "<table border=2><tr><th> \# </th><th> Problem Title </th>";
! 152: $Str .= '<th> Resource </th><th> Analysis </th></tr>'."\n";
! 153:
! 154: my $number=1;
! 155: foreach (split(':::', $optionResponses)) {
! 156: my ($uri,$title,$part,$problem)=split('::',$_);
! 157: my $Temp = '<a href="'.$uri.'" target="_blank">'.$title.'</a>';
! 158: $Str .= '<tr>';
! 159: $Str .= '<td> '.$number.' </td>';
! 160: $Str .= '<td bgcolor="#DDFFDD"> '.$Temp.' </td>';
! 161: $Str .= '<td bgcolor="#EEFFCC"> '.$uri.' </td>';
! 162: $Str .= '<td><input type="submit" name="Analyze:::'.$uri.':::';
! 163: $Str .= $title.':::'.$part.':::'.$problem.'" value="';
! 164: $Str .= 'Analyze" /></td></tr>'."\n";
! 165: $number++;
! 166: }
! 167: $Str .= '</table>'."\n";
! 168:
! 169: return $Str;
! 170: }
! 171:
! 172: #---- END Problem Analysis Web Page ------------------------------------------
! 173:
! 174: #---- Analyze Web Page -------------------------------------------------------
! 175:
! 176: #restore the student submissions and finding the result
! 177: sub OpStatus {
! 178: my ($problem, $student, $courseID, $ConceptData, $foil_to_concept,
! 179: $Answer)=@_;
! 180: my ($username,$userdomain)=split(/':'/,$student);
! 181: my $code='U';
! 182: my %reshash=&Apache::lonnet::restore($problem, $courseID, $userdomain,
! 183: $username);
! 184: my @True = ();
! 185: my @False = ();
! 186: my $flag=0;
! 187: if ($reshash{'version'}) {
! 188: my $tries=0;
! 189: &Apache::lonhomework::showhash(%$Answer);
! 190: for (my $version=1;$version<=$reshash{'version'};$version++) {
! 191: my $time=$reshash{"$version:timestamp"};
! 192:
! 193: foreach my $key (sort(split(/\:/,$reshash{$version.':keys'}))) {
! 194: if (($key=~/\.(\w+)\.(\w+)\.submission$/)) {
! 195: my $Id1 = $1; my $Id2 = $2;
! 196: #check if this is a repeat submission, if so skip it
! 197: if ($reshash{"$version:resource.$Id1.previous"}) { next; }
! 198: #if no solved this wasn't a real submission, ignore it
! 199: if (!defined($reshash{"$version:resource.$Id1.solved"})) {
! 200: &Apache::lonxml::debug("skipping ");
! 201: next;
! 202: }
! 203: my $Resp = $reshash{"$version:$key"};
! 204: my %submission=&Apache::lonnet::str2hash($Resp);
! 205: foreach (keys %submission) {
! 206: my $Ansr = $Answer->{"$Id1.$Id2.foil.value.$_"};
! 207: if ($submission{$_}) {
! 208: if ($submission{$_} eq $Ansr) {
! 209: &Decide("true", $foil_to_concept->{$_},
! 210: $time, $ConceptData);
! 211: } else {
! 212: &Decide("false", $foil_to_concept->{$_},
! 213: $time, $ConceptData);}
! 214: }
! 215: }
! 216: }
! 217: }
! 218: }
! 219: }
! 220: }
! 221:
! 222: sub DrawGraph {
! 223: my ($k,$Src,$Concepts,$ConceptData)=@_;
! 224: my $Max=0;
! 225: my @data1;
! 226: my @data2;
! 227:
! 228: # Adjust Data and find the Max
! 229: for (my $n=0; $n<(scalar @$Concepts); $n++ ) {
! 230: my $tmp=$Concepts->[$n];
! 231: $data1[$n]=$ConceptData->{$tmp.'.'.$k.'.true'};
! 232: $data2[$n]=$ConceptData->{$tmp.'.'.$k.'.false'};
! 233: my $Sum=$data1[$n]+$data2[$n];
! 234: if($Max < $Sum) {
! 235: $Max=$Sum;
! 236: }
! 237: }
! 238: for (my $n=0; $n<(scalar @$Concepts); $n++ ) {
! 239: if ($data1[$n]+$data2[$n]<$Max) {
! 240: $data2[$n]+=$Max-($data1[$n]+$data2[$n]);
! 241: }
! 242: }
! 243: my $P_No = (scalar @data1);
! 244:
! 245: if($Max > 1) {
! 246: $Max += (10 - $Max % 10);
! 247: $Max = int($Max);
! 248: } else {
! 249: $Max = 1;
! 250: }
! 251:
! 252: my $Titr=($ConceptData->{'Interval'}>1) ? $Src.'_interval_'.($k+1) : $Src;
! 253: # $GData=$Titr.'&Concepts'.'&'.'Answers'.'&'.$Max.'&'.$P_No.'&'.$data1.'&'.$data2;
! 254: my $GData = '';
! 255: $GData = $Titr.'&Concepts&Answers&'.$Max.'&'.$P_No.'&';
! 256: $GData .= (join(',',@data1)).'&'.(join(',',@data2));
! 257:
! 258: return '<IMG src="/cgi-bin/graph.gif?'.$GData.'" border=1/>';
! 259: }
! 260:
! 261: sub DrawTable {
! 262: my ($k,$Concepts,$ConceptData)=@_;
! 263: my $Max=0;
! 264: my @data1;
! 265: my @data2;
! 266: my $Correct=0;
! 267: my $Wrong=0;
! 268: for(my $n=0; $n<(scalar @$Concepts); $n++ ) {
! 269: my $tmp=$Concepts->[$n];
! 270: $data1[$n]=$ConceptData->{$tmp.'.'.$k.'.true'};
! 271: $Correct+=$data1[$n];
! 272: $data2[$n]=$ConceptData->{$tmp.'.'.$k.'.false'};
! 273: $Wrong+=$data2[$n];
! 274: my $Sum=$data1[$n]+$data2[$n];
! 275: if($Max < $Sum) {
! 276: $Max=$Sum;
! 277: }
! 278: }
! 279: for(my $n=0; $n<(scalar @$Concepts); $n++ ) {
! 280: if ($data1[$n]+$data2[$n]<$Max) {
! 281: $data2[$n]+=$Max-($data1[$n]+$data2[$n]);
! 282: }
! 283: }
! 284: my $P_No = (scalar @data1);
! 285: my $Str = '';
! 286: # $Str .= '<br><b>From: ['.localtime($ConceptData->{'Int.'.($k-1)});
! 287: # $Str .= '] To: ['.localtime($ConceptData->{"Int.$k"}).']</b>';
! 288: $Str .= "\n".'<table border=2>'.
! 289: "\n".'<tr>'.
! 290: "\n".'<th> # </th>'.
! 291: "\n".'<th> Concept </th>'.
! 292: "\n".'<th> Correct </th>'.
! 293: "\n".'<th> Wrong </th>'.
! 294: "\n".'</tr>';
! 295:
! 296: for(my $n=0; $n<(scalar @$Concepts); $n++ ) {
! 297: $Str .= '<tr>'."\n";
! 298: $Str .= '<td>'.($n+1).'</td>'."\n";
! 299: $Str .= '<td bgcolor="EEFFCC">'.$Concepts->[$n];
! 300: $Str .= '</td>'."\n";
! 301: $Str .= '<td bgcolor="DDFFDD">'.$data1[$n].'</td>'."\n";
! 302: $Str .= '<td bgcolor="FFDDDD">'.$data2[$n].'</td>'."\n";
! 303: $Str .= '</tr>'."\n";
! 304: }
! 305: $Str .= '<td></td><td><b>From:['.localtime($ConceptData->{'Int.'.$k});
! 306: $Str .= '] To: ['.localtime($ConceptData->{'Int.'.($k+1)}-1);
! 307: $Str .= ']</b></td><td>'.$Correct.'</td><td>'.$Wrong.'</td>';
! 308: $Str .= '</table>'."\n";
! 309:
! 310: return $Str;
! 311: #$Apache::lonxml::debug=1;
! 312: #&Apache::lonhomework::showhash(%ConceptData);
! 313: #$Apache::lonxml::debug=0;
! 314: }
! 315:
! 316: #---- END Analyze Web Page ----------------------------------------------
! 317:
! 318: sub Decide {
! 319: #deciding the true or false answer belongs to each interval
! 320: my ($type,$concept,$time,$ConceptData)=@_;
! 321: my $k=0;
! 322: while ($time>$ConceptData->{'Int.'.($k+1)} &&
! 323: $k<$ConceptData->{'Interval'}) {$k++;}
! 324: $ConceptData->{$concept.'.'.$k.'.'.$type}++;
! 325:
! 326: return;
! 327: }
! 328:
! 329: sub InitAnalysis {
! 330: my ($uri,$part,$problem,$student,$courseID)=@_;
! 331: my ($name,$domain)=split(/\:/,$student);
! 332:
! 333: # Render the student's view of the problem. $Answ is the problem
! 334: # Stringafied
! 335: my $Answ=&Apache::lonnet::ssi($uri,('grade_target' => 'analyze',
! 336: 'grade_username' => $name,
! 337: 'grade_domain' => $domain,
! 338: 'grade_courseid' => $courseID,
! 339: 'grade_symb' => $problem));
! 340: # my $Answ=&Apache::lonnet::ssi($URI,('grade_target' => 'analyze'));
! 341:
! 342: # (my $garbage,$Answ)=split(/_HASH_REF__/,$Answ,2);
! 343: my %Answer=();
! 344: %Answer=&Apache::lonnet::str2hash($Answ);
! 345:
! 346: my $parts='';
! 347: foreach my $elm (@{$Answer{'parts'}}) {
! 348: $parts.= $elm.',';
! 349: }
! 350: $parts =~ s/,$//;
! 351:
! 352: my @Concepts=();
! 353: foreach my $elm (@{$Answer{$parts.'.concepts'}}) {
! 354: push(@Concepts, $elm);
! 355: }
! 356:
! 357: my %foil_to_concept;
! 358: foreach my $concept (@Concepts) {
! 359: foreach my $foil (@{$Answer{$parts.'.concept.'.$concept}}) {
! 360: $foil_to_concept{$foil} = $concept;
! 361: #$ConceptData{$foil} = $Answer{$parts.'.foil.value.'.$foil};
! 362: }
! 363: }
! 364:
! 365: return (\@Concepts, \%foil_to_concept, \%Answer);
! 366: }
! 367:
! 368: sub Interval {
! 369: my ($part,$symb,$interval,$Concepts,$ConceptData)=@_;
! 370: my $Int=$interval;
! 371: my $due = &Apache::lonnet::EXT('resource.'.$part.'.duedate',$symb);
! 372: my $opn = &Apache::lonnet::EXT('resource.'.$part.'.opendate',$symb);
! 373: my $add=int(($due-$opn)/$Int);
! 374: $ConceptData->{'Int.0'}=$opn;
! 375: for (my $i=1;$i<$Int;$i++) {
! 376: $ConceptData->{'Int.'.$i}=$opn+$i*$add;
! 377: }
! 378: $ConceptData->{'Int.'.$Int}=$due;
! 379: for (my $i=0;$i<$Int;$i++) {
! 380: for (my $n=0; $n<(scalar @$Concepts); $n++ ) {
! 381: my $tmp=$Concepts->[$n];
! 382: $ConceptData->{$tmp.'.'.$i.'.true'}=0;
! 383: $ConceptData->{$tmp.'.'.$i.'.false'}=0;
! 384: }
! 385: }
! 386: }
! 387: 1;
! 388: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>