#!/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 scipy.stats import skewnorm 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 def option2(bonusFileData): ceCounter = 0 peCounter = 0 op2_list = [] p_list = [] risk_list = [] for risk in bonusFileData: if risk[0] == "certaintyEquivalent": ceCounter +=1 risk_list.append(risk[2]) elif risk[0] == "probabilityEquivalent": peCounter +=1 for i in range(ceCounter): # Certainty Equivalents requiring Option 2 # Idea: Moment matching and truncation # Get risk characterstics (Ebert, 2015) tmpRisk = risk_list[i] x1 = tmpRisk[0][0] p = tmpRisk[0][1] x0 = tmpRisk[1][0] # Get moments of risk (Ebert, 2015) E = p * x1 + (1-p) * x0 V = (x1-x0)**2 * p * (1-p) S = (1-2*p)/ ((p * (1-p))**0.5) randomDraws = [] # Make five random draws, take average for j in range(100): r = skewnorm.rvs(S, loc=E, scale=V, size=1)[0] randomDraws.append(r) num = round(sum(randomDraws) / len(randomDraws),2) num = max(min(num, x1), x0) # Truncate op2_list.append(num) for i in range(peCounter): x = round(random.random(),2) p_list.append(x) #random.shuffle(op2_list) #random.shuffle(p_list) randDict = { 'certaintyEquivalent': op2_list, 'probabilityEquivalent': p_list, } return randDict # Call Function to Create PDFS def createBonusFilePDFs(data, option2, password, id): numFiles = len(data) # Desctrucutre Option2 op2_list = option2["certaintyEquivalent"] p_list = option2["probabilityEquivalent"] ceCounter = 0 peCounter = 0 finalData = [] for value in data: if value[0] == "certaintyEquivalent": value[3] = op2_list[ceCounter] ceCounter += 1 elif value[0] == "probabilityEquivalent": payoff1 = value[2][0][0] payoff2 = value[2][1][0] prob1 = p_list[peCounter] prob2 = round(1 - prob1,2) value[2] = [[payoff1, prob1], [payoff2, prob2] ] peCounter += 1 finalData.append(value) fileNumbers = random.sample(range(100, 1000), numFiles) 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] bonusFileContent(fileData, title, inputfile) protectPDF(inputfile, password, outputfile) return fileDict def rewriteBonusFile(envelope, data, id): ## 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) title = 'BonusFile' + str(envelope) + ".pdf" inputfile = folder_no_pwd + title bonusFileContent(data, title, inputfile) # Create PDFs def bonusFileContent(data, title, inputfile): class PDF(FPDF): def frame(self): self.rect(5.0, 5.0, 200.0,287.0) def borders_4(self): self.set_line_width(0.5) starty = self.get_y() # Note: Two columns, two rows # Top Row self.rect(left, starty, width , text_height) self.rect(left + width, starty, width , text_height) # Second Row self.rect(left, starty + text_height, width , option_height) self.rect(left + width, starty + text_height, width , option_height) def borders_2(self): starty = self.get_y() self.set_line_width(0.5) # Note: Two columns, two rows # Top Row #self.rect(left, starty, width , text_height) # Second Row self.rect(left, starty + text_height, width , option_height) def option1_header(self, bold_text): starty = self.get_y() self.set_xy(left,starty) self.set_font('Helvetica', 'B', 12) self.cell(w=width, h=text_height, align='C', txt=bold_text, border=0) self.ln() 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 option2_header(self, bold_text): starty = self.get_y() self.set_xy(left + width,starty) self.set_font('Helvetica', 'B', 12) self.cell(w=width, h=text_height, align='C', txt=bold_text, border=0) self.set_y(starty) # Reset y def option1_shell(self, img_L, img_R, payoff): img_width = (1/3) * width starty = self.get_y() + (1/10) * option_height self.set_xy( left + (1 * width / 9) ,starty ) self.image(img_L, link='', type='', w= img_width) self.set_xy( left + (5 * width / 9) ,starty) self.image(img_R, link='', type='', w= img_width) # destructure payoff payoff_1 = "£" + '%.2f' %payoff[0] payoff_2 = "£" + '%.2f' %payoff[1] self.set_font('Helvetica', '', text_height) starty = self.get_y() + (1/10) * text_height self.set_xy( left + (3 * width / 9) , starty) self.cell(w= img_width, h= 0.6* text_height, align='C', txt=payoff_1, border=1) starty = starty + 0.7 * text_height self.set_xy( left + (3 * width / 9) , starty) self.cell(w= img_width, h= 0.6* text_height, align='C', txt=payoff_2, border=1) def option1_cards(self, payoff, probability): card_width = width / 13 card_height = 10 # destructure payoff payoff_1 = "£" + '%.1f' %payoff[0] payoff_2 = "£" + '%.1f' %payoff[1] # destructure probability prob_1 = probability[0] prob_2 = probability[1] starty = self.get_y() + 0.5 * card_height startx = left + card_width/2 self.set_xy( startx ,starty) self.set_font('Helvetica', '', 8) uniquePay = list(set(payoff)) uniquePay.sort(reverse=True) # sorted # fill colors in RGB fillColors = [ [191, 214, 246], #blueish [255, 239, 215] #yellowish ] for i in range(100): if i > 0 and (i % 10) == 0: self.set_xy( startx ,self.get_y() + card_height + 1) if i < prob_1 * 100: txt = payoff_1 colInd = uniquePay.index(payoff[0]) else: txt = payoff_2 colInd = uniquePay.index(payoff[1]) coloring = fillColors[colInd] self.set_fill_color(coloring[0], coloring[1], coloring[2]) self.cell( w= card_width, h= card_height, align='C', txt=txt, border=1, fill=True) self.set_x( self.get_x() + card_width/5) def option2(self, num): text = "£" + '%.2f' %num starty = self.get_y() self.set_xy( left + width , starty) self.set_font('Helvetica', 'B', 40) self.cell(w=width, h=option_height, align='C', txt=text, border=0) #self.set_y( starty) 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(): #print(text_part['text']) 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 task = data[0] resolutionType = data[1] riskInfo = data[2] option2_data = data[3] if resolutionType == "shell": option_height = 60 elif resolutionType == "cards": option_height = 120 # Higher table for 100 cards payoffs = [] probabilites = [] for info in riskInfo: payoffs.append(info[0]) probabilites.append(info[1]) # Define Table properties width = pdf_w / 2 - left pdf.add_page() pdf.frame() pdf.titles(title) pdf.borders_4() # Do Option 2 first because Option 1 shifts y pdf.option2_header(bold_text="Option 2: Take amount") pdf.option1_header(bold_text="Option 1: Take the risk") if resolutionType == "shell": shell_L = "_static/img/trapezoid_L.png" shell_R = "_static/img/trapezoid_R.png" # Do Option 2 first because Option 1 shifts y pdf.option2(option2_data) pdf.option1_shell(shell_L, shell_R, payoffs) elif resolutionType == "cards": pdf.option2(option2_data) pdf.option1_cards(payoffs, probabilites) 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() def rewriteAllBonusFiles(bonusFileDict, password, id): ## 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 bonusFileDict: title = 'BonusFile' + str(key) + ".pdf" inputfile = folder_no_pwd + title outputfile = folder + title fileData = bonusFileDict[key] bonusFileContent(fileData, title, inputfile) protectPDF(inputfile, password, outputfile) ## For testing ''' testData= [ ["certaintyEquivalent", "shell", [[8.00, 0.50], [2.00, 0.50]], None], ["certaintyEquivalent", "cards", [[26,0.02],[4.60,0.98]], None], ["probabilityEquivalent", "cards", [[8.00, None], [2.00, None]], 5.00], ] output = createBonusFilePDFs(testData, option2(testData), "Loewe50", 1001) print(output) '''