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>