Recent Question/Assignment
CSP1150/CSP5110 Programming Principles
Assignment 2: Individual programming project (Joke Bot)
Assignment Marks: Marked out of 30, (30% of unit)
Due Date: 30 May 2016, 9:00AM
Background Information
This assignment tests your understanding of and ability to apply the programming concepts we have covered throughout the unit. The concepts covered in the second half of the unit build upon the fundamentals covered in the first half of the unit.
Assignment Overview
You are required to design and implement two related programs:
• “admin.py”, a CLI program that allows the user to manage a collection of simple “setup and punchline” jokes which are stored in a text file. Develop this program before “jokebot.py”.
• “jokebot.py”, a GUI program that uses the data in the text file to display the jokes and allow the user to rate them. Develop this program after “admin.py”.
Starter files for both of these programs are provided along with this assignment brief, to help you get started and to facilitate an appropriate program structure. Please use the starter files.
Pseudocode
As emphasised by the case study of Module 5, it is important to take the time to properly design a solution before starting to write code. Hence, this assignment requires you to write and submit pseudocode of your program design for “admin.py”, but not “jokebot.py” (pseudocode is not very well suited to illustrating the design of an event-driven GUI program). Furthermore, while your tutors are happy to provide help and feedback on your assignment work throughout the semester, they will expect you to be able to show your pseudocode and explain the design of your code.
You will gain a lot more benefit from pseudocode if you actually attempt it before trying to code your program – even if you just start with a rough draft to establish the overall program structure, and then revise and refine it as you work on the code. This back and forth cycle of designing and coding is completely normal and expected, particularly when you are new to programming. The requirements detailed on the following pages should give you a good idea of the structure of the program, allowing you to make a start on designing your solution in pseudocode.
See Reading 3.3 for further information and tips regarding writing good pseudocode.
Write a separate section of pseudocode for each function you define in your program so that the pseudocode for the main part of your program is not cluttered with function definitions. Ensure that the pseudocode for each of your functions clearly describes the parameters that the function receives and what the function returns back to the program.
It may help to think of the pseudocode of your program as the content of a book, and the pseudocode of functions as its appendices: It should be possible to read and understand a book without necessarily reading the appendices, however they are there for further reference if needed.
Three functions are required in this assignment (detailed later in the assignment brief). The following pages describe the requirements of both programs in detail.
Requirements of “admin.py”
“admin.py” is a program with a Command-Line Interface (CLI) like that of the programs we have created throughout the first half of the unit. The entirety of this program can be implemented in under 175 lines of code – If your program exceeds this, ask your tutor for advice. Everything you need to know in order to develop this program is covered in the first 7 modules of the unit. This program should be developed before “jokebot.py”.
This program allows the user to manage the details of a collection of jokes which are stored in a text file named “data.txt”. Use the “json” module to write data to the text file in JSON format and to read the JSON data from the file back into Python. See Reading 7.1 for details regarding this. This is an example of the file’s content in JSON format (which is almost identical to Python):
[
{
-setup-: -What do you call a group of 8 hobbits?-,
-sumOfRatings-: 0,
-punchline-: -A hobbyte.-,
-numOfRatings-: 0
},
{
-setup-: -I once drank some food colouring...-,
-sumOfRatings-: 0,
-punchline-: -It made me feel like I had dyed a little inside.-, -numOfRatings-: 0
}
] JSON
This example file contains two items in a list. Each of those items is a dictionary consisting of 4 items which have keys of “setup”, “punchline”, “numOfRatings” and “sumOfRatings”. If this file was to be read into a Python variable named data, then “data[0]” would refer to the dictionary containing the first joke (about hobbits), and “data[0]['numOfRatings']” would refer to 0 (integer).
In the following information, numbered points describe a requirement of the program, and bullet points (in italics) are additional details, notes and hints regarding the requirement. Ask your tutor if you do not understand the requirements or would like further information. The requirements are:
1. The first thing the program should do is try to open “data.txt” in read mode, then load the data from the file into a variable named data and then close the file.
? The data in the file should be in JSON format, so you will need to use the “load()” function from the “json” module to read the data into your program. See the previous page for details of the data.
? If any exceptions occur (due to the file not existing, or it not containing valid JSON data), then simply set the data variable to be an empty list.
2. The program should then print a welcome message and enter an endless loop which starts by printing a list of options: “Choose [a]dd, [l]ist, [s]earch, [v]iew, [d]elete or [q]uit.” and then prompts the user to enter their choice.
Once a choice has been entered, use an “if/elif” to respond appropriately (detailed below).
3. If the user enters “a” (add), prompt them to enter the setup and punchline of a joke, and use them to create a new dictionary with the structure shown on the previous page. Append the dictionary to the data list, then write the list to the text file in JSON format to save the joke.
? Use your “inputSomething()” function (detailed below) when prompting for the setup and punchline, to ensure that the user is re-prompted until they enter something.
? The dictionary for the new joke should contain 4 keys – “setup” and “punchline” should contain what the user entered, and “numOfRatings” and “sumOfRatings” should be given values of 0.
? Once the joke has been added to the data list, call your “saveChanges()” function (detailed below) to write the changes to the text file.
4. If the user enters “l” (list), display a list of the jokes (just the setup) preceded by their index number in the data list, or a “No jokes saved” error message if there is nothing in the list.
? Use a “for” loop to iterate through the jokes in the data list.
? You can use the “enumerate()” function to make sure you have a variable containing the index number of each joke as you loop through them (see Lecture 3).
5. If the user enters “s” (search), prompt for a search term and then list the jokes whose setup or punchline contains the search term. Remember to include the index number next to each result.
? This is a good opportunity to reuse and tweak the code used to list all jokes – the loop body needs an “if” to only print jokes that contain the search term (use the “in” operator – see Lecture 3).
? Convert the search term, joke setup and punchline to lowercase to find matches regardless of case.
? Use your “inputSomething()” function (detailed below) when prompting for the search term, to ensure that the user is re-prompted until they enter something.
6. If the user enters “v” (view), prompt them for an index number and then print the corresponding joke’s setup and punchline, including details of the joke’s rating.
? If the joke’s “numOfRatings” key contains a 0, show a “Joke has not been rated” message. Otherwise, show how many times the joke has been rated and the average rating of the joke (rounded to 1 decimal place), e.g. “Rated 3 time(s). Average rating is 3.3/5.”
? Use your “inputInt()” function (detailed below) when prompting for an index number, to ensure that the user is re-prompted until they enter an integer.
? Display an “Invalid index number” message if the user enters an index number that doesn’t exist in the data list. Also consider showing a “No jokes saved” message and not allowing the user to specify an index number if the data list is empty.
7. If the user enters “d” (delete), prompt them for an index number and then remove the corresponding item from the data list, then display a “Joke deleted” message.
? Use your “inputInt()” function (detailed below) when prompting for an index number, to ensure that the user is re-prompted until they enter an integer.
? Display an “Invalid index number” message if the user enters an index number that doesn’t exist in the data list. Also consider showing a “No jokes saved” message and not allowing the user to specify an index number if the data list is empty.
? Once the joke has been deleted from data list, call your “saveChanges()” function (detailed below) to write the changes to the text file.
8. If the user enters “q” (quit), print “Goodbye!” and break out of the loop to end the program.
9. If the user enters anything else, print an “Invalid choice” message (the user will then be reprompted for a choice on the next iteration of the loop).
This concludes the core requirements of “admin.py”. The following pages detail the functions mentioned above, the additional requirements for CSP5110 students, optional additions and enhancements, and an annotated screenshot of the program.
Since jokes are rated in the GUI program (“jokebot.py”) the “ratings” aspect of the assignment will make more sense once you have read the rest of the assignment brief.
Remember that you are required to submit pseudocode for your design of “admin.py”.
Functions in “admin.py”
The requirements above mentioned three functions - “inputInt()”, “inputSomething()”, and “saveChanges()”. You must define and use these functions as part of “admin.py”.
1. The “inputInt()” function takes one parameter named prompt. The function should repeatedly re-prompt the user (using the prompt parameter) for input until they enter an integer. It should then return the value as an integer.
? See Workshop 4 for instructions regarding a similar function.
2. The “inputSomething()” function takes one parameter named prompt. The function repeatedly re-prompt the user (using the prompt parameter) for input until they enter a value which consists of at least one character once all whitespace has been stripped from the start and end of it. It should then return the value as a string.
? Use the “strip()” method on a string to remove whitespace from the start and end.
? Note that exception handling is of no use in this function.
3. The “saveChanges()” function takes one parameter named dataList (this will be the data list). The function should open “data.txt” in write mode, then write the dataList parameter to the file in JSON format and close the file. This function does not return anything.
? This is the only part of the program that should be writing to the file, and it always simply overwrites the entire content of the file with the entirety of the current data.
? See Reading 7.1 for an example of using the “json” module. You can specify an additional indent parameter in the “dump()” function to format the JSON data nicely in the file.
You may write/use additional functions if you feel they improve your program.
Additional “admin.py” Requirements for CSP5110 Students
If you are in CSP5110, the following additional requirements apply. If you are in CSP1150, you do not need to do implement these requirements (but you are encouraged to do so if you want). Ask your tutor if you do not understand any of the requirements or would like further information.
1. Add 1 to the index number of jokes whenever the list or search results are shown, so that the list begins at 1 instead of 0. Remember to subtract 1 from the user’s input when viewing or deleting jokes so that you reference the appropriate index of the data list.
2. As well as ensuring that the user enters an integer, the “inputInt()” function must also make sure that the integer is larger than 0 (i.e. a minimum of 1). Make sure that this requirement is mentioned in the error message that is displayed if an invalid value is entered.
Optional Additions and Enhancements for “admin.py”
The following are suggestions for optional additions and enhancements that you can implement to demonstrate deeper understanding of programming and deliver a product which is more “polished”. They are not required, but you are encouraged to implement them (and others) if you can.
? Always check if the data list is empty whenever a user tries to list, search, view or delete, and only allow the action to proceed if there is at least one item in the list.
? Add an additional menu option of “[t]op”, which works similarly to the “[l]ist” option except that it should only list jokes that have an average rating of 4 or more.
? Allow users to use the search, view and delete options more efficiently by allowing input of “s search term ”, “v index number ” and “d index number ”. For example, instead of needing to type “s” and then “hobbit”, the user could type “s hobbit”, and instead of needing to type “v” then “1”, the user could type “v 1”.
Annotated Screenshot of “admin.py”
To help illustrate the “admin.py” program, here is an annotated screenshot of it being used:
Requirements of “jokebot.py”
“jokebot.py” is a program with a Graphical User Interface (GUI), as covered in Module 9. Everything you need to know in order to develop this program is covered in the first 9 modules of the unit. This program should be developed after “admin.py”. The entirety of this program can be implemented in under 150 lines of code – If your program exceeds this, ask your tutor for advice.
This program uses the data from the “data.txt” file to show one joke at a time, allowing the user to rate the joke before showing the next one. Once all of the jokes have been shown, the program ends. To ensure compatibility and consistency, you are required to use the “tkinter” module for the GUI of “jokebot.py”. You will also need to use the “tkinter.messagebox” module and the
“json” module.
To help illustrate the “jokebox.py” program, here are some annotated screenshots of it being used:
(Your program may look slightly different, depending on which version of which operating system you use)
The setup of the joke is shown at the top, and the punchline is shown below it. Try to make them stand out, and look slightly different.
The number of ratings and average rating of the joke are shown here, with a form allowing the user to enter and submit a rating below it.
If the user has not entered a valid rating (1-5) when they press Submit, an error messagebox is shown.
Otherwise, a thankyou messagebox is shown and the next joke is loaded.
When the user rates the final joke from the self.data list, the messagebox should mention this and the program should then end.
See the content of Module 9 for examples of creating a class for your program’s GUI. A starter file has been provided to assist you. For conciseness, I have referred to attribute names without the
“self.” prefix in the following details.
Implement all of the following requirements, and ask your tutor if you do not understand any of the requirements or would like further information. The requirements of the program are:
The constructor (the “__init__” method) of your GUI class must implement the following:
1. Create the main window of the program and give it a title of “Joke Bot”.
? You may also wish to set other settings such as the minimum size of the window.
2. Try to open the “data.txt” file in read mode and load the JSON data from the file into an attribute named self.data, and then close the file. Also create an attribute named self.currentJoke and set it to 0.
? If any exceptions occur (due to the file not existing, or it not containing valid JSON data), show an error messagebox with a “Missing/Invalid file” message and use the “destroy()” method on the main window to end the program. Include a “return” statement in the exception handler after destroying the main window to halt the constructor so that the program ends cleanly.
? self.currentJoke will keep track of which joke in self.data the program is up to.
3. The constructor should then use Label, Entry, Button and Frame widgets from the “tkinter” module to implement the GUI depicted on the previous page.
? You will save time if you take time to design the GUI and determine exactly which widgets you will need and how to lay them out before you start writing the code.
? You are welcome change the layout of the GUI, as long as the functionality is implemented.
? See Reading 9.1 for information regarding various settings that can be applied to widgets to make them appear with the desired padding, colour, size, etc.
? The Button that allows users to submit the rating should call the “rateJoke” method (detailed below) when clicked.
4. Finally, the constructor should end by calling the “showJoke” method to place the first joke into the GUI, and then call “tkinter.mainloop()” to start the main loop.
That is all that the constructor requires. The following pages detail the methods mentioned above, the additional requirements for CSP5110 students and optional additions and enhancements.
You are not required to submit pseudocode for your design of “jokebot.py”, as pseudocode is not particularly well suited to illustrating the design of an event-driven GUI program.
Methods in the GUI class of “jokebot.py”
Your GUI class requires two methods to implement the functionality of the program - “showJoke” and “rateJoke”. Neither of them require any parameters other than “self”, which is passed to all methods in a class. As part of the GUI class of “jokebot.py”, you must write these methods.
1. The “showJoke” method is responsible for displaying a joke in the GUI. The method must first select a joke from self.data using the self.currentJoke attribute, and then configure the labels for the setup, punchline and rating information to display the setup, punchline and rating information of the selected joke.
? If the joke’s “numOfRatings” key contains a 0, show a “Joke has not been rated” message. Otherwise, show how many times the joke has been rated and the average rating of the joke (rounded to 1 decimal place), e.g. “Rated 3 time(s). Average rating is 3.3/5.”
? Once you’ve configured the labels to display the joke, set the focus to the rating Entry widget to make it convenient for the user – Use the “focus_set()” method of the Entry widget to do this.
2. The “rateJoke” method is responsible for validating and recording the rating that a user gives a joke. The method must first ensure that an integer between 1 and 5 has been entered into the rating Entry widget – If not, show an error messagebox and “return” to end the method.
If a valid rating has been entered, add one to the joke’s “numOfRatings” value, and add the rating to the joke’s “sumOfRatings” value in the self.data attribute. Then, open the “data.txt” file in write mode, write self.data to it in JSON format and close the file.
Finally, check the current joke is the last one (using self.currentJoke and self.data) and show the appropriate messagebox as per the screenshots above. If it is the final joke, end the program. Otherwise, add 1 to the self.currentJoke attribute, delete the content of the rating entry widget, and then call the “showJoke” method to display the next joke.
These two methods are all that are required to implement the functionality of the program, but you may write/use additional functions if you feel they improve your program.
Additional “jokebot.py” Requirements for CSP5110 Students
If you are in CSP5110, the following additional requirements apply. If you are in CSP1150, you do not need to do implement these requirements (but you are encouraged to do so if you want). Ask your tutor if you do not understand any of the requirements or would like further information.
1. The look of your GUI will be assessed more critically. Take some time to ensure that it is wellpresented: Use padding, make sure that long setups and punchlines are shown properly, use a different font/size/colour/style for the setup and punchline, etc.
Optional Additions and Enhancements for “jokebot.py”
The following are suggestions for optional additions and enhancements that you can implement to demonstrate deeper understanding of programming and deliver a product which is more “polished”. They are not required, but you are encouraged to implement them (and others) if you can.
? Try to use a different form of input for the ratings, such as radio buttons or a drop-down list.
? Instead of immediately showing the punchline when a joke is shown, show a “Reveal Punchline” button that, when clicked, will disappear and be replaced with the punchline. Alternatively, try adding a delay so that the punchline appears a few seconds after the rest of the joke is shown.
? Try to create the “CORAL Edition” of the jokebot program – This will be explained in a lecture towards the end of semester, and a video/hints will be made available on Blackboard. This will also require some changes to be made to the admin program.
Submission of Deliverables
Once your assignment is complete, submit both the pseudocode for admin.py (PDF format) and the source code for “admin.py” and “jokebot.py” to the appropriate location in the Assessments area of Blackboard. An assignment cover sheet is not required, but be sure to include your name and student number at the top of all files.
Referencing, Plagiarism and Collusion
The entirety of your assignment must be your own work (unless otherwise referenced) and produced for the current instance of the unit. Any use of unreferenced content you did not create constitutes plagiarism, and is deemed an act of academic misconduct. All assignments will be submitted to plagiarism checking software which includes previous copies of the assignment.
Remember that this is an individual assignment. Never give anyone any part of your assignment – even after the due date or after results have been released. Do not work together with other students on individual assignments – helping someone by explaining errors in their code/logic or directing them to the relevant resources is appropriate, but doing it for them or showing them how you did it is not. An unacceptable level of cooperation between students on an assignment is collusion, and is deemed an act of academic misconduct. If you are uncertain about plagiarism, collusion or referencing, simply email your tutor, lecturer or unit coordinator and ask.
Marking Key
Marks are allocated as follows for this assignment. The marks are divided between both programs.
Criteria Marks
Pseudocode
These marks are awarded for submitting pseudocode which suitably represents the design of your source code. As there are no fixed standards for pseudocode, it will be assessed on the basis of “does it help in understanding/describing the structure of the program?” 5
Functionality
These marks are awarded for submitting source code that implements the requirements specified in this brief, in Python 3. Code which is not functional or contains syntax errors will lose marks, as will failing to implement requirements as specified. 15
Code Quality
These marks are awarded for submitting well-written source code that is efficient, wellformatted and demonstrates a solid understanding of the concepts involved. This includes appropriate use of commenting and adhering to best practise. 10
Total: 30