Repository navigation
Expand file tree
/
Copy pathbookshelfmanager.py
More file actions
154 lines (124 loc) · 4.82 KB
/
Copy pathbookshelfmanager.py
File metadata and controls
154 lines (124 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
from typing import List
import json
from typing import Optional
from book import Book
import random
from pathlib import Path
from bookwidth import BookWidth
class BookshelfManager:
"""Manages a collection of books and their visualization."""
def __init__(self, data_file: Path):
self.data_file = data_file
self.books: List[Book] = []
def load_books(self) -> List[Book]:
"""Load books from JSON file."""
if not self.data_file.exists():
print(f"No existing bookshelf found at {self.data_file}")
return []
try:
with open(self.data_file, 'r') as f:
data = json.load(f)
self.books = [Book.from_dict(book_data) for book_data in data]
print(f"Loaded {len(self.books)} books from {self.data_file}")
return self.books
except (json.JSONDecodeError, KeyError) as e:
print(f"Error loading books from {self.data_file}: {e}")
return []
def save_books(self) -> bool:
"""Save books to JSON file."""
try:
self.data_file.parent.mkdir(parents=True, exist_ok=True)
with open(self.data_file, 'w') as f:
json.dump([book.to_dict() for book in self.books], f, indent=2)
print(f"Saved {len(self.books)} books to {self.data_file}")
return True
except Exception as e:
print(f"Error saving books to {self.data_file}: {e}")
return False
def add_book_interactive(self) -> bool:
"""Interactively add a new book."""
try:
title = input("Enter book title: ").strip()
if not title:
print("Title cannot be empty")
return False
author = input("Enter author name: ").strip()
if not author:
print("Author cannot be empty")
return False
pages = self._get_pages_input()
width = self._get_width_input()
new_book = Book(title=title, author=author,
pages=pages, book_width=width)
print(f"\nNew book: {new_book}")
confirm = input("Add this book to the shelf? [y/N]: ").lower()
if confirm == 'y':
self.books.append(new_book)
return self.save_books()
else:
print("Book not added")
return False
except KeyboardInterrupt:
print("\nOperation cancelled")
return False
def _get_pages_input(self) -> int:
"""Get valid page count from user."""
while True:
try:
pages = int(input("Number of pages: "))
if pages > 0:
return pages
print("Pages must be greater than 0")
except ValueError:
print("Please enter a valid number")
def _get_width_input(self) -> BookWidth:
"""Get book width choice from user."""
width_options = {
'0': BookWidth.SMALL,
'1': BookWidth.MEDIUM,
'2': BookWidth.WIDE,
'3': BookWidth.VERY_WIDE
}
print("\nBook width options:")
print("0: Small")
print("1: Medium")
print("2: Wide")
print("3: Very Wide")
while True:
choice = input("Choose width [1]: ").strip() or '1'
if choice in width_options:
return width_options[choice]
print("Please enter 0, 1, 2, or 3")
def link_books(self):
"""Set up linked list connections between books."""
for i, book in enumerate(self.books):
book.prev_book = self.books[i - 1] if i > 0 else None
book.next_book = self.books[i +
1] if i < len(self.books) - 1 else None
if i > 0:
book.x_start = random.randint(1, 11)
def display_bookshelf(self, output_file: Optional[str] = None):
"""Display the bookshelf visualization."""
if not self.books:
print("No books to display. Add some books first!")
return
self.link_books()
file_handle = None
if output_file:
try:
file_handle = open(output_file, 'w')
except Exception as e:
print(f"Error opening output file {output_file}: {e}")
return
try:
for book in reversed(self.books):
book.print_book(file=file_handle)
finally:
if file_handle:
file_handle.close()
print(f"Bookshelf visualization saved to {output_file}")
def reset_to_default(self) -> bool:
"""Reset bookshelf to default books."""
default_books = []
self.books = default_books
return self.save_books()