A gentle reminder to all - to open links in a new tab, hold 'Ctrl' (or '⌘' on Apple devices) as you click!
Computer Literate Investigator
https://github.com/daveyjh/ci-portfolio-three
- Computer Literate Investigator
Design an interactive quiz that uses an existing API for questions and answers. The project should run in a CLI, deployed via Heroku, using Python.
The needs within this project are not genuine and are made purely for the purpose of completing my Code Institute project
The goal of this site is to provide an interactive quiz with increasing difficulty levels. The final product should:
- be programmatically error free
- be written using Python
- have a varied question base to allow replayability
- handle all user input errors gracefully and appropriately
- give clear instructions regarding use and valid inputs
Some example user stories which will affect the design
"As a programmer, I would like to test my knowledge"
"As a quiz fanatic, I would like to know how I compare with other users"
"As someone who hasn't used a CLI before, I would like to know my inputs are valid"
"As a returning user, I would like to see a list of high-scores"
"I would like to know if my scores are in the high-scores list"
"If I return to play again, I would like to play different questions"
"As someone interested in how the application has been made, I am interested to see how user inputs have been validated and errors have been handled"
I intend to make a quiz application based around the popular television quiz show 'Who Wants To Be A Millionaire?'. I anticipate using a pre-populated API for the questions and answers, using a 'level of difficulty' selection built in to the API. I also intend to have a couple of 'life-line' options available to the user. Finally, I would like to implement a high-score spreadsheet maintained via Google Sheets.
Due to the nature of this project the wireframes are very basic. There is only one page and the design does not change across any devices, only a change in content.
The colour scheme for this project relies heavily on the colours available
through the colorama
package within Python. The package has allowed a few
colours to be applied to text within the terminal environment. The colours
outside the terminal are designed based around a classic CRT style monitor.
Contrast checks have been done to ensure the 'Run Program' button and text
present are of a high enough contrast to be easily read.
VT323 has been chosen from Google Fonts for the header, footer and button. The font is styled much like a classic terminal font and is perfect for this application.
The background image is a modified image from pexels.com and has been used as it reminded me of the introductory lighting that was used on the 'Who Wants To Be A Millionaire' television show. The colours also compliment the rest of the design.
I spent some time planning the logic behind the application to ensure I had a general idea of how it should be approached. I created flowcharts to allow me to follow the logic through the application as it developed. The charts were generated using Draw.io Integration and are shown below. As can be expected, the flow and features changed over the course of the project and so the charts do not accurately reflect all aspects of the end product.
"As a programmer, I would like to test my knowledge"
- The quiz uses an API that has a 'Science: Computers' category. This ensures the questions are related to code and computing in general.
"As a quiz fanatic, I would like to know how I compare with other users"
"As a returning user, I would like to see a list of high-scores"
"I would like to know if my scores are in the high-scores list"
"As someone who hasn't used a CLI before, I would like to know my inputs are valid"
"If I return to play again, I would like to play different questions"
- The API used has a token service that prevents repeat questions. The token only lasts 6 hours and the question quantity is fairly limited. Without adding some additional, verbose code, using and storing these tokens is the most effective way of trying to prevent repetition for users.
"As someone interested...how user inputs have been validated and errors have been handled"
-
The practices used within the program validate data when retrieving it from external sources. The overall design ensures a positive user experience and handles errors in an appropriate manner.
try: if response.status_code != 200: raise TypeError("API response missing") if "response_code" not in data: raise ValueError("API structure corrupt") except (TypeError, ValueError) as e: red_print(f"Critical Error: {e}") red_print("Program will now terminate!") exit()
-
Even The Odds
- This allows users to remove 2 incorrect answers
- If a user inputs a keyword, they will be presented with the question and only 2 answers, one of which will be correct. This will only be allowed once during each play.
-
Call A Coder
- This allows users to receive some advice from an ersatz friend
- If a user requires assistance on a question, they may input a keyword that generates a simulated response from another coder. The response received may not be correct. The chance of the response being correct is scaled depending on the current question number.
-
Request A Review
- This allows users to pose the current question to a pseudo panel of spectators
- If a user is struggling with an answer, they may request assistance from a spurious audience. The responses received may not be correct and are scaled depending on the current question number.
-
Help
- This allows users to read through the rules and keyword meanings during the quiz
- This will prevent user frustration due to forgetting any keyword meanings.
-
Take
- This allows users to leave the quiz with their current score
- By providing this feature, if users are unsure of an answer, they may stop the quiz in the hope of having their score entered on the score board.
-
Scores
- This allows users to view the score board at any time
- This feature enables users to check where they are in relation to the high scores before deciding whether to attempt difficult questions. It also adds a nice competitive element to encourage returning visits.
-
???
- There is a secret keyword that has a secret function
- This feature is just here for fun...remember, the cake is a lie!
- 'Hi Ron!' ༼ ◕_◕ ༽つ
At present, I am happy with the features in the program. Possible additions could include:
- a category option - for users not interested in computers
- personal tokens - to further reduce the likelihood of repeated questions
- a larger scores database - over time, the top scores may be difficult for some users to reach. A larger database would allow for recognition of the position achieved if it is not within the top ten
A Google Sheet was used to store scores and token strings.
The sheets consists of two worksheets, 'tokens' and 'scores', for clarity.
The scores cells are identified using two ranges, one for users and one for
the score values. This allowed me to experiment with some extra functions
available through the gspread
package.
- requests: enables data retrieval from APIs
- gspread: allows communication wit Google Sheets
- colorama: allows terminal text to be printed in different colours/styles
- random
- shuffle: used to generate random ordering
- randrange: returns a random integer within a given range
- html
- unescape: converts HTML entities to printable characters
- time
- sleep: stalls the program for a defined time
- google.oauth2.service_account
- Credentials: used to validate credentials and grant access to google service accounts
- better_profanity
- profanity: simple profanity checker
- py-getch
- pause: used to provide a 'Press any key to continue...' function
- Instant Eyedropper
- A quick and simple application to obtain hex values from any colour on my display. I downloaded this while playing around with my laptop layout/display settings. I have the app set to run on startup and remain minimized in my system tray. This allows quick access and if I click the colour, it automatically copies the value to my clipboard.
- WebAIM Contrast Checker
- A basic contrast checking service for conformity to the Web Content Accessibility Guidelines. The service allows input of a foreground and background colour and displays the resulting contrast ratio, including a quick reference to meeting WCAG AA / AAA standards.
- Windows Snipping Tool
- A screenshot tool built in to Windows. It allows quick, partial screenshots to be taken that can be saved as image files.
- Balsamiq
- Balsamiq was used to create wireframes for the project.
- Adobe Photoshop
- The background image was modified and converted using this image editing software
- Font Awesome
- The project uses icons from Font Awesome version 5.
- Google Fonts
- The fonts used in the website are imported from Google Fonts.
- Multi Device Mockup Generator
- The image at the top of this document was created using a free service provided by TechSini.com
- W3C Markup Validation Service
- A service to check the HTML and CSS files for errors. During development, I copied the entire text from the files and ran them through the direct input method. Upon completion, I ran the deployed site through the 'Validate by URI' method with results here.
- PEP8 online
- An online Python code validation service.
- Visual Studio Code
- A free, streamlined code editor. The extensions available have allowed me to customize my workspace and become more efficient.
Links to the VSCode marketplace for each extension used throughout this project:
- Python
- Better Comments
- Bracket Pair Colorizer 2
- GitHub Pull Request and Issue Provider
- Highlight Matching Tag
- Markdown All in One
- markdownlint
- Preview on Web Server
- Colored Regions
- Reflow Markdown
- Pylance
- Draw.io
- Code Spell Checker
The specification within the project requires manual testing. I have performed multiple tests on the deployed site and during the development stage to ensure data is handled correctly and all functions are carrying out their intended actions.
Documentation can be view here
The Python files have all been run through PEP8 online. The results are displayed here. One warning has been reported multiple times:
I have chosen to leave the code with the warnings in place. Having consulted the PEP8 Style Guide, I have found the latest advice is to write code as I have done so. It results in the code being more reader-friendly.
Two Python linters were used during the creation of this project.
They assisted in keeping the code well structured throughout. There are some warnings and suggestions highlighted by these linters that will remain in place. The explanation of this can be found here
I used the W3C validators to test the HTML and CSS. No errors were reported.
I used the online JSHint linter to check the JavaScript within index.html.
The warnings and undefined variables are related to the creation of the terminal. As this code is not my own, and they are not significant errors, I have left them as they are.
Lighthouse testing has been performed on desktop only as the site requires a minimum screen size of 750 × 750 pixels. The results are satisfactory and the suggested modifications are beyond my control due to the nature of the project.
- It is possible for questions to repeat during the quiz if tokens expire.
To resolve this issue, I could re-write the program to retrieve all questions simultaneously and store them in lists of dict objects. I would then need to manipulate the lists by removing used questions as the quiz progresses. My intention has been to show good working practices with data retrieval from an API, and data input to a different API. I feel the current method achieves this goal in a more satisfying way.
- If a user leaves the page idle for an extended period of time, the program appears to stop allowing input.
This appears to be a bug within the set up of the terminal and is beyond the scope of the project.
It was noted during testing on Mozilla Firefox that the special symbols do not display fully. I suspect this is due to limitations of the terminal and do not feel it detracts significantly from the user experience.
- There is a question that asks about Moore's Law, it appears to have the wrong answer assigned in the API database.
I have been unable to find a way to report an error with the questions.
-
Token()
updates replaced entire Token instance with a string. Issue #3Commit - e3b8fad - I changed the function from assigning the current
Token
withinitiate_new_token()
to assign just a newToken.string
. The function name was updated to reflect this change. -
If a user name appeared twice in the scores list, only the lowest scores was displayed.
Commit - 2d5dab6 - The bug was caused by using a dict object. As keys must be unique in dictionaries, duplicated user names were causing the original instance of the user name to be updated. I have used lists and the
enumerate
function to resolve the issue. -
When changing the winner message to print in cyan it became mis-aligned.
Commit - 6a1d4b5 - The
cyan_print
function only permits one string to be passed in. I had overlooked this when writing the winner's message. The message originally used therjust()
andcenter()
methods. I have removed those methods and (after a couple of mis-calculated attempts) resolved the issue by writing the message as a concatenated string.
The site was made using GitHub and VSCode
- Sign in to GitHub.
- I used a template created by Code Institute that can be accessed here and is available for public use via the Use this template button.
Alternatively
- Select the template you wish to use
- Give the repository a name and description and then click Create repository
The repository has now been created and is ready for editing
For general information on using GitHub with VSCode see their documentation
here.
This section assumes you have successfully linked your GitHub account to the
application.
- Open the command panel using your keyboard shortcut or View > Command Palette...
- Type the GitHub username followed by / and the repository you wish to work on
- Click the repository from the drop-down list and save it in a local directory of your choosing
The repository is now ready for development
- The explorer tab enables viewing of the files within the repository
- Open files from the explorer tab in the editor window and perform changes as necessary
- Save files as appropriate, add, commit and push them. There are multiple ways
to do this
-
VSCode Source Control
- Select the Source Control tab that looks like a repository branch
- Click the + sign next to files you wish to add to staged changes
- Type a commit message and click the tick icon to commit
- When ready to push your repository back to GitHub click the push/pull icon in the bar at the bottom of the application
- I have many keyboard shortcuts set to speed up this process, they are configurable within the VSCode settings
-
Terminal
These steps assume you are in the root directory of your repository and typing in the terminal- Type
git add .
and press Enter to add all modified or untracked file
- Type
git add fileNameHere.extension assets/anotherFileHere.extension
and press Enter to add specific files, remembering to include sub-directories where necessary
- Type
git commit -m "meaningful message here"
to commit your staged files with the typed commit message
- Type
git push
to push your repository to the remote repository held at GitHub
- There are many other stages to editing, such as branches, git stash, reverting commit messages and others. For more information, refer to the git documentation
- Type
-
This section assumes you have python installed on your machine and added to PATH. I am unfamiliar with macOS so these steps may be different.
A virtual environment is advised when working with Python. I chose to use
venv
.
- With the terminal in the route directory of my project I used
python -m venv .venv
to create a virtual environment in the.venv
directory. - I the used
source .venv/scripts/activate
to enable the virtual environment. - The
(.venv)
displayed above the current directory show the venv is active.
This allows local installation of packages within the virtual environment and can help to prevent errors with global installs.
To install all packages within this repo you can run pip3 install -r requirements.txt
in the terminal. This installs all packages from the text
file. The text file was created using pip3 freeze > requirements.txt
.
To install individual packages you need to review the appropriate
documentation for the install command. All packages I have found and used were
installed using something similar to pip3 install py-getch
. The documentation
files are linked above under the python packages heading.
To run a file from the terminal I type python -m file_name_here
, where
'file_name_here' is the name of the file I wish to run.
It is also possible to run small snippets of python code by typing python
and
pressing enter. This allows me to create variables and run functions without
saving any data. Using this live python terminal, you can also import files
you have already created by typing import file_name_here
.
VSCode has a built in debugger. I set breakpoints at points in my files to enable me a step by step view of how my variables were being manipulated. This allowed for quick fault finding and ensuring data is being handled as expected.
- Select breakpoints by clicking to the left of the line number.
- Select 'Debug Python File'.
- File will run until a breakpoint is reached. It will pause and highlight the
selected line before it is carried out.
- Step through each line individually or skip through functions as necessary.
- View variables and data as it is being created or manipulated.
- Press play to continue to the next breakpoint or stop to end the file.
This application uses Google Sheets to store data.
-
Navigate to Google Sheets.
-
The name used must match the name called in the
open()
method.`GSPREAD_CLIENT.open('example')`
-
Input data if required:
-
Assign 'Named ranges' if necessary:
-
Either highlight the range to be named, right click and select 'Define named range' from 'View more cell actions'.
-
Named ranges can be viewed via the second option and can be edited if needed.
-
Named ranges can be accessed using the
worksheet.range('range_name')
method.import gspread SHEET = GSPREAD_CLIENT.open("ci_p3_quiz") SCORES_SHEET = SHEET.worksheet("scores") current_highscore_values_cells = SCORES_SHEET.range("values")
-
-
The
gspread
package allows many operations including retrieving, updating and adding new data.
To allow access from the project to Google Sheets, credentials must be generated and provided.
- Navigate to the Google Cloud Platform
- Click 'Select a project', this may have an existing project name in place.
- Click 'NEW PROJECT'.
- Give the project a name.
- Click 'CREATE'.
- From the project's dashboard, select 'APIs and services' and then
'Library'.
- Search for, and enable, Google Drive API.
- Click 'CREATE CREDENTIALS'.
- Select 'Google Drive API' from the drop down list.
- Select 'Application data' from the first set of radio buttons.
- Select 'No, I', not using them' from the second set of radio buttons.
- Click 'DONE' and then enter a name and description for the service account
details.
- Select a role of 'Editor' from the options available.
- Click 'DONE' to create the service account.
- Click on the service account on the credentials page.
- Select 'KEYS' from the menu bar.
- Select 'Create new key' from the 'ADD KEY' menu.
- Select 'JSON' and click 'CREATE'.
- The JSON file will be downloaded to your computer. Copy the contents into
a
creds.json
file within the repository. Make sure to add this file to the.gitignore
file.
- Navigate to your heroku dashboard
- Click "New" and select "Create new app".
- Input a meaningful name for your app and choose the region best suited to
your location.
- Select "Settings" from the tabs.
- Click "Reveal Config Vars".
- Input
PORT
and8000
as one config var and click add. - Input
CREDS
and the content of your Google Sheet API creds file as another config var and click add.
- Click "Add buildpack".
- Add "nodejs" and "python" from the list or search if necessary, remember to
click save.
- Python must be the first buildpack. They can be dragged into the correct
position if needed.
- Click "Reveal Config Vars".
- Select "Deploy" from the tabs.
- Select "GitHub - Connect to GitHub" from deployment methods.
- Click "Connect to GitHub" in the created section.
- Search for the GitHub repository by name.
- Click to connect to the relevant repo.
- Either click
Enable Automatic Deploys
for automatic deploys orDeploy Branch
to deploy manually. Manually deployed branches will need re-deploying each time the repo is updated.
- Click
View
to view the deployed site.
- Select "GitHub - Connect to GitHub" from deployment methods.
- The live site can also be accessed from your repo in GitHub from the environments section of the repo.
The site is now live and operational
- The question database and API functionality was obtained through opentdb.com
- The terminal function and template for the deployable application was provided by Code Institute, with special mention to Matt Rudge
- The background image was sourced from pexels.com and was provided by Wendy Wei
-
Thank you to Fiona Tracey. I reached out in the Code Institute Slack community with a minor issue. Fiona provided a wonderfully simple solution to prevent some unused variable warnings as detailed below:
string = "this is a string" # This string was from the KEYWORDS list line = "" for char in string: line += "=" # 'char' variable is unused # Above was my original code to create an underline of '='s for some titles # Below is a neater solution that led to a better approach to other code # within the repo line = "=" * len(KEYWORDS[index])
-
Thank you to David Bowers for saving me from having to trawl through previous Slack messages. Within minutes of asking, he provided a link to the exact information I was looking for, detailed below. He also has some really awesome work available to look through on his GitHub profile, well worth a look.
-
Thank you to Matt Boden for sharing his project. From there I was able to see the easiest way to style my own project to give a more pleasing UX. Matt has a fantastic approach to code, I highly recommend a review of his work.
-
A big thanks to Jim Morel and many more of the Code Institute slack community members. Jim was able to point me in the right direction regarding virtual environments on VSCode and has an eternally-positive attitude that really helps in many ways.
-
A final huge thank you to Abi Harrison and Emanuel Jose Felisberto Dos Santos Moreira Da Silva, what an amazing name! With a great attitude to continued development, encouragement along the way, and testing whenever it was needed - These two continue to make my developer journey thoroughly enjoyable.