books can be added
- debug function added - updating progress added - book select/add multifunction (ew sounds like corpo-speak) - fixed initial priority assignment to be randomized - pulled out preset function - normal exit capability (lol)
This commit is contained in:
@@ -5,12 +5,14 @@ CLI tracker to prioritize your limited time by ELO ranking media.
|
|||||||
- [ ] Mark books read/unread/in-progress.
|
- [ ] Mark books read/unread/in-progress.
|
||||||
- [x] Show top 10 / bottom 10. Show only in-progress or unread.
|
- [x] Show top 10 / bottom 10. Show only in-progress or unread.
|
||||||
- [ ] Rank only in-progress or unread.
|
- [ ] Rank only in-progress or unread.
|
||||||
- [ ] Track books by title, author, and series. Default is to recognize "by" or "(series)" and automatically sort into relevant fields.
|
- [x] Track books by title, author, and series. Default is to recognize "by" or "(series)" and automatically sort into relevant fields.
|
||||||
- [x] But also almost nothing is actually *needed*.
|
- [x] But also almost nothing is actually *needed*.
|
||||||
- [x] Store progress as a numerical value? (Unread = 0, read = 1, in-progress in-between? Too easy to forget how it works?)
|
- [x] Store progress as a numerical value? (Unread = 0, read = 1, in-progress in-between? Too easy to forget how it works?)
|
||||||
- [x] Store pages as an option,
|
- [x] Store pages as an option,
|
||||||
- [ ] allow a weighted priority based on remaining percentage or whatever.
|
- [ ] allow a weighted priority based on remaining percentage or whatever.
|
||||||
- [x] Store items as an array instead of object, because that makes the JSON output more consistent -> smaller JSON commit differences.
|
- [x] Store items as an array instead of object, because that makes the JSON output more consistent -> smaller JSON commit differences.
|
||||||
|
- [ ] Re-implement ELO ranking.
|
||||||
|
- [ ] Display filter/sort options to output lists. (Focus only on top 10 items?)
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
|
|||||||
+153
-47
@@ -3,6 +3,8 @@ local json = require "lib.dkjson"
|
|||||||
math.randomseed(os.time())
|
math.randomseed(os.time())
|
||||||
|
|
||||||
local default_file = "books.json"
|
local default_file = "books.json"
|
||||||
|
local debug = function() end
|
||||||
|
local debug = function(...) print(...) end
|
||||||
|
|
||||||
local path_exists = function(path_name)
|
local path_exists = function(path_name)
|
||||||
local file = io.open(path_name, "r")
|
local file = io.open(path_name, "r")
|
||||||
@@ -27,6 +29,7 @@ local save_json = function(file_name, data)
|
|||||||
file:write(json.encode(data, { indent = true, }))
|
file:write(json.encode(data, { indent = true, }))
|
||||||
file:write("\n")
|
file:write("\n")
|
||||||
file:close()
|
file:close()
|
||||||
|
debug("Saved.")
|
||||||
end
|
end
|
||||||
|
|
||||||
local get_random_order = function(array)
|
local get_random_order = function(array)
|
||||||
@@ -105,6 +108,136 @@ sort_orders = {
|
|||||||
end,
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
local get_display_name = function(book)
|
||||||
|
local result = ""
|
||||||
|
|
||||||
|
if book.title then
|
||||||
|
result = book.title
|
||||||
|
if book.author then
|
||||||
|
result = result .. " by " .. book.author
|
||||||
|
end
|
||||||
|
elseif book.author then
|
||||||
|
result = book.author .. " (author)"
|
||||||
|
end
|
||||||
|
|
||||||
|
if book.series then
|
||||||
|
if #result > 0 then
|
||||||
|
result = result .. " (" .. book.series .. ")"
|
||||||
|
else
|
||||||
|
result = book.series .. " (series)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if book.genre then
|
||||||
|
if #result > 0 then
|
||||||
|
result = result .. " (" .. book.genre .. ")"
|
||||||
|
else
|
||||||
|
result = book.genre .. " (genre)"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if book.pages then
|
||||||
|
result = result .. " ~" .. math.floor(book.progress * book.pages) .. "/" .. book.pages .. " pages read"
|
||||||
|
elseif book.progress > 0 and book.progress < 1 then
|
||||||
|
result = result .. " ~" .. math.floor(book.progress * 100) .. "% read"
|
||||||
|
end
|
||||||
|
|
||||||
|
return result
|
||||||
|
end
|
||||||
|
|
||||||
|
local update_progress_prompt = function(book)
|
||||||
|
if not book then
|
||||||
|
print("Invalid selection.")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
print("Enter a value between 0 and 1 to update progress:")
|
||||||
|
print(" " .. get_display_name(book))
|
||||||
|
|
||||||
|
local input = io.read("*line")
|
||||||
|
local numerical = tonumber(input)
|
||||||
|
if numerical >= 0 and numerical <= 1 then
|
||||||
|
book.progress = numerical
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
|
||||||
|
-- saving is handled by a higher function on the stack
|
||||||
|
end
|
||||||
|
|
||||||
|
local get_book = function(data, input)
|
||||||
|
local title, author, series, genre
|
||||||
|
local i, j = input:find(" by ")
|
||||||
|
if i then
|
||||||
|
title = input:sub(1, i - 1)
|
||||||
|
author = input:sub(j + 1)
|
||||||
|
debug("get_book() Title by Author detected:", title, author)
|
||||||
|
else
|
||||||
|
local i = input:find(" (author)")
|
||||||
|
if i then
|
||||||
|
author = input:sub(1, i - 1)
|
||||||
|
end
|
||||||
|
local i = input:find(" (series)")
|
||||||
|
series = input:sub(1, i - 1)
|
||||||
|
if i then
|
||||||
|
end
|
||||||
|
local i = input:find(" (genre)")
|
||||||
|
genre = input:sub(1, i - 1)
|
||||||
|
if i then
|
||||||
|
end
|
||||||
|
|
||||||
|
if not (author or series or genre) then
|
||||||
|
title = input
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
local book
|
||||||
|
for i = 1, #data.books do
|
||||||
|
local current = data.books[i]
|
||||||
|
if title then
|
||||||
|
if current.title == title then
|
||||||
|
if author then
|
||||||
|
if current.author and current.author == author then
|
||||||
|
book = current
|
||||||
|
break
|
||||||
|
end
|
||||||
|
else
|
||||||
|
book = current
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif author and current.author == author then
|
||||||
|
book = current
|
||||||
|
break
|
||||||
|
elseif series and current.series == series then
|
||||||
|
book = current
|
||||||
|
break
|
||||||
|
elseif genre and current.genre == genre then
|
||||||
|
book = current
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
if not book then
|
||||||
|
book = {
|
||||||
|
title = title,
|
||||||
|
author = author,
|
||||||
|
series = series,
|
||||||
|
genre = genre,
|
||||||
|
progress = 0,
|
||||||
|
priority = 0,
|
||||||
|
}
|
||||||
|
data.books[#data.books + 1] = book
|
||||||
|
end
|
||||||
|
|
||||||
|
-- this may or may not stay relevant to this placement
|
||||||
|
return update_progress_prompt(book)
|
||||||
|
end
|
||||||
|
|
||||||
|
local update_book = function(book)
|
||||||
|
-- currently just a wrapper, because I'm not sure if this will stay exactly consistent with that
|
||||||
|
return update_progress_prompt(book)
|
||||||
|
end
|
||||||
|
|
||||||
local import_json = function(data, file_name)
|
local import_json = function(data, file_name)
|
||||||
import = load_json(file_name)
|
import = load_json(file_name)
|
||||||
if import.books then
|
if import.books then
|
||||||
@@ -170,49 +303,12 @@ local import_json = function(data, file_name)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
save_json(default_file, data)
|
-- we must rely on parent function to save
|
||||||
end
|
|
||||||
|
|
||||||
local get_display_name = function(book)
|
|
||||||
local result = ""
|
|
||||||
|
|
||||||
if book.title then
|
|
||||||
result = book.title
|
|
||||||
if book.author then
|
|
||||||
result = result .. " by " .. book.author
|
|
||||||
end
|
|
||||||
elseif book.author then
|
|
||||||
result = book.author .. " (author)"
|
|
||||||
end
|
|
||||||
|
|
||||||
if book.series then
|
|
||||||
if #result > 0 then
|
|
||||||
result = result .. " (" .. book.series .. ")"
|
|
||||||
else
|
|
||||||
result = book.series .. " (series)"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if book.genre then
|
|
||||||
if #result > 0 then
|
|
||||||
result = result .. " (" .. book.genre .. ")"
|
|
||||||
else
|
|
||||||
result = book.genre .. " (genre)"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if book.pages then
|
|
||||||
result = result .. " ~" .. math.floor(book.progress * book.pages) .. "/" .. book.pages .. " pages read"
|
|
||||||
elseif book.progress > 0 and book.progress < 1 then
|
|
||||||
result = result .. " ~" .. math.floor(book.progress * 100) .. "% read"
|
|
||||||
end
|
|
||||||
|
|
||||||
return result
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local select_books = function(preset_name)
|
local get_books_by_preset = function(data, preset_name)
|
||||||
local selected_books = {}
|
local selected_books = {}
|
||||||
for i = 1, #data.books do
|
for i = 1, #data.books do
|
||||||
local book = data.books[i]
|
local book = data.books[i]
|
||||||
@@ -247,7 +343,7 @@ local launch = function(file_name)
|
|||||||
save_json(file_name, data)
|
save_json(file_name, data)
|
||||||
end
|
end
|
||||||
|
|
||||||
local selected_books = select_books("launch")
|
local selected_books = get_books_by_preset(data, "launch")
|
||||||
|
|
||||||
return data, selected_books
|
return data, selected_books
|
||||||
end
|
end
|
||||||
@@ -257,22 +353,32 @@ local main = function(data, selected_books)
|
|||||||
local book = selected_books[i]
|
local book = selected_books[i]
|
||||||
print(" " .. (i == 10 and "0" or i) .. ". " .. get_display_name(book))
|
print(" " .. (i == 10 and "0" or i) .. ". " .. get_display_name(book))
|
||||||
end
|
end
|
||||||
print("Commands: " .. (#selected_books > 0 and "[0-9] to modify a book's progress. " or "") .. "[i <file>] to import from a JSON file. Enter nothing to exit.")
|
print("Commands: " .. (#selected_books > 0 and "[0-9] to modify a book's progress. " or "") .. "[i <file>] to import from a JSON")
|
||||||
|
print(" file. Enter nothing to exit.")
|
||||||
print(" Adding/Selecting: Title OR Title by Author OR \"Name (type)\" for other types.")
|
print(" Adding/Selecting: Title OR Title by Author OR \"Name (type)\" for other types.")
|
||||||
-- TODO define what can go in <book> and how it will be interpreted
|
|
||||||
-- TODO actually implement modifying progress and adding books
|
|
||||||
-- TODO implement elo ranking
|
-- TODO implement elo ranking
|
||||||
-- TODO type title to add or edit an extant book (this is better than the "a" command I wrote above)
|
|
||||||
|
|
||||||
local input = io.read("*line")
|
local input = io.read("*line")
|
||||||
if #input == 0 then os.exit(0) end
|
local numerical = tonumber(input)
|
||||||
|
|
||||||
if input:sub(1, 1) == "i" then
|
if #input == 0 then
|
||||||
|
os.exit(0)
|
||||||
|
elseif numerical and (numerical >= 0 and numerical <= 9) then
|
||||||
|
update_book(selected_books[numerical])
|
||||||
|
elseif input:sub(1, 1) == "i" then
|
||||||
import_json(data, input:sub(3))
|
import_json(data, input:sub(3))
|
||||||
|
else -- assumed we are trying to add/select a book
|
||||||
|
get_book(data, input)
|
||||||
|
-- but that just returns a book, we need to DO something with it ??
|
||||||
|
-- right now, it demands a progress update;
|
||||||
|
-- TODO add mode selection to select and update vs select only mode that THEN asks what to do?
|
||||||
|
-- no? these are completely separate modes, there should be quick add, update progress, rank mode, add pages mode, etc
|
||||||
end
|
end
|
||||||
|
|
||||||
|
save_json(default_file, data) -- this assumes it is equivalent with how launch() is called
|
||||||
end
|
end
|
||||||
|
|
||||||
local data, selected_books = launch(default_file)
|
local data, selected_books = launch(default_file) -- the file name doesn't make it to main :\
|
||||||
while true do
|
while true do
|
||||||
main(data, selected_books)
|
main(data, selected_books)
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user