📄 librarysystem.java
字号:
package library;
import dslib.list.BilinkedListUos;
import dslib.dictionary.arrayed.ArrayedPKeyedBasicDictUos;
import dslib.base.*;
import java.io.*;
import dslib.exception.*;
/** The library system to handle the borrowing and returning of books. In particular,
it keeps track of books on loan so that overdue notices can be sent out efficiently. */
public class LibrarySystem
{
/** A list of overdue books. */
private BilinkedListUos overdueList;
/** A list for each day of the books due back that day. */
private BilinkedListUos[] onLoanLists;
/** A constant to store the number of days in a year. */
private final int YEAR_LENGTH = 366;
/** A constant recording the current upper bound for the number of books. */
private final int MAX_NUM_OF_BOOKS = 10;
/** A dictionary of all books in the library with access by isbn number. */
private ArrayedPKeyedBasicDictUos books;
/** The date today. */
private int date;
/** The next day for which overdue notices need to be printed. */
private int nextDayToPrint;
/** Initialize the library system: the lists, the current date, and the books dictionary.
Analysis: Time = O(max(YEAR_LENGTH, MAX_NUM_OF_BOOKS)) */
public LibrarySystem()
{
overdueList = new BilinkedListUos();
onLoanLists = new BilinkedListUos[YEAR_LENGTH];
for (int i = 0; i < YEAR_LENGTH; i++)
onLoanLists[i] = new BilinkedListUos();
date = 1;
nextDayToPrint = date;
books = new ArrayedPKeyedBasicDictUos(MAX_NUM_OF_BOOKS);
}
/** Add a new book into the library.
Analysis: Time = O(books.count) i.e., time to insert a book into the dictionary
PRECONDITION:
!books.isFull()
!books.has(isbn) */
public void addBook(String title, String author, String isbn) throws ContainerFullUosException, DuplicateItemsUosException
{
if (books.isFull())
throw new ContainerFullUosException("Cannot add a book when the book dictionary is full.");
if (books.has(isbn))
throw new DuplicateItemsUosException("Cannot add a book with the same isbn as an existing book");
LibraryBook newBook = new LibraryBook(title, author, isbn);
books.insert(isbn, newBook);
}
/** Remove the 'isbn' book from the library.
Analysis: Time = O(books.count) i.e., time to delete a book from the dictionary
PRECONDITION:
books.has(isbn) */
public void removeBook(String isbn) throws ItemNotFoundUosException
{
if (!books.has(isbn))
throw new ItemNotFoundUosException("Cannot delete a book that is not in the dictionary.");
books.delete(isbn);
}
/** Carry out the borrowing of the `isbn' book by patron `p'.
Analysis: Time = O(log(books.count)) i.e., time to obtain the book
PRECONDITION:
books.has(ibsn) */
public void borrowBook(String isbn, Patron p) throws ItemNotFoundUosException, BookOnLoanException
{
if (!books.has(isbn))
throw new ItemNotFoundUosException("Cannot borrow a book that is not in the library.");
LibraryBook b = (LibraryBook)books.obtain(isbn);
if (b.isOnLoan())
throw new BookOnLoanException("Cannot borrow a book already on loan.");
int dd = dueDate();
p.borrowBook(b);
b.borrowed(p, dd);
onLoanLists[dd - 1].insertGo(b);
b.setPosition(onLoanLists[dd - 1].currentPosition());
}
/** Carry out the return of the `isbn' book.
Analysis: Time = O(log(books.count)) i.e., time to obtain the book
PRECONDITION:
books.has(isbn) */
public void returnBook(String isbn) throws ItemNotFoundUosException, BookNotOnLoanException
{
if (!books.has(isbn))
throw new ItemNotFoundUosException("Cannot return a book that is not in the library.");
LibraryBook b = (LibraryBook)books.obtain(isbn);
if (!b.isOnLoan())
throw new BookNotOnLoanException("Cannot return a book not on loan.");
Patron p = b.onLoanTo;
BilinkedListUos listOfBooks;
if (b.isOverdue)
{
printOverdueCharges(b);
listOfBooks = overdueList;
}
else
listOfBooks = (BilinkedListUos)onLoanLists[b.dueDate - 1];
listOfBooks.goPosition(b.position);
listOfBooks.deleteItem();
p.returnBook(b);
b.returned();
}
/** Print overdue notices and start of month reminder notices.
Analysis: Time = O(n), where n = number of notices printed */
public void printNotices()
{
int printStart = nextDayToPrint;
printFirstNotices(printStart); // print overdue notices from printStart to yesterday
nextDayToPrint = date;
/* Print start of month reminders if a month started during the period being printed. */
int printEnd = date - 1;
if (printEnd == 0)
printEnd = YEAR_LENGTH;
if (containsMonthStart(printStart, printEnd))
printReminderNotices();
}
/** Print a reminder notice for those books more than 15 days overdue.
Analysis: Time = O(k), where k = length of the overdue list */
public void printReminderNotices()
{
overdueList.goFirst();
while (!overdueList.after())
{
LibraryBook curBook = (LibraryBook)overdueList.item();
if (daysOverdue(curBook) >= 15)
printOverdue(curBook, "reminder");
overdueList.goForth();
}
}
/** Print overdue notices for books which just became overdue.
Analysis: Time = O(p), where p = number of notices printed */
public void printFirstNotices(int printStart)
{
/* Print notices from day = printStart until date - 1. */
for (int d = printStart; d != date; d++)
{
if (d == YEAR_LENGTH + 1)
d = 1;
/* Print the notices for books due on date d. */
BilinkedListUos list = onLoanLists[d-1];
list.goFirst();
while (!list.after())
{
LibraryBook b = (LibraryBook)list.item();
printOverdue(b, "first");
list.deleteItem();
overdueList.insertGo(b);
b.setPosition(overdueList.currentPosition());
b.setOverdue();
/* Don't include list.goForth as deleteItem advances to next item. */
}
}
}
/** Compute the date that the book is due.
Analysis: Time = O(1) */
public int dueDate()
{
int result = date + 21;
if (result > YEAR_LENGTH)
result -= YEAR_LENGTH;
return result;
}
/** Compute the number of days book `b' is overdue.
Analysis: Time = O(1) */
public int daysOverdue(LibraryBook b)
{
int result = date - b.dueDate;
if (result <= 0)
result += YEAR_LENGTH;
return result;
}
/** Compute the late charges for book `b'.
Analysis: Time = O(1) */
public double computeCharges(LibraryBook b)
{
return daysOverdue(b) * 0.5;
}
/** Set the date.
Analysis: Time = O(1) */
public void setDate(int x)
{
date = x;
}
/** The day of the month. */
private int monthDay;
/** Dummy function for testing purposes.
Assumes 5 working days (calls to printNotices) per month */
public boolean containsMonthStart(int d1, int d2)
{
boolean found = false;
monthDay++;
if (monthDay == 5)
{
found = true;
monthDay = 0;
}
return found;
}
/** Writer for debug */
PrintWriter outfile;
/** Set the writer for debugging purposes */
public void setWriter(PrintWriter newOutFile)
{
outfile = newOutFile;
}
/** Print the late charges for book `b'.
Analysis: Time = O(1) */
public void printOverdueCharges(LibraryBook b)
{
outfile.println("\nreturn of overdue book: " + b.toString()
+ "\n" + " Late charges amount to: $" + computeCharges(b));
}
/** Print out the late notice of a specific type for book `b'.
Analysis: Time = O(1) */
public void printOverdue(LibraryBook b, String type)
{
outfile.println("\nOVERDUE NOTICE for day " + date + " ---------------"
+ "\n" + b.toString() + "\n Type of notice: " + type);
}
/** String representation of all library current information, including the books
in the library, the books on loan, and the books that are overdue.
Analysis: Time = O(n+m+p), where n = number of books in the library,
m = number of books on loan, and p = number of overdue books */
public String toString()
{
String result = "\n........... Library status on day " + date + " ............"
+ "\nBooks of the library \n" + books.toString() + "\nOn loan lists";
for (int i = 0; i < YEAR_LENGTH; i++)
if (!onLoanLists[i].isEmpty())
{
result += " \nList " + (i+1) + " contents *************************"
+ "\n" + onLoanLists[i].toString();
}
result += "\n\nOverdue list contents *************************";
if (overdueList.isEmpty())
result += "\n No overdue books.\n";
else
result += "\n" + overdueList.toString();
result += "\n........... End library status .........\n";
return result;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -