Hello everybody, what's up? Every pleasure to meet you and write, together, some goods scripts, which can be help to solve some needs. Today, script we'll write will be some fun. Indeed, we'll realize a quiz. This quiz is little bit particular. I explain myself. Firstly, i want precise you that if you're superheroes fan, you'll love this script!
What will we do in this script? That is the question... π€
At Scripting Day, we like explicit things. So we need to define how the process of this quiz. Good! Let's go.
- We choose an heroes team (Marvel, DC comics or Hyper heroes)
- Some questions which refers to team chosen will be asked. We'll must answer to it
- At end, we get a score
- Then, a random book will be create and store in a folder. Book content will be:
- cover page (an heroe picture, who belongs to our heroes choice team)
- our name and answers, with quiz correction
- heroe story (who is on cover page)
- two or three heroes pictures who belongs to our heroe team choice
Obviously, each script we code need some prerequisites! So, let's list them.
Prerequisites
To code this script, we must have some knowledge such as:
- list and dictionary use
- files path handling (here, we'll use pathlib module, but you're free to use os module)
- csv module use (for creating and reading csv file)
- pdf file handling (we must install PyPDF2 and reportlab)
Here are some documentation for prerequisites:
- list
- dictionnary
- Read and write file
- csv module
- manage pdf file
Ready? Good, let's code our app now!!!
Firstly, create a folder called heroes_stories. All our script, files and folders will be inside it.
alpha@alpha:~$ mkdir heroes_stories && cd heroes_stories
Heroes list
For our quiz, we will define three teams of heroes. As a result, we will create three lists (each list for a hero team). Our heroes team are:
- marvel team
- Hyper team
- Dc Comics team
Each category will store the images of its heroes (as a pdf file). Let's create a folder containing these images (one folder for each team).
alpha@alpha:~/heroes_stories$ mkdir Heroes && cd Heroes
alpha@alpha:~/heroes_stories/Heroes$ mkdir dc_comic hyper marvel
Inside theses folders, put correct heroes pictures.
You can download heroes pictures here.
Now we've our heroes pictures, we need to code functions which we'll use to interact with its files (heroes pictures) in our application. We'll code into a file called heroes_list.py (create it).
alpha@alpha:~/heroes_stories$ touch heroes_list.py
Inside it, firstly, import pathlib and randint, then let's precise heroes files path.
import pathlib
from random import randint
# Heroes path
the_path = pathlib.Path.cwd() / 'Heroes'
# Specific heroes path
dc_heroes_path = the_path / 'dc_comic' # Folder where DC Comics heroes are
marvel_heroes_path = the_path / 'marvel' # Folder where Marvel heroes are
hyper_heroes_path = the_path / 'hyper' # Folder where hyper heroes are
To permit user to choose a super heroe, he must see their name! So it's obvious that we must display them to user. So how can we do it? 1rst thing we know is folders where they stored. So we need to find a way to list them and display them in order to permit user to choose one of them. We can just write their name! Yes, but if later, we want to add other heroes in folders, it'll be fastidious to add manually their names. So we must need to write a generic code which be able to display automatically names of super heroes, even if we add other names later. How then get the list of superheroes that are in folders and display them to the user? One way will be to display each file within the hero folders to get the name of the hero, while taking care to remove the file extension.
dc_heroes_list = []
marvel_heroes_list = []
hyper_heroes_list = []
# Let's define a function which take a path and list in which fill out
# heroes name
def fill_out_heroes_name(path, the_list):
""" Take a path.
In this path, get all files which can be found.
Next, for each file, get only the name without extension, and fill out
the list which passed in arguments with these names.
"""
# 1rst method
for the in path.rglob('*'):
the_name = the.stem # get the name of file without it's extension
the_list.append(the_name) # fill out the list
'''Another method: using os module (2nd method)
As we know that all files have same extension (.pdf), we could procceded
by use listdir method (os module) firstly and then, remove the extension
by removing 4 last character of each file name.
the_files = os.listdir(path) # get all files which can be found
for names in the_files:
the_name = names[:-4] # get the name of file without it's extension
the_list.append(the_name)
'''
return the_list
def fill_on_number(team_number):
"""Get team number and fill out correct list """
#NOTE: team number based on main scenario in heroes.py
if team_number == 1:
heroes_team = fill_out_heroes_name(dc_heroes_path, dc_heroes_list)
elif team_number == 2:
heroes_team = fill_out_heroes_name(hyper_heroes_path, hyper_heroes_list)
else:
heroes_team = fill_out_heroes_name(marvel_heroes_path, marvel_heroes_list)
return heroes_team
If you prefer os module instead of pathlib, you can use 2nd method and comment the 1rst. In addition, we don't create heroes.py file yet. We'll do it in next part.
Our first function (fill_out_heroes_name) take as arguments, the heroes folder path and heroes list in which heroes names must be added. Then, for each heroes pictures which is in folder path specified, it add the name (without extension) in list. In our application, we'll ask user to choose team he wants. Then, according to team number he'll chosen, function will execute 1rst function and save the result in variable called heroes_team, then return this variable.
For bonus pictures, it would cool to create a function which choose randomly two or three heroes pictures which will be add to generated book, isn't it? If you're agree with me, let's code it!
def choose_bonus_picture(heroes_list):
""" Get a list a return two or three heroe in this list """
# choose if we want get two or three heroes pictures as bonus
bonus_heroes_number = randint(2, 3)
heroes = []
for x in range(0, bonus_heroes_number):
heroes_list_length = len(heroes_list)
the_heroe_name = heroes_list[randint(0, heroes_list_length-1)]
while the_heroe_name in heroes:
the_heroe_name = heroes_list[randint(0, heroes_list_length-1)]
heroes.append(the_heroe_name)
return heroes
We created a function for bonus picture, but what's about cover picture!
def choose_cover_page(heroes_list):
"""Choose in a list one heroe for cover page"""
choosen_num = randint(0, len(heroes_list)-1)
return heroes_list[choosen_num]
We have finished the heroes_list.py file script. Now, what is the next task? Remember, in our application, we want that after answering questions, a book is generated for the user. It is now time to code the script that will do it! π π
The generated book
Here, we'll write scripts which permit us to create book for player. As remember, book will contains:
- Cover page made with an heroe (choosen randomly) from team choosen by player
- Player name and his score
- Biography of heroe which is on cover page
- Two or three heroes pictures as bonus
Let's start by import.
import pathlib
from PyPDF2 import PdfFileReader, PdfFileWriter
from reportlab.pdfgen import canvas
import heroes_list
NB: you'll need to install PyPDF2 and reportlab
alpha@alpha:~/heroes_stories$ pip3 install reportlab alpha@alpha:~/heroes_stories$ pip3 install PyPDF2
Generated books will be store in a folder called Edited_books (so, create it). Create another folder called trash_pdf. Now, let's create function which will generate book.
To understand this function, i recommend you to be familiar to with files and path handling.
Instead comment each code in this function directly here, i added comments directly in function.
def conceive_book(player_name, heroe_team, cover_heroe, player_score,
quiz_summary, bonus_pictures):
"""Use arguments to create a pdf book"""
the_heroes_path = pathlib.Path.cwd() / f'{heroe_team}'
bonus_pictures_names = [] # use list to collect bonus pictures
# define generated book name (with its extension)
output_file_name = pathlib.Path.cwd() / 'Edited_books' / f'quiz result of {player_name}.pdf'
output_file = open(output_file_name, 'wb')
output_pdf = PdfFileWriter()
# Introduction text with player name
intro_text = f'Mega heroes quizz with {player_name}'
# The cover page
cover_page_name = the_heroes_path / f'{cover_heroe}'
cover_page = PdfFileReader(open(cover_page_name, 'rb'))
# store player score into a variable
display_score = f'Score: {player_score}/20 | {player_score*100 / 20}%'
# Create book
output_pdf.addPage(cover_page.getPage(0)) # add cover page
''' For add some pages, i'll need to create them and then,
add them to final pdf file. These files will be at "trash_pdf" folder.
'''
# let's create a pdf page which will store intro text and player score
trash_path = pathlib.Path.cwd() / 'trash_pdf'
intro_path = trash_path / 'intro.pdf'
intro_pdf = canvas.Canvas(f'{intro_path}')
intro_pdf.setFont('Helvetica', 28)
intro_pdf.drawString(50, 500, f'{intro_text}')
intro_pdf.setFont('Helvetica', 18)
intro_pdf.drawString(200, 450, f'{display_score}')
intro_pdf.save()
intro_file = PdfFileReader(open(intro_path, 'rb'))
output_pdf.addPage(intro_file.getPage(0))
# add quiz summary
quiz_summary_path = trash_path / 'quiz_summary.pdf'
quiz_summary_pdf = canvas.Canvas(f'{quiz_summary_path}')
quiz_summary_pdf.setFont('Helvetica', 28) # set title font
quiz_summary_pdf.drawString(180, 700, 'Quiz summary') # write title
quiz_summary_pdf.setFont('Helvetica', 11) # set font for other lines
line_height_level = 600
i = 1
for key_value, info_value in quiz_summary.items():
quiz_summary_pdf.drawString(10, line_height_level, f'{key_value} {info_value}')
if i % 2 == 0:
line_height_level -= 50
else:
line_height_level -= 20
i += 1
quiz_summary_pdf.save()
quiz_summary_file = PdfFileReader(open(quiz_summary_path, 'rb'))
output_pdf.addPage(quiz_summary_file.getPage(0))
# add bonus pictures
for picture in bonus_pictures:
picture_file_name = the_heroes_path / f'{picture}.pdf'
picture_file = PdfFileReader(open(picture_file_name, 'rb'))
output_pdf.addPage(picture_file.getPage(0))
output_pdf.write(output_file) # write all output_pdf content in output_file
output_file.close()
Good done!!! We finished this first part !!! In the next part, we'll add questions, a scenario and other fun things. So stay tuned and I wish you a nice Sunday!!!