This commit is contained in:
		
							parent
							
								
									623a463d9f
								
							
						
					
					
						commit
						2d0fb9ed84
					
				
							
								
								
									
										106
									
								
								src/garden/book-collecting.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										106
									
								
								src/garden/book-collecting.md
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,106 @@
 | 
				
			|||||||
 | 
					how do you define a book collection?
 | 
				
			||||||
 | 
					my book collection is the set of all books.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i prefer physical books to e-readers.
 | 
				
			||||||
 | 
					unfortunately i have quite a few these days.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i want to read them all eventually!
 | 
				
			||||||
 | 
					i also tend to live in quite small places
 | 
				
			||||||
 | 
					and i want to be able to move city easily!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					so here's my system for organising my physical book collection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i want to:
 | 
				
			||||||
 | 
					*   read books i already have
 | 
				
			||||||
 | 
					*   read as many different books as possible
 | 
				
			||||||
 | 
					*   minimise physical storage requirements
 | 
				
			||||||
 | 
					*   keep track of books i've read
 | 
				
			||||||
 | 
					*   gather books i don't already have
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					constraints
 | 
				
			||||||
 | 
					*   i don't know for sure what book i will want to read next
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					for every book in the world
 | 
				
			||||||
 | 
					*   i either have or have not read it
 | 
				
			||||||
 | 
					*   i have access to it or i don't
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					so i sort my book collection with 4 categories
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*-------------------*-----------------------*
 | 
				
			||||||
 | 
					|                   |                       |
 | 
				
			||||||
 | 
					|       unread      |          read         |
 | 
				
			||||||
 | 
					|        have       |          have         |
 | 
				
			||||||
 | 
					|                   |                       |
 | 
				
			||||||
 | 
					|   37º2 le matin   |   L'Homme des Jeux    |
 | 
				
			||||||
 | 
					|                   |                       |
 | 
				
			||||||
 | 
					*-------------------*-----------------------*
 | 
				
			||||||
 | 
					|                   |                       |
 | 
				
			||||||
 | 
					|       unread      |         read          |
 | 
				
			||||||
 | 
					|       haven't     |        haven't        |
 | 
				
			||||||
 | 
					|                   |                       |
 | 
				
			||||||
 | 
					|    Das Kapital    |      Frankisstein     |
 | 
				
			||||||
 | 
					|                   |                       |
 | 
				
			||||||
 | 
					*-------------------*-----------------------*
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i can then begin to optimise my collection.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*   i do not have this book, and i have read it.
 | 
				
			||||||
 | 
					*   i have this book, but i have not read it.
 | 
				
			||||||
 | 
					*   i have this book, and i have read it.
 | 
				
			||||||
 | 
					*   i do not have this book, but i have not read it.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					the books i am most interested in having nearby are unread ones, as i would like to read as many different books as possible.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					books i have already read i don't need nearby anymore.
 | 
				
			||||||
 | 
					i might pass it on, or store it somewhere with less of a premium on space.
 | 
				
			||||||
 | 
					i could also attempt to track where it is!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					based on my requirements and my categories, i create four lists for the books
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					*   ready
 | 
				
			||||||
 | 
					*   all done
 | 
				
			||||||
 | 
					*   read and gone
 | 
				
			||||||
 | 
					*   hunted
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					that looks like a decent start to the system, so i suppose now i'll start collecting!
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					so i'll use markdown lists in the format
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					* [x] author - title    # reading
 | 
				
			||||||
 | 
					* [ ] author - title    # nearby
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					when collecting music i use artist - year - name
 | 
				
			||||||
 | 
					however, publication year is an extra step that will slow data entry, so won't use this to start with - i have a lot of books
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					i realised i had a gpt-4 sub and that it could look at pictures now so i gave it a go
 | 
				
			||||||
 | 
					i fed it some photos and some formatting preferences and i got out perfect markdown lists
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					- [ ] Doctorow, Cory - Walkaway
 | 
				
			||||||
 | 
					- [ ] Ferreira, Pedro G. - The Perfect Theory
 | 
				
			||||||
 | 
					- [ ] Hadfield, Chris - An Astronaut's Guide to Life on Earth
 | 
				
			||||||
 | 
					- [ ] Heinlein, Robert A. - Beyond This Horizon
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					books are lovely are great to look at, but the mishmash of fonts and presentation are a nightmare for indexing.
 | 
				
			||||||
 | 
					now we have some good and lovely metadata :)
 | 
				
			||||||
 | 
					this is an imperfect method, as the only way i can check it is still by combing through the physical books manually
 | 
				
			||||||
 | 
					but it does let me target my combing after identifying problems in the index
 | 
				
			||||||
 | 
					and in the meantime gives us a bunch of data to play with
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					markdown lists also allow me to mark some items in a list
 | 
				
			||||||
 | 
					this is looks flexible, so i think in my 'ready' list i will mark which book(s) i am currently reading
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					- [ ] Doctorow, Cory - Walkaway
 | 
				
			||||||
 | 
					- [ ] Ferreira, Pedro G. - The Perfect Theory
 | 
				
			||||||
 | 
					- [ ] Hadfield, Chris - An Astronaut's Guide to Life on Earth
 | 
				
			||||||
 | 
					- [ ] Heinlein, Robert A. - Beyond This Horizon
 | 
				
			||||||
 | 
					```
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					the other lists i will leave unmarked for now, until i think of something to do with them.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					as for doing things with them, i wrote a [python script](#) which processes the data in the now-populated all-done and ready lists to yield some interesting (?) and fun (?) results?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					[example output](#)
 | 
				
			||||||
							
								
								
									
										87
									
								
								src/garden/books.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/garden/books.py
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,87 @@
 | 
				
			|||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_usage():
 | 
				
			||||||
 | 
					    print(f"usage: python {sys.argv[0]} DIR")
 | 
				
			||||||
 | 
					    print(f"")
 | 
				
			||||||
 | 
					    print(f"\tDIR\tdirectory containing markdown lists in files.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if len(sys.argv) != 2:
 | 
				
			||||||
 | 
					    print_usage()
 | 
				
			||||||
 | 
					    exit(1)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					base_path = os.path.abspath(sys.argv[1])
 | 
				
			||||||
 | 
					ready_list_name = "ready.md"
 | 
				
			||||||
 | 
					done_list_name = "all-done.md"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_path(list_name : str) -> str:
 | 
				
			||||||
 | 
					    return os.path.join(base_path, list_name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_matches(list_name : str) -> list[re.Match]:
 | 
				
			||||||
 | 
					    # Matches a markdown list item
 | 
				
			||||||
 | 
					    entry_pattern = re.compile(r"^[*-] \[([ *x])\] (.+) - (.+)")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    matches = []
 | 
				
			||||||
 | 
					    with open(get_path(list_name)) as f:
 | 
				
			||||||
 | 
					        matches = [entry_pattern.match(l) for l in f.readlines()]
 | 
				
			||||||
 | 
					    return [m for m in matches if m is not None]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Book:
 | 
				
			||||||
 | 
					    def __init__(self, match : re.Pattern):
 | 
				
			||||||
 | 
					        self.mark = match.group(1) != " "
 | 
				
			||||||
 | 
					        self.author = match.group(2)
 | 
				
			||||||
 | 
					        self.title = match.group(3)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def is_metadata_complete(self):
 | 
				
			||||||
 | 
					        if not self.title or not self.author:
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if self.title == "???" or self.author == "???":
 | 
				
			||||||
 | 
					            return False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    @staticmethod
 | 
				
			||||||
 | 
					    def get_list(list_name : str, filter_partial_metadata = True) -> []:
 | 
				
			||||||
 | 
					        books = [Book(m) for m in get_matches(list_name)] 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if filter_partial_metadata:
 | 
				
			||||||
 | 
					            books = [b for b in books if b.is_metadata_complete()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        return books
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_section(title : str, books : list[str]):
 | 
				
			||||||
 | 
					    print(f"# {title} ({len(books)})\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    longest_title = max([len(b.title) for b in books])
 | 
				
			||||||
 | 
					    title_column_width = longest_title + 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    for book in books:
 | 
				
			||||||
 | 
					        row = [book.title, book.author]
 | 
				
			||||||
 | 
					        format_str = "- {: <" + str(title_column_width) + "} {: <20}"
 | 
				
			||||||
 | 
					        print(format_str.format(*row))
 | 
				
			||||||
 | 
					    print()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_in_progress():
 | 
				
			||||||
 | 
					    books = [b for b in Book.get_list(ready_list_name, False) if b.mark]
 | 
				
			||||||
 | 
					    print_section("in progress", books)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_completed():
 | 
				
			||||||
 | 
					    books = Book.get_list(done_list_name)
 | 
				
			||||||
 | 
					    print_section("up for borrowing", books)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def print_partial_metadata():
 | 
				
			||||||
 | 
					    books = Book.get_list(ready_list_name, False)
 | 
				
			||||||
 | 
					    books += Book.get_list(done_list_name, False)
 | 
				
			||||||
 | 
					    books = [b for b in books if not b.is_metadata_complete()]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print_section("metadata incomplete", books)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					print_in_progress()
 | 
				
			||||||
 | 
					print_completed()
 | 
				
			||||||
 | 
					print_partial_metadata()
 | 
				
			||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user