Skip to content

DaveyJH/ci-portfolio-three

Repository files navigation

Computer Literate Investigator

A gentle reminder to all - to open links in a new tab, hold 'Ctrl' (or '⌘' on Apple devices) as you click!

Multiple Device Demo

Live Site

Computer Literate Investigator

Repository

https://github.com/daveyjh/ci-portfolio-three


Table of Contents


Objective

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


Brief

Computer Literate Investigator

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

UX − User Experience Design

User Requirements

Some example user stories which will affect the design

First Time User

"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"

Returning User

"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"

Interested Party

"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"


Initial Concept

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.

Wireframes

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.

Desktop

Desktop Wireframe

Mobile

Mobile Wireframe


Colour Scheme

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.


Typography

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.


Imagery

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.


Logic

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.

Initial Flow

Flow Chart


Python Logic

Flow Chart


Features

Existing Features

UX

"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"

  • The program has a score board feature. This can be accessed by users through the use of a keyword.

    Score Board


"As someone who hasn't used a CLI before, I would like to know my inputs are valid"

  • All user inputs are validated and errors allow repeat opportunities to input a valid selection.

    Invalid Input


"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()

Keywords

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. 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.
  6. 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.
  7. ???

    • 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!' ༼ ◕_◕ ༽つ

Features Left to Implement

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

Data Model

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.
Tokens data
Scores data Sheets ranges

Technologies Used

Python Packages

  • 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

Other Tech

  • 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.

VSCode Extensions

Links to the VSCode marketplace for each extension used throughout this project:


Testing

Python Testing

Manual Python Testing

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.

Manual Testing Documentation

Documentation can be view here

PEP8 Testing

The Python files have all been run through PEP8 online. The results are displayed here. One warning has been reported multiple times:

PEP* Warning

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.

Binary operator style explanation

Other Python Testing

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


W3C Validator

I used the W3C validators to test the HTML and CSS. No errors were reported.

HTML

HTML Results

CSS

CSS Results


JSHint

I used the online JSHint linter to check the JavaScript within index.html.

JSHint result

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

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.

Lighthouse results
Lighthouse suggestions


Bugs

Current

  • 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.


  • Not all browsers allow full size symbols.
    Half symbols

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.


  • I have found typing errors in two questions provided by the API.
    Double question mark
    Double question mark api
    Double be
    Double be api

Resolved

  1. Token() updates replaced entire Token instance with a string. Issue #3

    Commit - e3b8fad - I changed the function from assigning the current Token with initiate_new_token() to assign just a new Token.string. The function name was updated to reflect this change.

  2. 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.

  3. When changing the winner message to print in cyan it became mis-aligned. Winner message

    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 the rjust() and center() 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.


Development

The site was made using GitHub and VSCode

GitHub

GitHub Website

  • 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.

Use Template

Alternatively

  • Click GitHub Icon and select New from the panel on the left, next to Repositories

New Repository

  • Select the template you wish to use

Select Template

  • Give the repository a name and description and then click Create repository

Create Repo

The repository has now been created and is ready for editing


VSCode

VSCode Website

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.

Cloning

  • Open the command panel using your keyboard shortcut or View > Command Palette...

View>Command

  • With the command palette open, type clone and click Git: Clone and then GitHub IconClone from GitHub

Command Palette

  • Type the GitHub username followed by / and the repository you wish to work on

Repo Clone

  • 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

Editing

  • The explorer tab enables viewing of the files within the repository

Explorer

  • Open files from the explorer tab in the editor window and perform changes as necessary

Editor

  • 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

      Source Control

      • Click the + sign next to files you wish to add to staged changes

      SC Add

      • Type a commit message and click the tick icon to commit

      SC Commit

      • When ready to push your repository back to GitHub click the push/pull icon in the bar at the bottom of the application

      SC Push

      • 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

      Terminal All

      • Type git add fileNameHere.extension assets/anotherFileHere.extension and press Enter to add specific files, remembering to include sub-directories where necessary

      Terminal Add

      • Type git commit -m "meaningful message here" to commit your staged files with the typed commit message

      Terminal Commit

      • Type git push to push your repository to the remote repository held at GitHub

      Terminal Push

      • 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

Working With Python

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.

Venv

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.
    Venv active

