#!/usr/bin/env python # -*- coding: utf8 -*- # Python program to create # password-protected bonus files # Create pdf using FPDF # Encrypt PDF using pyPDF2 # Get file name and password import PyPDF2 import random import string from fpdf import FPDF from pathlib import Path from webcolors import name_to_rgb def createPassword(length): #characters = string.ascii_letters + string.digits + string.punctuation characters = string.ascii_letters + string.digits password = ''.join(random.choice(characters) for i in range(length)) return password # Create PDFs def createPDF(data, title, inputfile): class PDF(FPDF): def frame(self): self.rect(5.0, 5.0, 200.0,287.0) def bonusTask(self, startx, upperLine, task): row_width = pdf_w - 2 * left starty = self.get_y() self.set_font('Helvetica', '', 12) if starty <= top: starty = top self.set_xy(startx, starty) self.cell(w=row_width, h=text_height/2, align='C', txt=upperLine, border=0) self.ln() self.set_font('Helvetica', 'B', 14) self.cell(w=row_width, h=text_height/2, align='C', txt=task ,border=0) self.ln() self.ln() def ballTriangle(self, leftStart, topStart, width, task, plotColor, columns = 6): ballSize = 5 leftEnd = leftStart + width - ballSize colWidth = (leftEnd - leftStart) / (columns-1) colGrid = [leftStart + colWidth * i for i in range(columns)] numRows = 2 * columns - 1 rowHeight = (width - ballSize) / (numRows-1) rowGrid = [topStart + rowHeight * i for i in range(numRows)] middleRow = columns nodeNum = -1 # used for path coloring path = [0,1,4, 8 , 12] for lay in range(columns): col = colGrid[lay] startRow = middleRow - lay for nodes in range(lay + 1): nodeNum += 1 if lay == columns - 1: self.set_fill_color(0, 0, 0) elif task == "decoloring": self.set_fill_color(*name_to_rgb(plotColor)) elif nodeNum in path and task == "walking": self.set_fill_color(*name_to_rgb(plotColor)) else: self.set_fill_color(255, 255, 255) thisRow = startRow + nodes * 2 - 1 # -1 because indexing from 0 row = rowGrid[thisRow] self.ellipse(col, row, w=ballSize, h=ballSize, style= "DF") def option1(self, taskName, plotColor): drawx = (left + width - triangleHeight) / 2 drawy = self.get_y() + (1/10) * triangleHeight # Rectangle self.rect(left, self.get_y() , width , (1.2) * triangleHeight) #BallTraingle self.ballTriangle(drawx, drawy, triangleHeight, task=taskName, plotColor = plotColor) self.set_y(self.get_y() + (1.2) * triangleHeight) def titles(self, text): self.set_xy(0.0,10) self.set_font('Helvetica', 'B', 16) self.cell(w=210.0, h=20.0, align='C', txt=text, border=0) self.ln() def write_multicell_with_styles(self, startx, text_list, color = None): starty = self.get_y() self.set_font('', '', 14) if starty <= top: starty = top self.set_xy(startx, starty) th = self.font_size #loop through differenct sections in different styles for text_part in text_list: #check and set style try: current_style = text_part['style'] self.set_font('', current_style, 12) except KeyError: self.set_font('', '', 12) if color: line_break = False if '\n' in text_part['text']: line_break = True # Need to use cells for writing text to achieve coloring self.set_fill_color(232, 232, 232) #loop through words and write them down space_width = self.get_string_width(' ') for word in text_part['text'].split(): current_pos = self.get_x() word_width = self.get_string_width(word + " ") + space_width #check for newline if (current_pos + word_width) > (pdf_w - left): self.cell(w = 0, h= th * 1.3, fill=True) self.set_y(self.get_y() + th * 1.2) self.set_x(startx) if int(round(self.get_x(),0)) != startx: self.cell(word_width, th * 1.3, " " + word, fill=True) else: self.cell(word_width, th * 1.3, word, fill=True) # Add line if last element and line break symbol if line_break and word == list(text_part['text'].split())[-1]: self.cell(w = 0, h= th * 1.3, fill=True) self.ln(th * 1.2) if text_part == text_list[-1]: ## Fill Last Line self.cell(w = 0, h= th * 1.3, fill=True) else: self.write(th * 1.2 , text_part['text']) self.ln(th) pdf = PDF() #our pdf object # Define width pdf_w=210 #A4 page is 240mm wide left = 10 top = 30 text_height=14 triangleHeight = 60 task = data[0] plotColor = "" if data[1] == "green": plotColor = "seagreen" elif data[1] == "yellow": plotColor = "gold" elif data[1] == "red": plotColor = "maroon" if task=="walking": # Define Table properties width = pdf_w - 2 * left try: taskNumber = data[2] bonus_task = task.capitalize() + " Task " + str(taskNumber) + "." except: bonus_task = "the " + task.capitalize() + " Task." pdf.add_page() pdf.frame() pdf.titles(title) pdf.bonusTask(left, "Your bonus task is ", bonus_task) instr_text = [ {'style':'B','text':'Your bonus: '}, {'text':'Your bonus is determined by how you instructed the computer to walk through your decoloring during '}, {'text': bonus_task} ] pdf.write_multicell_with_styles(left, instr_text) pdf.ln() pdf.option1(task,plotColor) pdf.ln() note = [ {'style':'I','text':'Note: '}, {'text':' The decoloring and path shown above are illustrative and do not show your actual decoloring or path. '}, {'text': "Remember that you downloaded this file before the experiment. Therefore, its content cannot depend on how you completed " + bonus_task} ] pdf.write_multicell_with_styles(left, note) elif task == "decoloring": # Define Table properties width = pdf_w - 2 * left bonus_task = task.capitalize() + " Task." pdf.add_page() pdf.frame() pdf.titles(title) pdf.bonusTask(left, "Your bonus task is the ", bonus_task) instr_text = [ {'style':'B','text':'Your bonus: '}, {'text':'Your bonus is determined by how you instructed the computer to take the single risk repeatedly (by decoloring the '}, {'text': data[1]}, {'text':' ball triangle).'}, ] pdf.write_multicell_with_styles(left, instr_text) pdf.ln() pdf.option1(task, plotColor) pdf.ln() note = [ {'style':'I','text':'Note: '}, {'text':' The colored ball triangle shown above is illustrative and does not show your decoloring. '}, {'text': "Remember that you downloaded this file before the experiment. Therefore, its content cannot depend on how you completed the " + bonus_task} ] pdf.write_multicell_with_styles(left, note) pdf.output(inputfile, 'F') def protectPDF(inputfile, password, outputfile): pdfFile = open(inputfile, 'rb') # Create reader and writer object pdfReader = PyPDF2.PdfFileReader(pdfFile) pdfWriter = PyPDF2.PdfFileWriter() # Add all pages to writer (accepted answer results into blank pages) for pageNum in range(pdfReader.numPages): pdfWriter.addPage(pdfReader.getPage(pageNum)) # Encrypt with your password pdfWriter.encrypt(password) # Write it to an output file. (you can delete unencrypted version now) resultPdf = open(outputfile, 'wb') pdfWriter.write(resultPdf) resultPdf.close() # Call Function to Create PDFS def createBonusFilePDFs(data, password, id): finalData = [] for information in data: try: numRepetitions = information[2] # The number of identical tasks is saved in the third position for i in range(numRepetitions): toAdd = [information[0], information[1], i+1] finalData.append(toAdd) except: finalData.append(information) numFiles = len(finalData) fileNumbers = random.sample(range(100, 1000), numFiles) # Bonus file numbers bonusFiles = random.sample(finalData, numFiles) fileDict = dict(zip(fileNumbers, bonusFiles)) ## Generate Folder if it does not already exist folder = "_static/bonusFiles/" + str(id) + "/" folder_no_pwd = "_static/bonusFiles/" + str(id) + "/no_pwd/" Path(folder).mkdir(parents=True, exist_ok=True) Path(folder_no_pwd).mkdir(parents=True, exist_ok=True) #Path("/my/directory").mkdir(parents=True, exist_ok=True) for key in fileDict: title = 'BonusFile' + str(key) + ".pdf" inputfile = folder_no_pwd + title outputfile = folder + title fileData = fileDict[key] createPDF(fileData, title, inputfile) protectPDF(inputfile, password, outputfile) return fileDict #### TESTING ''' import treatments createBonusFilePDFs(treatments.basic, "Loewe50", 1000) createBonusFilePDFs(treatments.rand, "Loewe50", 1000) createBonusFilePDFs(treatments.path, "Loewe50", 1000) '''