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