Skip to content

Instantly share code, notes, and snippets.

@JamesJinPark
Last active August 29, 2015 14:07
Show Gist options
  • Save JamesJinPark/1b76823bd0d550fda102 to your computer and use it in GitHub Desktop.
Save JamesJinPark/1b76823bd0d550fda102 to your computer and use it in GitHub Desktop.
library
# Classes and methods for a simple library program
# Authors: Dave Matuszek and James Park and Josh Kessler
#--------------------------------------------------------------
class Calendar(object):
"""Keeps track of the durrent date (as an integer)."""
def __init__(self):
"""Creates the initial calendar."""
self.date = 0
def get_date(self):
"""Returns (as a positive integer) the current date."""
return self.date
def advance(self):
"""Advances this calendar to the next date."""
self.date += 1
#--------------------------------------------------------------
class Book(object):
"""Represents one copy of a book. There may be many copies
of a book with the same title and author.
Each book has:
* A title
* An author (one string, even if many authors)
* A due date (or None if the book is not checked out.)."""
global book_id_count
book_id_count = 1
def __init__(self, title, author):
"""Creates a book, not checked out to anyone."""
global book_id_count
self.book_id = book_id_count
book_id_count += 1
self.title = title
self.author = author
self.due_date = None
def get_title(self):
"""Returns the title of this book."""
return self.title
def get_author(self):
"""Returns the author(s) of this book, as a single string."""
return self.author
def get_due_date(self):
"""If this book is checked out, returns the date on
which it is due, else returns None."""
return self.due_date
def check_out(self, due_date):
"""Sets the due date for this book."""
self.due_date = due_date
def check_in(self):
"""Clears the due date for this book (sets it to None)."""
self.due_date = None
def __str__(self):
"""Returns a string representation of this book,
of the form: title, by author"""
return "%s, by %s" % (self.title, self.author)
def __eq__(self, other):
"""Tests if this book equals the given parameter. Not
required by assignment, but fairly important."""
return self.title == other.title and self.author == other.author
#--------------------------------------------------------------
class Patron(object):
"""Represents a patron of the library. A patron has:
* A name
* A set of books checked out"""
def __init__(self, name):
"""Constructs a new patron, with no books checked out yet."""
self.name = name
self.books_checked_out = []
def get_name(self):
"""Returns this patron's name."""
return self.name
def get_books(self):
"""Returns the set of books checked out to this patron."""
return set(self.books_checked_out)
def take(self, book):
"""Adds a book to the set of books checked out to this patron."""
self.books_checked_out.append(book)
def give_back(self, book):
"""Removes a book from the set of books checked out to this patron."""
self.books_checked_out.remove(book)
def __str__(self):
"""Returns a string representation of the name of this patron."""
return "The name of this patron is " + self.name
#--------------------------------------------------------------
class OverdueNotice(object):
"""Represents a message that will be sent to a patron."""
def __init__(self, set_of_books):
"""Takes note of all the books checked out to some patron."""
patron = Patron('name')
self.set_of_books = patron.get_books()
def __str__(self):
"""From a set of books, returns a multi-line string giving
the dates on which the books were or will be due.
This should only be called when at least one of the books
is overdue, but ALL the patron's books are listed, with
their due dates, and the overdue ones specially marked."""
#pseudo code
#We don't know if we should check HERE if one of the borrowed books is...
#overdue, since there is another method in library that checks for overdue books.
"""
for x in len(list of books taken out by patron)
get date for each book
if get date < current_date:
flag overdue book
return list of all books
"""
for x in range(0, len(list((self.set_of_books)))):
if list(self.set_of_books)[x].get_due_date < Calendar().get_date:
return "OVERDUE NOTICE: " + list(self.set_of_books)[x].get_title + "was due on " + list(self.set_of_books)[x].get_due_date + "!"
elif list(self.set_of_books)[x].get_due_date == Calendar().get_date:
return list(self.set_of_books)[x].get_title + "is due today."
else:
return list(set_of_books)[x].get_title + "is due on " + list(set_of_books)[x].get_due_date + "."
#--------------------------------------------------------------
class Library(object):
"""Provides operations available to the librarian."""
def __init__(self):
"""Constructs a library, which involves reading in a
list of books that are in this library's collection."""
# Create a global calendar, to be used by many classes
global calendar
calendar = Calendar()
# Initialize some instance variables for _this_ library
self.is_open = False # Is library open?
self.collection = [] # List of all Books
self.patrons = {} # Set of all Patrons
self.patron_being_served = None # Current patron
self.response = '' # Accumulated messages to print
self.last_search_result = set()
def read_collection(self):
# Read in the book collection
file = open('collection.txt')
for line in file:
if len(line) > 1:
tuple = eval(line.strip())
self.collection.append(Book(tuple[0], tuple[1]))
file.close()
def set_collection(self, list_of_books):
self.collection.append[list_of_books]
def open(self):
"""Opens this library for business at the start of a new day."""
if self.is_open:
self.response = "The library is already open!"
return self.response
else:
self.is_open = True
calendar.advance()
self.response = "Today's date is %d." % calendar.get_date()
return self.response
def list_overdue_books(self):
"""Returns a nicely formatted, multiline string, listing the names of
patrons who have overdue books, and for each such patron,
the books that are overdue. Or, it returns the string
"No books are overdue.".
Possible - 'Exception: "The library is not open."'
"""
if not self.is_open:
self.response = "The library is not open."
return self.response
def issue_card(self, name_of_patron):
"""Allows the named person the use of this library. No patron should be
permitted to have more than one library card. For convenience,
immediately begins serving the new patron.
Returns either "Library card issued to name_of_patron" or
"name_of_patron already has a library card."
Possible - "Exception: "The library is not open.""
"""
if not self.is_open:
self.response = "The library is not open."
return self.response
# additional code goes here
self.serve(name_of_patron)
def serve(self, name_of_patron):
"""Sets the patron_being_served instance variable if the patron has a
library card. Otherwise returns "name of patron does not have a library card.
If the patron does have a library card,
the method should return a multiline string containing
"Now serving name_of_patron." plus a numbered list of books
checked out to that patron, if any.
Possible Exception: "The library is not open."
Subsequent check_in and check_out operations will refer to this patron,
so that the patron's name need not be entered many times.
"""
if not self.is_open:
self.response = "The library is not open."
return self.response
self.patron_being_served = name_of_patron
def check_in(self, *book_numbers):
"""
One or more books are being returned by the collection and
remove it from the set of books currently checked out to the patron.
The book_numbers are taken from the list printed by the serve command.
Checking in a Book will involve both telling the Book that it is checked
in and returning the Book to this library's collection of available Books.
If successful, returns "name_of_patron has returned n books.".
May raise an Exception with an appropriate message:
"The library is not open."
"No patron is currently being served."
"The patron does not have book number."
"""
if not self.is_open:
self.response = "The library is not open."
return self.response
pass
def search(self, string):
"""
Finds those Books whose title or author (or both) contains this string.
For example, the string "tact" might return, among other things, the
book Contact, by Carl Sagan. The search should be case-insensitive;
that is, "saga" would also return this book. Only books which are
currently available (not checked out) will be found.
If there is more than one copy of a book (with the same title and
same author), only one will be found. In addition, to keep from
returning too many books, require that the search string be at
least 4 characters long.
Returns one of:
"No books found."
"Search string must contain at least four characters."
A multiline string, each line containing one book
(as returned by the book's __str__ method.)
"""
if not self.is_open:
self.response = "The library is not open."
return self.response
search_results = set()
if len(string) < 4:
self.response = "Search term needs to be 4 characters or longer."
return self.response
for x in self.collection:
if string.lower() in x.get_title().lower() \
or string.lower() in x.get_author().lower():
search_results.add(x.__str__())
for x in self.collection:
if x.get_due_date() != None:
search.results.pop(x)
if search_results == set([]):
self.response = "No books found."
return self.response
result_list = list(search_results)[:10]
for i, result in enumerate(result_list):
print "%s: %s" % (i + 1, result)
self.last_search_results = search_results
return search_results
def check_out(self, *book_numbers):
books = []
results = list(self.last_search_results)
due_date = calendar.get_date() + 7
# TODO: CHECK HERE IF ALREADY CHECKED OUT BEFORE ALLOWING USER TO CHECKOUT
for i in book_numbers:
book = results[i - 1]
book.check_out(due_date)
books.append(book)
print books
"""Checks books out to the patron currently being served.
Books will be due seven days from "today".
Patron must have a library card, and may have not more
than three books checked out at a time."""
pass
def renew(self, *book_ids):
"""Renews the books for the patron currently being served
(by setting their due dates to today's date plus 7) or tells
why the operation is not permitted. If successful, returns
"n books have been renewed for name_of_patron.".
May throw an Exception with an appropriate message:
"The library is not open."
"No patron is currently being served."
"The patron does not have book id."
"""
if not self.is_open:
self.response = "The library is not open."
return self.response
pass
def close(self):
"""Closes the library for the day."""
if not self.is_open:
self.response = "The library is not open."
return self.response
else:
self.is_open = False
self.response = "Good night."
return self.response
def quit(self):
print ("The mayor embezzled from the city, and the library is closed"
+ " until further funding can be secured.")
def help(self):
self.talk("""
help()
Repeat this list of commands.
open()
Opens the library for business; do this once each morning.
list_overdue_books()
Prints out information about books due yesterday.
issue_card("name_of_patron")
Allows the named person the use of the library.
serve("name_of_patron")
Sets this patron to be the current patron being served.
search("string")
Searches for any book or author containing this string
and displays a numbered list of results.
check_out(books...)
Checks out books (by number) to the current patron.
check_in(books...)
Accepts returned books (by number) from the current patron.
close()
Closes the library at the end of the day.
quit()
Closes the library for good. Hope you never have to use this!""")
# ----- Assorted helper methods (of Library) -----
def talk(self, message):
"""Accumulates messages for later printing. A newline is
appended after each message."""
self.response += message + '\n'
# Feel free to add any more helper methods you would like
#--------------------------------------------------------------
def main():
library = Library()
library.read_collection()
print len(library.collection), 'books in collection.'
print "Ready for input. Type 'help()' for a list of commands.\n"
command = '\0'
while command != 'quit()':
try:
command = raw_input('Library command: ').strip()
if len(command) == 0:
print "What? Speak up!\n"
else:
eval('library.' + command)
print library.response
library.response = ''
except AttributeError, e:
print "Sorry, I didn't understand:", command
print e
print "Type 'help()' for a list of the things I do understand.\n"
except Exception, e:
print "Unexpected error:", e
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment