Assignment title: Information
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 1
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.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 2
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):
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).
[
{
"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
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 3
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.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 4
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".
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 5
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.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 6
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 ", "v " and "d ". 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".
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 7
Annotated Screenshot of "admin.py"
To help illustrate the "admin.py" program, here is an annotated screenshot of it being used:
The program welcomes the user, then shows
a list of options to choose from.
The user chooses "l" to list the current jokes
and is told that there are none saved.
They then choose "a" and add a joke by
following the prompts that appear.
They then choose "a" again and add a
second joke.
Now when the user chooses "l", they are
shown the setups of the two saved jokes.
The user chooses "v" to view a joke, entering
the index number when prompted.
Details of the joke's rating are shown – in
this case, the joke has not been rated (Jokes
are rated in the "jokebot.py" program).
The user chooses "s" to search for a joke,
entering a search term when prompted. The
program searches both setup and punchline.
Next the user adds another joke, but then
decides that it is a terrible joke.
They choose "l" to list the jokes, finding that
the terrible one has an index number of 2.
The user chooses "d" to delete the joke,
entering the index number when prompted.
Finally, the user chooses "q" to quit.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 8
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)
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.
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.
When the user rates the final joke from the
self.data list, the messagebox should
mention this and the program should then end.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 9
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.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 10
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.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 11
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.
Semester 1, 2016 CSP1150/CSP5110 Assignment 2 Page 12
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