A console app for managing a small library branch — built around the scenario of a librarian needing to know whether a book is available, check it out to a patron, keep study room bookings conflict-free, and run events without overbooking the room.
- .NET SDK 10.0 or later
- Git
git clone https://github.com/anthonysim/CS690-Project.git
cd CS690-Project
dotnet runThat's it — no database setup, no environment variables. On first run the app seeds sample data automatically.
dotnet runYou'll see a menu:
=== Library Branch Manager ===
1. Search books
2. Check out a book
3. View overdue loans
4. Reserve a study room
5. View library events
6. Check in to an event
7. Exit
Choose 1, then enter a search term. It matches against title, author, or ISBN (case-insensitive, partial match). Leave it blank to list every book in the catalog. Each result shows its status — Available, Checked Out, or Unavailable — and the copy count, e.g.:
[1] The Midnight Library by Matt Haig — Checked Out (0 of 1 available)
[2] Atomic Habits by James Clear — Available (2 of 3 available)
Choose 2, then enter a Patron ID and a Book ID. Checkout is blocked if:
- the patron's account is blocked, or
- the patron has any overdue loan, or
- the book has no available copies.
Otherwise the book is checked out and you'll see a confirmation with a due date 14 days out.
Choose 3 to list every loan past its due date, with the patron, book, due date, and days overdue.
Choose 4, then enter a Patron ID, Room ID, date (yyyy-MM-dd), start time, and end time (HH:mm). The reservation is rejected if it overlaps an existing booking for that room on that date.
Choose 5 to list upcoming events with their date/time and current attendance, e.g. 2 of 2 attending.
Choose 6, then enter an Event ID and a Patron ID. Check-in is rejected once the event's attendance count reaches its capacity.
On first run (when the data files below don't exist yet), the app seeds the following data and writes it to text files (Data/SeedData.cs):
Books
| ID | Title | Author | Status |
|---|---|---|---|
| 1 | The Midnight Library | Matt Haig | Checked Out (0/1) |
| 2 | Atomic Habits | James Clear | Available (2/3) |
| 3 | Where the Crawdads Sing | Delia Owens | Available (1/2) |
Patrons
| ID | Name | Notes |
|---|---|---|
| 1 | Maria Lopez | Has an overdue loan (Book 3, due 6 days ago) |
| 2 | James Carter | |
| 3 | Sam Reed | Blocked account |
Study Rooms
| ID | Name |
|---|---|
| 1 | Room A |
| 2 | Room B |
Events
| ID | Name | Capacity |
|---|---|---|
| 1 | Children's Story Hour | 2 (small on purpose — easy to hit capacity with the 3 seeded patrons) |
| 2 | Author Talk: Local Writers | 20 |
Data is stored in pipe-delimited text files in the project root: books.txt, patrons.txt, loans.txt, studyrooms.txt, reservations.txt, events.txt, eventattendance.txt (Storage/). They're loaded on startup and rewritten after every checkout, reservation, or check-in, so changes survive restarting the app. These files are gitignored — delete them to reset back to the seed data.
Models/ Domain entities (Book, Patron, Loan, StudyRoom, RoomReservation, Event, EventAttendance)
Services/ Business logic (BookService, LoanService, RoomReservationService, EventService)
Storage/ Text-file repositories (load/save each entity)
Data/ Seed data used when no data files exist yet
Tests/ xUnit tests for the Services
Program.cs Console menu and entry point
Unit tests cover the three service modules:
- BookServiceTests — catalog search (blank term, title/author/ISBN match, case-insensitivity, no match)
- LoanServiceTests — checkout success/failure paths (no copies, blocked patron, overdue patron) and overdue loan filtering
- RoomReservationServiceTests — reservation success/failure paths (bad time range, overlapping booking, unknown room)
Run them with:
cd Tests
dotnet testExpected output: all 14 tests pass.
Use the seed data below to verify every functional requirement from the project root after dotnet run.
Choose 1.
- Enter
atomic→ returns Atomic Habits (title match) - Enter
Owens→ returns Where the Crawdads Sing (author match) - Enter
9780525559474→ returns The Midnight Library (ISBN match) - Leave blank → returns all 3 books
Shown inline with every search result:
[1] The Midnight Library by Matt Haig — Checked Out (0 of 1 available)
[2] Atomic Habits by James Clear — Available (2 of 3 available)
Choose 2.
- Patron ID
2(James Carter), Book ID2(Atomic Habits, has copies) → success, due date shown
Choose 2.
- Patron ID
3(Sam Reed — blocked), Book ID2→ rejected: "Sam Reed's account is blocked and cannot borrow books."
Choose 2.
- Patron ID
1(Maria Lopez — has overdue loan), Book ID2→ rejected: "Maria Lopez has overdue items and cannot borrow more books until they are resolved."
Choose 3 → lists Maria Lopez / Where the Crawdads Sing / days overdue.
Choose 4.
- Patron ID
2, Room ID1, Date2026-07-10, Start10:00, End11:00→ success
Choose 4 again with the same inputs → rejected: "Room A is already booked for part of that time on Jul 10, 2026."
Choose 5 → lists both events with date, time, and current attendance count.
Children's Story Hour (Event ID 1) has capacity 2.
Choose 6:
- Event ID
1, Patron ID1→ check-in 1 of 2 - Event ID
1, Patron ID2→ check-in 2 of 2 (full) - Event ID
1, Patron ID3→ rejected: event is at capacity
Restart the app after any of the above actions — all changes survive. Delete the .txt files in the project root to reset to seed data.
This covers all eleven functional requirements from the original scenario:
- Search books by title, author, or ISBN
- Display whether a book is available, checked out, or unavailable
- Check out an available book to a patron
- Prevent borrowing if the patron has overdue items or a blocked account
- View overdue loans
- Reserve a study room for a patron, preventing double-booking
- View library events
- Track event attendance
- Prevent additional check-ins once an event is at capacity
- Store and retrieve library data from text files
Not yet implemented: returning books (no functional requirement covers this yet).