Parent Directory
|
Revision Log
Incorporate Gavin's changes enabling linked problems
1 #!/usr/local/bin/webwork-perl 2 3 ## $Id$ 4 5 6 #################################################################### 7 # Copyright @ 1995-1998 University of Rochester 8 # All Rights Reserved 9 #################################################################### 10 11 12 13 # This file is proceduresForBuildProbSetDB.pl 14 # Call with command arguments of the form: set5.def classl.gp 15 # This file loads the database from the class list and the set definition 16 ################################################################### 17 18 use strict; 19 20 #$method ='readFromLogFile'; ## or 'createNewPSVNs' 21 #$method ='createNewPSVNs'; 22 #$logFileName = "sampleCourse_set:3_bak3.psvnlog"; 23 24 25 ######################### 26 27 sub buildProbSetDB ## builds the problem set and returns a message 28 { 29 my ($classID,$setDefFilename,$method,$logFileName,$outputFormat) = @_; 30 my $scriptDirectory = $Global::scriptDirectory; 31 &Global::getCourseEnvironment("$classID"); 32 my $databaseDirectory = $Global::databaseDirectory; 33 my $templateDirectory = $Global::templateDirectory; 34 my $logsDirectory = getCourseLogsDirectory(); 35 36 require "${scriptDirectory}$Global::DBglue_pl"; 37 require "${scriptDirectory}$Global::classlist_DBglue_pl"; 38 require "${scriptDirectory}$Global::FILE_pl"; 39 40 41 # Get data from set definition 42 43 my $fileName="${templateDirectory}$setDefFilename"; ## e.g. $fileName=set5.def 44 my $PIN; 45 my $message = ''; 46 $message .= "\nGetting set definition from file: $fileName\n"; 47 # print "Getting set definition from file: $fileName\n"; 48 49 my ($setNumber,$setHeaderFileName,$probHeaderFileName,$dueDate,$openDate,$answerDate,$problemListref,$problemValueListref,$problemAttemptLimitListref,$problemContinuationFlagListref) 50 = &readSetDef($fileName); 51 my @problemList = @$problemListref; 52 my @problemValueList = @$problemValueListref; 53 my @problemAttemptLimitList = @$problemAttemptLimitListref; 54 my @problemContinuationFlagList = (defined($problemContinuationFlagListref) ? @$problemContinuationFlagListref : (0)x scalar(@problemList)); 55 $message .= " set Name or Number: $setNumber\n openDate: $openDate\n dueDate: $dueDate\n answerDate: $answerDate\n\n"; 56 57 58 ## put dates into standard perl format, i.e. seconds since 1980 59 60 $openDate = &unformatDateAndTime($openDate); 61 $dueDate = &unformatDateAndTime($dueDate); 62 $answerDate = &unformatDateAndTime($answerDate); 63 64 65 #get data from class list. 66 # $fileName="${templateDirectory}$classlistFilename"; ## e.g. fileName=m161.lst 67 # print "Getting class list from $fileName\n"; 68 # checkClasslistFile($Global::noOfFieldsInClasslist,$fileName); 69 # open(FILE, "$fileName") || wwerror($0, "Can't open $fileName"); 70 # my @classList=<FILE>; 71 # close(FILE); 72 ################################### 73 # Before building the database we pause to check that the database file exists 74 # (if not we create it). 75 ################################### 76 if ( -e "${databaseDirectory}$Global::database" ) { 77 78 my @data = stat("${databaseDirectory}$Global::database"); 79 ## This statement is a hack. When using Berkeley DB 1.85 on a FreeBSD system 80 ## sometimes this test returns true even when the database file does not exist. 81 ## We have never seen this happen with the stat statement. Very strange indeed. 82 83 # $message .= "data base file statistics: @data\n\n"; 84 85 $message .= "Loading WeBWorK database: ${databaseDirectory}$Global::database\n"; 86 } 87 else { 88 # print "Data base ${databaseDirectory}$Global::database does not exist.\n\n"; 89 $message .= "Data base ${databaseDirectory}$Global::database does not exist.\n\n"; 90 # print "Create new database?(y or n)"; 91 # my $tempinput = <STDIN>; 92 my $tempinput = 'y'; ## always create a new database 93 if ($tempinput =~ /y|Y/) { 94 # print "Creating new data base ${databaseDirectory}$Global::database.\n"; 95 $message .= "Creating new data base ${databaseDirectory}$Global::database.\n"; 96 create_db("${databaseDirectory}$Global::database", $Global::webwork_database_permission); 97 if ( -e "${databaseDirectory}$Global::database" ) { 98 chmod($Global::webwork_database_permission,"${databaseDirectory}$Global::database") || 99 wwerror($0, "Can't do chmod($Global::webwork_database_permission,${databaseDirectory}$Global::database)"); 100 chown(-1,$Global::numericalGroupID,"${databaseDirectory}$Global::database") || 101 wwerror($0,"Can't do chown(-1,$Global::numericalGroupID,${databaseDirectory}$Global::database)"); 102 # print "New data base created\n"; 103 $message .= "New data base created\n"; 104 } 105 else { 106 # print "New data base could not be created\n"; 107 $message .= "New data base could not be created\n"; 108 } 109 } 110 else { 111 112 print "Abort buildProbSetDB.pl\n\n"; 113 exit; 114 } 115 } 116 117 ## Create a logfile in which we will save the following data for each new psvn created 118 ## $login_name $PIN seedForProb1 seedForProb2 seedForProb3 ... 119 120 ##don't overwrite existing backups 121 my $i=1; 122 while(-e "${logsDirectory}${classID}_set:${setNumber}_bak${i}.psvnlog") {$i++;} 123 my $fullLogFileName ="${logsDirectory}${classID}_set:${setNumber}_bak${i}.psvnlog"; 124 &createFile($fullLogFileName, 0660, $Global::numericalGroupID); 125 open(LOGFILE,">$fullLogFileName") or wwerror($0, "Can't open $fullLogFileName"); 126 127 ## two hashes which are used in 'readFromLogFile' mode 128 my (%psvnsHash,%seedsHash,@seedsArrayFromLogFile); 129 130 if ($method eq 'readFromLogFile') { 131 my (@lineArray, $loginID, $seedString); 132 $logFileName = "${logsDirectory}${logFileName}"; 133 # print "Getting psvn's and problem seeds from $logFileName\n\n"; 134 $message .= "Getting psvn's and problem seeds from $logFileName\n\n"; 135 open(BAKLOGFILE,"$logFileName") or wwerror($0, "Can't open $logFileName"); 136 while (<BAKLOGFILE>) 137 { 138 @lineArray = split; 139 $loginID= shift(@lineArray); 140 $psvnsHash{$loginID} = shift(@lineArray); 141 $seedString = join ':', @lineArray; 142 $seedsHash{$loginID} = $seedString; 143 } 144 close(BAKLOGFILE); 145 } 146 147 148 ## get a hash of all loginID's for set if set is already defined 149 150 my %loginHashForSet =(); 151 if (&probSetExists($setNumber)) {%loginHashForSet = %{getLoginHashForSet($setNumber)};} 152 my $new_student_count = 0; 153 my $existing_student_count = 0; 154 155 my $login_name; 156 157 $message .= "Loading classlist database: ${databaseDirectory}$Global::CL_Database\n\n"; 158 my @classList = @{getAllLoginNamesSortedByName()}; 159 160 foreach $login_name (@classList) { ## read through classlist database and create 161 ## problems for all active students 162 ## except if problems already exist for 163 attachCLRecord($login_name); 164 ## student 165 my $lastName = CL_getStudentLastName($login_name); 166 my $firstName = CL_getStudentFirstName($login_name); 167 my $status = CL_getStudentStatus($login_name); 168 my $comment = CL_getComment($login_name); 169 my $section = CL_getClassSection($login_name); 170 my $recitation = CL_getClassRecitation($login_name); 171 my $email_address = CL_getStudentEmailAddress($login_name); 172 my $studentID = CL_getStudentID($login_name); 173 174 175 176 unless (&dropStatus($status)) ## skip students who have dropped the course 177 { 178 if (defined $loginHashForSet{$login_name}) { 179 $existing_student_count++; 180 if (((defined $outputFormat) and ($outputFormat eq 'all_students')) or ($method eq 'readFromLogFile')){ 181 $message .= " Problems for $firstName $lastName (login $login_name) already exist. \n"; 182 $message .= " Retaining probsetkey $loginHashForSet{$login_name} and data. \n"; 183 } 184 } 185 elsif (($method eq 'readFromLogFile') and !(defined($psvnsHash{$login_name}))) 186 { 187 # print "$firstName $lastName (login $login_name) is not in the logfile $logFileName. \n"; 188 $message .= " $firstName $lastName (login $login_name) is not in the logfile $logFileName. \n"; 189 # print " Problems for $firstName $lastName (login $login_name) not added.\n"; 190 $message .= " Problems for $firstName $lastName (login $login_name) not added.\n"; 191 } 192 elsif (($method eq 'readFromLogFile') and (&attachProbSetRecord($psvnsHash{$login_name}) )) 193 { 194 $PIN = $psvnsHash{$login_name}; 195 my $oldLogin = &getStudentLogin($PIN); 196 attachCLRecord($oldLogin); 197 198 my $oldFN = &CL_getStudentFirstName($oldLogin); 199 my $oldLN = &CL_getStudentLastName($oldLogin); 200 201 # print "ERROR, ERROR, ERROR\n"; 202 # print " The psvn $PIN already exists. It is assigned to $oldFN $oldLN ($oldLogin).\n"; 203 # print " A new problem set must have been created after the psvn $PIN for \n"; 204 # print " $firstName $lastName (login $login_name) was deleted.\n"; 205 # print " Problems for $firstName $lastName (login $login_name) have not been added.\n"; 206 # print " After restoring all other psvn's for this set from the psvnlog(s),\n"; 207 # print " run buildProbSetDB.pl. This will create a new psvn for $login_name.\n"; 208 # print " Then use the dataMonger to restore the original problem seeds for\n"; 209 # print " $login_name. The seeds for $login_name are listed in order in the file\n"; 210 # print " $logFileName, on the line begining: $login_name $PIN .\n"; 211 $message .= 212 "ERROR, ERROR, ERROR\n 213 The psvn $PIN already exists. It is assigned to $oldFN $oldLN ($oldLogin).\n 214 A new problem set must have been created after the psvn $PIN for \n 215 $firstName $lastName (login $login_name) was deleted.\n 216 Problems for $firstName $lastName (login $login_name) have not been added.\n 217 After restoring all other psvn's for this set from the psvnlog(s), use \n 218 Build problem sets from the Professor's page to build this set again. This \n 219 will create a new psvn for $login_name.\n 220 Then use Examine or modify data from the Professor's page to restore the original \n 221 problem seeds for $login_name. The seeds for $login_name are listed in order in \n 222 the file $logFileName, on the line begining: $login_name $PIN .\n"; 223 224 } 225 else 226 { 227 if ($method eq 'readFromLogFile') 228 { 229 $PIN = $psvnsHash{$login_name}; 230 } 231 else 232 { 233 # Create a new unique pin number; 234 my $min_psnv = 10**($Global::psvn_digits - 1); 235 my $big_psvn = 10**$Global::psvn_digits - $min_psnv - 1; 236 $PIN = int ( rand($big_psvn)+$min_psnv ); ##eg rand(8999)+1000 237 $i=0; 238 # Try for up to 200 times to create a pin number which hasn't been used. 239 while ( &attachProbSetRecord($PIN) ) { 240 # print "psvn Number $PIN already taken\n" if $i>0 ; 241 $message .= "psvn Number $PIN already taken\n" if $i>0 ; 242 $PIN = int ( rand($big_psvn)+$min_psnv ); 243 ++$i; 244 if ($i>200) { wwerror($0, 'Tried 200 times and could not find an unused psvn number. 245 You have run out of psvn numbers. In Global.pm, increase the variable \$psvn_digits')}; 246 }#end while loop 247 } ##end of if ($method eq 'readFromLogFile') 248 # Store the record of pin numbers in @pinNumbersArray 249 # This can be used to delete pin numbers in case of a failure. 250 251 # push(@pinNumbersArray, $PIN); 252 253 # Create a random security number 254 # $securityNumber=int rand(99999); 255 # print "security number is $securityNumber\n"; 256 257 # Install the necessary variables into pinRecord 258 259 # &putStudentLastName ($lastName, $PIN); 260 # &putStudentFirstName ($firstName, $PIN); 261 # &putStudentID ($studentID, $PIN); 262 &putStudentLogin ($login_name,$PIN); 263 # &putStudentStatus ($status,$PIN); 264 # &putClassSection ($section,$PIN); 265 # &putClassRecitation ($recitation,$PIN); 266 &putSetNumber ($setNumber, $PIN); 267 &putSetHeaderFileName ($setHeaderFileName, $PIN); 268 &putProbHeaderFileName ($probHeaderFileName, $PIN); 269 &putDueDate ($dueDate, $PIN); 270 &putOpenDate ($openDate, $PIN); 271 &putAnswerDate ($answerDate, $PIN); 272 # &putStudentEmailAddress ($email_address, $PIN); 273 274 my @seedList =(); 275 my ($probNumber,$probSeed); 276 # Generate the problems 277 if ($method eq 'readFromLogFile') {@seedsArrayFromLogFile = split /:/,$seedsHash{$login_name};} 278 for($i=0; $i<@problemList; ++$i) { 279 $probNumber=$i+1; 280 &putProblemFileName ($problemList[$i],$probNumber, $PIN); 281 282 if ($method eq 'readFromLogFile') {$probSeed = shift @seedsArrayFromLogFile;} 283 else { 284 # note continuationflag is zero for first problem & if unspecified 285 unless( $problemContinuationFlagList[$i] ) { $probSeed = int(rand(5000)); } 286 } 287 288 push (@seedList,$probSeed); ## put seed in array to be saved later in log file 289 &putProblemSeed ($probSeed,$probNumber, $PIN); 290 &putProblemValue ($problemValueList[$i],$probNumber, $PIN); 291 &putProblemMaxNumOfIncorrectAttemps ($problemAttemptLimitList[$i],$probNumber, $PIN); 292 &putProblemAttempted(0,$probNumber, $PIN); 293 &putProblemStatus(0,$probNumber, $PIN); 294 &putProblemNumOfCorrectAns (0,$probNumber, $PIN); 295 &putProblemNumOfIncorrectAns (0,$probNumber, $PIN); 296 } 297 298 299 if (&detachProbSetRecord($PIN) ) { 300 # print "probSetKey $PIN for $firstName $lastName (login $login_name) inserted succesfully\n"; 301 302 if ( 303 ((defined $outputFormat) and ($outputFormat ne 'no_students')) or 304 ($method eq 'readFromLogFile') 305 ) { 306 $message .= "probSetKey $PIN for $firstName $lastName (login $login_name) inserted succesfully\n"; 307 } 308 $new_student_count++; 309 # print "$login_name $PIN @seedList \n"; 310 print LOGFILE "$login_name $PIN @seedList \n"; 311 } 312 else { 313 # print "Couldn't insert probSetKey $PIN\n"; 314 $message .= "Couldn't insert probSetKey $PIN\n"; 315 }#endif 316 } # end if else 317 }#end unless 318 }#endforeachLoop 319 # print "\n"; 320 close(LOGFILE); 321 # print "DONE\n"; 322 $message .= "\nData entered for $new_student_count new student(s) in set $setNumber.\n"; 323 $message .= "Data left unchanged for $existing_student_count existing student(s) in set $setNumber.\n"; 324 $message .= "\nFINISHED BUILDING PROBLEM SET\n\n"; 325 $message; 326 } ### end of sub buildProbSetDB 327 328 1; 329
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |