Parent Directory
|
Revision Log
Revision 1533 - (view) (download) (as text)
| 1 : | sh002i | 1533 | #!/usr/bin/env perl |
| 2 : | sam | 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 : | apizer | 409 | my ($setNumber,$setHeaderFileName,$probHeaderFileName,$dueDate,$openDate,$answerDate,$problemListref,$problemValueListref,$problemAttemptLimitListref,$problemContinuationFlagListref) |
| 50 : | sam | 2 | = &readSetDef($fileName); |
| 51 : | my @problemList = @$problemListref; | ||
| 52 : | my @problemValueList = @$problemValueListref; | ||
| 53 : | my @problemAttemptLimitList = @$problemAttemptLimitListref; | ||
| 54 : | apizer | 409 | my @problemContinuationFlagList = (defined($problemContinuationFlagListref) ? @$problemContinuationFlagListref : (0)x scalar(@problemList)); |
| 55 : | sam | 2 | $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 : | gage | 6 | if (&probSetExists($setNumber)) {%loginHashForSet = %{getLoginHashForSet($setNumber)};} |
| 152 : | sam | 2 | 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 : | gage | 6 | attachCLRecord($oldLogin); |
| 197 : | |||
| 198 : | my $oldFN = &CL_getStudentFirstName($oldLogin); | ||
| 199 : | my $oldLN = &CL_getStudentLastName($oldLogin); | ||
| 200 : | |||
| 201 : | sam | 2 | # 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 : | gage | 6 | # &putStudentLastName ($lastName, $PIN); |
| 260 : | # &putStudentFirstName ($firstName, $PIN); | ||
| 261 : | # &putStudentID ($studentID, $PIN); | ||
| 262 : | sam | 2 | &putStudentLogin ($login_name,$PIN); |
| 263 : | gage | 6 | # &putStudentStatus ($status,$PIN); |
| 264 : | # &putClassSection ($section,$PIN); | ||
| 265 : | # &putClassRecitation ($recitation,$PIN); | ||
| 266 : | sam | 2 | &putSetNumber ($setNumber, $PIN); |
| 267 : | &putSetHeaderFileName ($setHeaderFileName, $PIN); | ||
| 268 : | &putProbHeaderFileName ($probHeaderFileName, $PIN); | ||
| 269 : | &putDueDate ($dueDate, $PIN); | ||
| 270 : | &putOpenDate ($openDate, $PIN); | ||
| 271 : | &putAnswerDate ($answerDate, $PIN); | ||
| 272 : | gage | 6 | # &putStudentEmailAddress ($email_address, $PIN); |
| 273 : | sam | 2 | |
| 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 : | apizer | 409 | else { |
| 284 : | # note continuationflag is zero for first problem & if unspecified | ||
| 285 : | unless( $problemContinuationFlagList[$i] ) { $probSeed = int(rand(5000)); } | ||
| 286 : | } | ||
| 287 : | sam | 2 | |
| 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 |