Quizbank/Python/unpickle.py

From Wikiversity
Jump to navigation Jump to search

The output exam file it typically quite long because it prints all versions of all exams. This is convenient if the intent is to print every exam for an entire semester before the semester starts. To permit individual options, I modified program.py to "pickle" python lists that permit this program (unpickle.py) to take those lists and break the exam file up into smaller units.

unpickle.py[edit]

#Keep this in the QuizSoftware folder next to program.py
#program.py finds it here and copies it to output
#last update 180516
import os
import pickle
import re
import shutil
##import time##import random##import sys##import csv
#
#Unpickles some exam info and creates ListExams
def unPickle():
  if not os.path.exists("courseinfo.pickle"):
    print("Unable to find courseinfo.pickle in folder")
  else:
    courseInfo = pickle.load( open( "courseinfo.pickle", "rb" ) )
    #print("courseinfo.pickle has been opened")
    courseData=courseInfo[0]
    courseName = courseData[0]
    numberOfVersions=courseInfo[1]                    
    testNames = courseData[1][0][5:]
    examsList = open("exams.txt").readlines()
  #for diagnostic purposes I delete unpacked
  try:
    shutil.rmtree("./unpacked")
  except OSError:
    pass
  #Now create if it does not exist
  if not os.path.exists("./unpacked"):
    os.makedirs("./unpacked")
  print('exiting unPickle')
  return[examsList,courseName, testNames, numberOfVersions]
#
#getmore gets more info
def getmore(examsList):
  outputNames=[]
  titleNumbers=[]
  totalLines=len(examsList)
  #This creates outputNames even if no file is never opened.
  for lineNum in range(totalLines):
    line=examsList[lineNum]
    tag=re.search('===',line)
    if tag !=None:
      filename=line.replace('===','') 
      filename=filename.replace(':','')
      filename=filename.strip('\n')
      filename="unpacked/" + filename+ ".txt"
      #print(filename)
      outputNames.append(filename)
      #print('in getmore: lineNum= ',lineNum)
      titleNumbers.append(lineNum)
  titleNumbers.append(totalLines+1)
  #The last line in titleNumbers exceeds examsList (by 1)
  print('exiting getmore\n')
  return [outputNames,titleNumbers]
    

#
#Start program

[examsList,courseName, testNames, numberOfVersions]= unPickle()
totalLines=len(examsList)
#examsList contains the textfile that prints ALL exams
#courseName, testNames, numberOfVersions are attached to course
#the numberOfVersions does not include V0; hence often use (numberOfVersions+1)
[outputNames,titleNumbers]=getmore(examsList)
print("courseName = ",courseName)                      
print("numberOfVersions = ", numberOfVersions)
print('totalLines: ',totalLines)
print('TitleNumbers',titleNumbers,'\n')
#print('outputNames',outputNames,'\n')#unpacked/<course><test>V#.txt

#
#create list of header lines from first few lines of examsList
header=[]#header will be the first page of each textfile
headerRange = titleNumbers[0] #first instance of ===
for lineNum in range(headerRange):#take out last line b/c gets printed later
  header.append(examsList[lineNum])
print('header\n',header,'\n')

#
#Make each test (w/o key)
#   We use j to index which of the 
print('Making each version of each test')  
for testNum in range(len(testNames)): #testNum starts at 0
  testName = testNames[testNum]
  #j is the index in outputNames for tests (w/o keys)
  j=testNum*2*(numberOfVersions+1)+2 #this gets us to V1 exam, later advance
  for testVer in range(1,numberOfVersions+1): #testVer starts at 1
    j=j+(testVer-1)* 2   
#
# start print2unpacked for versions 1, 2, ... of testName
    titleAt = titleNumbers[j] ###Diagnostic print to screen
    print(testName,j,"<",len(titleNumbers),titleNumbers[j],examsList[titleAt].strip('\n'))
    #open the file
    outputName=outputNames[j] 
    file=open(outputName,'w')
    for headerline in range(len(header)):
      file.write(header[headerline])
    startLine=titleNumbers[j] #first line to be printed (go back one)
    stopLine =titleNumbers[j+1]-1 #I think this includes unwanted harmless line
    for line in range(startLine,stopLine):
      file.write(examsList[line])
    file.close()
    #file has been closed   
#
#Make instructors version for each test (w/keys for all versions)
print('')#creates blank line
print('Making instructor versions V0 of each test (w/ keys for V#0)\n')
for testNum in range(0,len(testNames)): #testNum starts at 0 (first test)
  testName = testNames[testNum]
  #V0name is the name of the file of the instructors version for each test
  V0name = outputNames[2*testNum*(numberOfVersions+1)]
  print('opening ',testName,V0name)
  #printing header page  
  #j is the index in outputNames for V0 questions and find titleAt
  j=testNum*2*(numberOfVersions+1)
  titleAt = titleNumbers[j]  ###Diagnostic print to screen
###open textfile for this testNum and print header
  outputName=outputNames[j] 
  file=open(outputName,'w')
  for headerline in range(len(header)):
    file.write(header[headerline]) 
  print(testName,j,"<",len(titleNumbers),titleNumbers[j],examsList[titleAt].strip('\n'))
  startLine=titleNumbers[j] #first line to be printed (go back one)
  stopLine =titleNumbers[j+1]-1 #I think this includes unwanted harmless line
  for line in range(startLine,stopLine):
      file.write(examsList[line])
  #advance j for key to V0 and find titleAt
  j=j+1
  titleAt = titleNumbers[j]
  print(testName,j,"<2",len(titleNumbers),titleNumbers[j],examsList[titleAt].strip('\n'))
  startLine=titleNumbers[j] #first line to be printed (go back one)
  stopLine =titleNumbers[j+1]-1 #I think this includes unwanted harmless line
  for line in range(startLine,stopLine):
      file.write(examsList[line]) 
  #j is the index in outputNames for keys and find titleAt  Starts at v1
  for testVer in range(1,numberOfVersions+1): #testVer starts at 1
    j=2*testVer + testNum*2*(numberOfVersions+1) + 1 #I think the +1 advances to key
    titleAt = titleNumbers[j] ###Diagnostic print to screen
    print(testName,j,"<3",len(titleNumbers),titleNumbers[j],examsList[titleAt].strip('\n'))
    startLine=titleNumbers[j] #first line to be printed (go back one)
    stopLine =titleNumbers[j+1]-1 #I think this includes unwanted harmless line
    for line in range(startLine,stopLine):
      file.write(examsList[line])
  print('closing ',testName,'\n')
  file.close
###closed textfile for this testNum