This allows local installation of packages within the virtual environment and can help to prevent errors with global installs.

Packages

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.

Debugging

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.
    Breakpoint selected
  • Select 'Debug Python File'.
    Run in debug mode
  • File will run until a breakpoint is reached. It will pause and highlight the selected line before it is carried out.
    Debug paused
  • Step through each line individually or skip through functions as necessary.
    Debug step
  • View variables and data as it is being created or manipulated.
    Debug variables
  • Press play to continue to the next breakpoint or stop to end the file.

Google Sheets

This application uses Google Sheets to store data.

Creating Sheets

  • Navigate to Google Sheets.

  • Create a Blank sheet.
    Naming google sheet

  • Edit the sheet name.
    Google sheets name

  • The name used must match the name called in the open() method.

    `GSPREAD_CLIENT.open('example')`
  • Input data if required:

    • Google Sheets data works differently to most python objects. The 'list' of columns and rows starts at an index of 1.
      Google sheets tokens
      Google sheets scores
  • Assign 'Named ranges' if necessary:

    • Either highlight the range to be named, right click and select 'Define named range' from 'View more cell actions'.
      Google sheets right click naming ranges

    • OR Select 'Data' from the toolbar and click 'Named ranges'.
      Google sheets data named ranges

    • Named ranges can be viewed via the second option and can be edited if needed.
      Google sheets named ranges

    • 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.

API Credentials

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.
    Cloud select a project
  • Click 'NEW PROJECT'.
    Cloud new project
  • Give the project a name.
    Cloud project name
  • Click 'CREATE'.
    Cloud create
  • From the project's dashboard, select 'APIs and services' and then 'Library'.
    Cloud library menu
  • Search for, and enable, Google Drive API.
    Cloud Google Drive API
    Cloud enable
  • Click 'CREATE CREDENTIALS'.
    Cloud create credentials
  • Select 'Google Drive API' from the drop down list.
    Cloud API selection
  • Select 'Application data' from the first set of radio buttons.
    Cloud accessing app data
  • Select 'No, I', not using them' from the second set of radio buttons.
    Cloud not using cloud functions
  • Click 'DONE' and then enter a name and description for the service account details.
    Cloud service account details
  • Select a role of 'Editor' from the options available.
    Cloud editor
  • Click 'DONE' to create the service account.
  • Click on the service account on the credentials page.
    Cloud edit service account
  • Select 'KEYS' from the menu bar.
    Cloud keys
  • Select 'Create new key' from the 'ADD KEY' menu.
    Cloud create key
  • Select 'JSON' and click 'CREATE'.
    Cloud JSON option
  • 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.

Deployment

Heroku

  • Navigate to your heroku dashboard
  • Click "New" and select "Create new app".
    New heroku
  • Input a meaningful name for your app and choose the region best suited to your location.
    Create new app
  • Select "Settings" from the tabs.
    Settings tab
    • Click "Reveal Config Vars".
      Config vars button
    • Input PORT and 8000 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.
      Config vars values
    • Click "Add buildpack".
      Add buildpack
    • Add "nodejs" and "python" from the list or search if necessary, remember to click save.
      Select buildpacks
    • Python must be the first buildpack. They can be dragged into the correct position if needed.
      Buildpacks added
  • Select "Deploy" from the tabs.
    Settings tab
    • Select "GitHub - Connect to GitHub" from deployment methods.
      Select GitHub
    • Click "Connect to GitHub" in the created section.
      Connect to GitHub
    • Search for the GitHub repository by name.
      Heroku repo search
    • Click to connect to the relevant repo.
      Heroku connect to repo
    • Either click Enable Automatic Deploys for automatic deploys or Deploy Branch to deploy manually. Manually deployed branches will need re-deploying each time the repo is updated.
      Heroku deploy branch
    • Click View to view the deployed site.
      Heroku view
  • The live site can also be accessed from your repo in GitHub from the environments section of the repo.
    • Click the link to view deployments history.
      GitHub environments
    • Click View deployment. This page also shows all the deployment history.
      GitHub view deployment

The site is now live and operational


Credits

Content

  • 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

Media

Acknowledgements

  • 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. Nerd Life


About

Code Institute - Third Portfolio Project - Python

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published