#!/usr/bin/env luajit math.randomseed(os.time()) local books = { read = 514, unread = 2682, per_calibre_page = 6, } books.total = books.read + books.unread local ratings = { 47, 51, 84, 76, 31 } local average_rating = (function() local count, rating = 0, 0 for i = 1, #ratings do count = count + ratings[i] rating = rating + ratings[i] * i end return rating / count end)() -- based on StoryGraph read, to-read, dnf, and owned stats books.average_page_count = (90487 + 146938 + 14796 + 145380) / (434 + 419 + 59 + 668) -- at time of coding, this estimated 113492 pages read, instead of the 90487 I actually read -- this also doesn't have any way to account for many of those pages being not ebooks -- so I'm adding an adjustment factor here to make estimates more accurate: books.average_page_count = books.average_page_count / (113492/90487) -- according to StoryGraph, 75% of my reading is ebooks, so I'm adding another adjustment: books.average_page_count = books.average_page_count * 0.75 -- the calculated number here now PERFECTLY matches my read pages on StoryGraph, despite 17% print books.. -- so I guess I should do one more adjustment! books.average_page_count = books.average_page_count * (1 - 0.17) local function to_calibre_pages(count) return math.ceil(count / books.per_calibre_page) end local calibre_pages = { total = to_calibre_pages(books.total), read = to_calibre_pages(books.read), unread = to_calibre_pages(books.unread), } local calibre_links = { total = "https://calibre.tangentfox.com/page/", read = "https://calibre.tangentfox.com/read/stored/1/", unread = "https://calibre.tangentfox.com/unread/stored/1/", } local function open_random_links(_type, count) for i = 1, count do local page_number = math.random(calibre_pages[_type]) os.execute("open \"" .. calibre_links[_type] .. page_number .. "\"") os.execute("sleep 1") end end local function estimate_pages(count) return math.floor(books.average_page_count * count) end print(books.total .. " books: " .. books.read .. " read (" .. string.format("%.2f", books.read / books.total * 100) .. "%), " .. books.unread .. " unread. Average rating: " .. string.format("%.2f", average_rating)) -- print("Calibre pages: " .. calibre_pages.total .. " pages. " .. calibre_pages.read .. " read pages, " .. calibre_pages.unread .. " unread pages.") print("Estimated pages: " .. estimate_pages(books.total) .. " total, " .. estimate_pages(books.read) .. " read, " .. estimate_pages(books.unread) .. " unread.") print("") -- 2025's reading rate is 115.792 pages/day. Some pages are double-counted though, so I presume the 100/day rate is correct. -- 2024's reading rate was 83.485 pages/day. Some were double-counted, and only part of the year is when I set a 100/day goal average. print("In theory, it will take " .. string.format("%.1f", estimate_pages(books.unread) / 100 / 365) .. " years to read all unread books.") print(" (Between " .. string.format("%.1f", estimate_pages(books.unread) / 116 / 365) .. " and " .. string.format("%.1f", estimate_pages(books.unread) / 83 / 365) .. " years.)") print("") print("Press enter to open 9 random pages on Calibre. :D Or close this window / Ctrl+C to skip that.") io.read("*line") open_random_links("unread", 9)