Initial commit
This commit is contained in:
@@ -0,0 +1,68 @@
|
||||
local SQ3 = require("lua-ljsqlite3/init")
|
||||
local DataStorage = require("datastorage")
|
||||
local logger = require("logger")
|
||||
local db_location = DataStorage:getSettingsDir() .. "/statistics.sqlite3"
|
||||
local Reader = {}
|
||||
local OVERLAP_SECONDS = 24 * 60 * 60
|
||||
|
||||
function Reader.bookData()
|
||||
local conn = SQ3.open(db_location)
|
||||
local sql = "SELECT id,title,authors,notes,last_open,highlights,pages,series,language,md5,total_read_time,total_read_pages FROM book"
|
||||
local result, rows = conn:exec(sql)
|
||||
local books = {}
|
||||
for i = 1, rows do
|
||||
table.insert(books, {
|
||||
id = tonumber(result[1][i]), title = result[2][i], authors = result[3][i],
|
||||
notes = tonumber(result[4][i]), last_open = tonumber(result[5][i]), highlights = tonumber(result[6][i]),
|
||||
pages = tonumber(result[7][i]), series = result[8][i], language = result[9][i], md5 = result[10][i],
|
||||
total_read_time = tonumber(result[11][i]), total_read_pages = tonumber(result[12][i]),
|
||||
})
|
||||
end
|
||||
conn:close()
|
||||
return books
|
||||
end
|
||||
|
||||
local function md5_by_id(books)
|
||||
local map = {}
|
||||
for _, b in ipairs(books) do map[b.id] = b.md5 end
|
||||
return map
|
||||
end
|
||||
|
||||
local function flush_statistics()
|
||||
local ok, ReaderUI = pcall(require, "apps/reader/readerui")
|
||||
if ok and ReaderUI and ReaderUI.instance and ReaderUI.instance.statistics and ReaderUI.instance.statistics.is_doc then
|
||||
pcall(function() ReaderUI.instance.statistics:insertDB() end)
|
||||
end
|
||||
end
|
||||
|
||||
-- The first sync sends the complete statistics history. Successful syncs store a
|
||||
-- high-water mark on the reader; later syncs only re-send a one-day overlap.
|
||||
-- kovi de-duplicates identical page_stat_data events, so the overlap protects
|
||||
-- against clock/order edge cases without double-counting reading time.
|
||||
function Reader.progressData(sync_cursor, books)
|
||||
flush_statistics()
|
||||
books = books or Reader.bookData()
|
||||
local map = md5_by_id(books)
|
||||
local cursor = math.max(0, tonumber(sync_cursor) or 0)
|
||||
local threshold = math.max(0, cursor - OVERLAP_SECONDS)
|
||||
local conn = SQ3.open(db_location)
|
||||
local sql = "SELECT id_book,page,start_time,duration,total_pages FROM page_stat_data"
|
||||
if threshold > 0 then sql = sql .. " WHERE start_time >= " .. tostring(math.floor(threshold)) end
|
||||
local result, rows = conn:exec(sql)
|
||||
local stats = {}
|
||||
local device_id = G_reader_settings:readSetting("device_id")
|
||||
for i = 1, rows do
|
||||
local md5 = map[tonumber(result[1][i])]
|
||||
if md5 then
|
||||
table.insert(stats, {
|
||||
book_md5 = md5, page = tonumber(result[2][i]), start_time = tonumber(result[3][i]),
|
||||
duration = tonumber(result[4][i]), total_pages = tonumber(result[5][i]), device_id = device_id,
|
||||
})
|
||||
else
|
||||
logger.warn("[kovi] statistic row references unknown book")
|
||||
end
|
||||
end
|
||||
conn:close()
|
||||
return stats
|
||||
end
|
||||
return Reader
|
||||
Reference in New Issue
Block a user