Online Book Reader
Problem
Design OnlineBookReader to manage a copy-counted library and registered users. One logged-in user at a time can borrow books, read one unfinished book, and rate completed books.
Requirements
- Library setup. The constructor creates each distinct book with its supplied page count and copy count. Every copy is initially available.
- Registration.
registerUsercreates a new user and returnstrue. A duplicate user ID returnsfalsewithout changing state. - Single login.
loginmakes a registered user the sole logged-in user and returnstrue, replacing any previous login. An unknown user returnsfalseand keeps the current login. - Borrowing.
borrowBookreturnstrue, adds the book to the logged-in user's holdings and borrowing history, and consumes one available copy when every borrowing rule is satisfied. Otherwise it returnsfalsewithout changing state. - Holding limit. A user may hold at most two books at once.
- Distinct holdings. A user cannot hold two copies of the same book.
- One current book. The first
readPagecall for a held book starts it when no book is current. A call for a different held book returns0without changing either book while another book is unfinished. - Page navigation. The
movementstring is"current","next", or"previous"."current"reports the page,"next"advances one page, and"previous"moves back one page without going below page 1. The method returns the resulting page. - Completion. When
"next"reaches the last page, the book is completed for that user, removed from holdings and the current slot, and its copy becomes available again. - Rating.
rateBookstores one integer rating from 1 through 5 only after the logged-in user completes that book. It returnstruewhen the rating is stored andfalseotherwise. - User details.
getCurrentUserDetailsreturns the logged-in user ID, held book IDs in borrow order, current book ID and page, and all successfully borrowed book IDs in chronological order. With no current book, its ID is""and its page is0. - Available books.
listAvailableBooksreturns an object keyed by each book ID with at least one available copy. Each value containsavailableCopiesandaverageRating. - Average rating.
averageRatingis the arithmetic mean of all accepted ratings for that book, or0.0when the book has no ratings. - No rereading.
borrowBookreturnsfalsewithout changing state when the logged-in user has already completed that book.
API
| Signature | Returns | Behavior |
|---|---|---|
OnlineBookReader(books: object[]) | Not applicable | Creates the library. Each book object has bookId, pageCount, and copyCount. |
registerUser(userId: string) | boolean | Registers a distinct user. |
login(userId: string) | boolean | Selects the sole logged-in user. |
borrowBook(bookId: string) | boolean | Borrows one copy when inventory and the user's holding rules permit it. |
readPage(bookId: string, movement: string) | integer | Starts or navigates a held book and returns its resulting page, or 0 when another book is current. |
rateBook(bookId: string, rating: integer) | boolean | Stores the user's one valid rating for a completed book. |
getCurrentUserDetails() | object | Returns {userId, heldBookIds, currentBookId, currentPage, borrowingHistory}. |
listAvailableBooks() | object | Returns available books as {bookId: {availableCopies, averageRating}}. |
Examples
Given books [{bookId: "book-a", pageCount: 3, copyCount: 1}, {bookId: "book-b", pageCount: 2, copyCount: 1}]:
| Step | Operation | Result |
|---|---|---|
| 1 | registerUser("u1") | true |
| 2 | login("u1") | true |
| 3 | borrowBook("book-a") | true |
| 4 | borrowBook("book-b") | true |
| 5 | readPage("book-a", "current") | 1 |
| 6 | readPage("book-b", "current") | 0 |
| 7 | rateBook("book-a", 5) | false |
| 8 | readPage("book-a", "next") | 2 |
| 9 | readPage("book-a", "next") | 3 |
| 10 | rateBook("book-a", 5) | true |
| 11 | readPage("book-b", "current") | 1 |
Constraints
- The constructor receives 1 to 100 distinct books. Each
bookIdis non-empty, eachpageCountis from 2 to 10,000, and eachcopyCountis from 1 to 1,000. - User IDs are non-empty strings, and at most 10,000 users register.
- At most 100,000 public method calls occur in one testcase.
- Calls other than the documented boolean rejections use existing book IDs, a logged-in user where required, a held unfinished book for
readPage, and at most one rating per user and completed book.
Notes
Calls are sequential and take effect in invocation order. Counts and pages never become negative. Floating-point results are compared with an absolute tolerance of ; object key order is not significant.