Storage opt.; BookCopy; library in GUI; & more

Overhaul reader libraries:
- Introduce BookCopy storage class, which represents a copy of a book
  acquired by a reader, and has quality, acquired time, and status
  (purchased, pirated, or written).
- Reader.quality()/quality_ now stores BookCopy objects, not double
  quality values.  (The previous quality value is now inside the
  BookCopy).
- got rid of library_pirated, library_pirated_new, library_purchased,
  etc. containers.
- add ReaderState.library_pirated, .library_pirated_new,
  .library_purchased, and .library_purchased_new counters, which cache
  the number of the various types of books.  There's a new
  ReaderState.updateLibraryCounts() method to recalculate the counters
  for a ReaderState.
- some of the non-library_ containers that are left (such as newBooks())
  now return an unordered_map with a reference_wrapper<BookCopy>, to
  avoid needing to do an extra hash lookup in library_ to get at the
  BookCopy info.
- all of this cascades changes into various other creativity classes

Added a Library tab to the reader info window, which lists all library
books (excluding self-authored ones, which are already on the Authored
Books tab)

FileStorage and PsqlStorage library storage efficiency overhaul
- Don't story library entries multiple times.
  - FileStorage now has separate Library blocks which are associated
    with a reader and grow (with pointers to the next block at the end,
    like continuation blocks) as needed, but are stored globally, not
    per-state.  This reduces the file size considerably (on roughly
    similar simulation runs of 100 readers, 200 periods, piracy @ 100,
    the .crstate is now ~90MB, reduced from ~400MB).
  - PsqlStorage has a similar optimization, making the library table
    tied to the simulation and reader_eris_id instead of to the
    per-state reader row.
  - Something similar could be done to MemoryStorage, but isn't: it
    currently still duplicates BookCopys across periods.
- Store eris_ids 32-bit ints instead of 64-bit ints.  Since a creativity
  simulation never destroys anything, it seems extremely unlikely that
  eris_id_t that doesn't fit in a 32-bit will ever come up.
- Storage blocks (continuation blocks, library blocks, and states) are
  now aligned to 4096-byte offsets.  Library blocks are 240*17+8=4088
  (so 8 bytes lost per library block), and continuation blocks were
  already 4096.  The amount lost per state is variable (it depends on
  the number of readers, and the per-state number of books), but
  obviously maximum loss here is 4095 bytes per state.  The alignment
  may slightly speed up state access, though doesn't seem to have much
  effect on my SSD system.

Other miscellaneous changes:
- piracy cost wasn't actually being set
- Renamed Reader.receiveProfits() to receiveProceeds (it's not profits,
  technically, since fixed cost was already incurred).
- cli: when simulation finished, show pending storage status until the
  storage backend finishes.
- To do the above, added a pending() method to the StorageBackend base
  class, that returns the queue_ size (if threading, otherwise 0).
- StorageBackend.enqueue wasn't actually locking the queue mutex.
- Removed Reader for the quality draw lambda: it was a pointless
  argument.
- Moved the "File save" GUI section immediately under the "File load"
  GUI section, which makes much more sense than having it near the
  bottom.