mostly implemented an import system
This commit is contained in:
@@ -3,18 +3,14 @@ CLI tracker to prioritize your limited time by ELO ranking media.
|
|||||||
|
|
||||||
## Initial Ideas
|
## Initial Ideas
|
||||||
- [ ] Mark books read/unread/in-progress.
|
- [ ] Mark books read/unread/in-progress.
|
||||||
- [ ] 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.
|
- [ ] Track books by title, author, and series. Default is to recognize "by" or "(series)" and automatically sort into relevant fields.
|
||||||
- [ ] 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.
|
||||||
- [ ] 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.
|
||||||
|
|
||||||
I think the opening UI should be to display the top 10 books in-progress (sort order customizable by user), where pressing a number key
|
|
||||||
allows the user to immediately enter an updated progress. Additional alphabetic keys are an option to access other features. This way
|
|
||||||
tracker use is near frictionless. (0 maps to 10)
|
|
||||||
|
|
||||||
## Contributions
|
## Contributions
|
||||||
|
|
||||||
@@ -30,6 +26,7 @@ Licensing? I don't care. Do whatever you want. IP rights are stupid.
|
|||||||
"title": "Title",
|
"title": "Title",
|
||||||
"author": "Author",
|
"author": "Author",
|
||||||
"series": "Series",
|
"series": "Series",
|
||||||
|
"genre": "Fiction",
|
||||||
"pages": 100,
|
"pages": 100,
|
||||||
"priority": 0,
|
"priority": 0,
|
||||||
"progress": 0.5,
|
"progress": 0.5,
|
||||||
@@ -37,14 +34,18 @@ Licensing? I don't care. Do whatever you want. IP rights are stupid.
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
- `title`, `author`, `series`, `pages`, and `hidden` are optional.
|
- `title`, `author`, `series`, `pages`, `genre`, and `hidden` are optional.
|
||||||
- At least one of `title`, `author`, or `series` must be defined.
|
- At least one of `title`, `author`, `series`, or `genre` must be defined.
|
||||||
- `priority` is the ELO ranking, initializing to `0`.
|
- `priority` is the ELO ranking, initializing to `0`.
|
||||||
- `progress` represents read/unread/in-progress status. `0` is unread, `1` is
|
- `progress` represents read/unread/in-progress status. `0` is unread, `1` is
|
||||||
read, and anything in-between in a percentage of progress.
|
read, and anything in-between in a percentage of progress.
|
||||||
- `hidden` is undefined or `true` to hide a book from ALL of the interface
|
- `hidden` is undefined or `true` to hide a book from ALL of the interface
|
||||||
without deleting its data.
|
without deleting its data.
|
||||||
|
|
||||||
|
Despite the script supporting otherwise, I highly recommend only using this for
|
||||||
|
*specific book titles*. In my experience, using entries representing multiple
|
||||||
|
books makes it more difficult to prioritize and use.
|
||||||
|
|
||||||
## Why "Asymptome" ?
|
## Why "Asymptome" ?
|
||||||
A combination of asymptote - because you will die before you finish your reading
|
A combination of asymptote - because you will die before you finish your reading
|
||||||
list, always getting closer but never arriving - and tome.
|
list, always getting closer but never arriving - and tome.
|
||||||
|
|||||||
Regular → Executable
+143
-1
@@ -66,6 +66,13 @@ local filters = {
|
|||||||
end
|
end
|
||||||
return false
|
return false
|
||||||
end,
|
end,
|
||||||
|
exclude_series = function(book)
|
||||||
|
if book.hidden then return false end
|
||||||
|
if book.series and not (book.title or book.author) then
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
return true
|
||||||
|
end,
|
||||||
}
|
}
|
||||||
|
|
||||||
local sort_orders
|
local sort_orders
|
||||||
@@ -84,7 +91,7 @@ sort_orders = {
|
|||||||
end,
|
end,
|
||||||
most_pages_remaining = function(A, B)
|
most_pages_remaining = function(A, B)
|
||||||
if not (A.pages and B.pages) then -- if pages is unknown for both, fallback to percentage
|
if not (A.pages and B.pages) then -- if pages is unknown for both, fallback to percentage
|
||||||
return A.progress > B.progress
|
return A.progress < B.progress
|
||||||
end
|
end
|
||||||
local average_page_count = data.total_pages / #data.books
|
local average_page_count = data.total_pages / #data.books
|
||||||
local a = (A.pages or average_page_count) - (A.pages or average_page_count) * A.progress
|
local a = (A.pages or average_page_count) - (A.pages or average_page_count) * A.progress
|
||||||
@@ -96,6 +103,47 @@ 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- TODO this procedural code should be split into functions where feasible
|
||||||
|
|
||||||
local data
|
local data
|
||||||
if path_exists(default_file) then
|
if path_exists(default_file) then
|
||||||
data = load_json(default_file)
|
data = load_json(default_file)
|
||||||
@@ -115,4 +163,98 @@ else
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
save_json(default_file, data)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- main menu
|
||||||
|
-- TODO should be a loop/function to return to
|
||||||
|
|
||||||
|
local selected_books = {}
|
||||||
|
for i = 1, #data.books do
|
||||||
|
local book = data.books[i]
|
||||||
|
if filters[data.defaults.launch.filter](book) then
|
||||||
|
selected_books[#selected_books + 1] = book
|
||||||
|
end
|
||||||
|
end
|
||||||
|
table.sort(selected_books, sort_orders[data.defaults.launch.sort])
|
||||||
|
|
||||||
|
for i = 1, math.min(10, #selected_books) do
|
||||||
|
local book = selected_books[i]
|
||||||
|
print(" " .. (i == 10 and "0" or i) .. ". " .. get_display_name(book))
|
||||||
|
end
|
||||||
|
print("Commands: " .. (#selected_books > 0 and "[0-9] to modify a book's progress. " or "") .. "[a <book>] to add a book. [i <file>] to import from a JSON file.")
|
||||||
|
-- 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 type title to add or edit an extant book (this is better than the "a" command I wrote above)
|
||||||
|
|
||||||
|
local input = io.read("*line")
|
||||||
|
|
||||||
|
if input:sub(1, 1) == "i" then
|
||||||
|
-- TODO this should all be broken out into a function
|
||||||
|
import = load_json(input:sub(3))
|
||||||
|
if import.books then
|
||||||
|
|
||||||
|
for i = 1, #import.books do
|
||||||
|
data.books[#data.books + 1] = import.books[i]
|
||||||
|
-- TODO detect and ignore duplicates (would be better to provide user an option for what to do with duplicates)
|
||||||
|
-- default should accept highest progress of duplicates?
|
||||||
|
end
|
||||||
|
|
||||||
|
else -- assume we are importing from decider.lua's format
|
||||||
|
for title, value in pairs(import) do
|
||||||
|
local run = function()
|
||||||
|
local book = { -- minimum required book data strucutre
|
||||||
|
priority = 0,
|
||||||
|
progress = 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
local i = title:find(" %(.-series.-%)")
|
||||||
|
if i then
|
||||||
|
book.series = title:sub(1, i - 1)
|
||||||
|
end
|
||||||
|
local i = title:find(" %(trilogy%)")
|
||||||
|
if i then
|
||||||
|
book.series = title:sub(1, i - 1)
|
||||||
|
end
|
||||||
|
local i = title:find(" %(.-author%)")
|
||||||
|
if i then
|
||||||
|
book.author = title:sub(1, i - 1)
|
||||||
|
end
|
||||||
|
local i = title:find(" %(genre%)")
|
||||||
|
if i then
|
||||||
|
print("Skipping import of \"" .. title .. "\"")
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
if not (book.series or book.author) then
|
||||||
|
-- TODO detect " by " and split if needed
|
||||||
|
book.title = title
|
||||||
|
end
|
||||||
|
|
||||||
|
if type(value) == "number" then
|
||||||
|
book.priority = value
|
||||||
|
|
||||||
|
else
|
||||||
|
book.priority = value.score
|
||||||
|
|
||||||
|
if value.done == true then
|
||||||
|
book.progress = 1
|
||||||
|
elseif value.done == false then
|
||||||
|
book.hidden = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO detect duplicates before adding them
|
||||||
|
data.books[#data.books + 1] = book
|
||||||
|
end
|
||||||
|
run()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
save_json(default_file, data)
|
||||||
|
|
||||||
|
-- TODO there should be a sort of main menu I am returned to
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user