fix: remember ratings in 5-star space — odd server ratings no longer drift up
Change-detection compared a derived 10-scale value against a remembered raw 10-scale value, but the summary can only hold whole stars: a pulled server 9 (4.5 stars) applied as 5 stars, remembered 9, and the next close-push derived 10 ≠ 9 and silently rounded the server rating up. Every odd rating (9/7/5/3/1) drifted one half-star on the first close after a pull. The remembered state is now the star count actually written (5-space); the POST fires only when the star count itself changed, converting at the boundary. koreader's display is an array-index lookup (a fractional rating would render nil), so whole stars are the only safe memory. getMetaSyncState normalizes any 10-space value an older build wrote. Verified: s → stars → 2s → stars is stable for all s in 1..10.
This commit is contained in:
1 parent
001628f2a2
commit
b0ff330b0f
1 file changed
+25
-13
@@ -1980,6 +1980,11 @@ function Bookhoard:getMetaSyncState(book_key)
|
|||||||
if type(state) ~= "table" then
|
if type(state) ~= "table" then
|
||||||
state = {}
|
state = {}
|
||||||
self.settings.meta_sync_state[book_key] = state
|
self.settings.meta_sync_state[book_key] = state
|
||||||
|
elseif type(state.rating) == "number" and state.rating > 5 then
|
||||||
|
-- Settings written by the first bridge build remembered ratings
|
||||||
|
-- in 10-space; normalize once. 10-space memory cannot survive
|
||||||
|
-- the round-trip (odd values would re-round at every push).
|
||||||
|
state.rating = rating10to5(state.rating)
|
||||||
end
|
end
|
||||||
return state
|
return state
|
||||||
end
|
end
|
||||||
@@ -2007,20 +2012,24 @@ function Bookhoard:pullBookMeta(interactive)
|
|||||||
if self.settings.sync_ratings then
|
if self.settings.sync_ratings then
|
||||||
local ok, result = api:getRating(ref)
|
local ok, result = api:getRating(ref)
|
||||||
if ok and result and not result.error then
|
if ok and result and not result.error then
|
||||||
local server10 = result.rating
|
-- Compare in 5-STAR SPACE. The summary cannot represent odd
|
||||||
local server5 = rating10to5(server10)
|
-- server values (9 = 4.5 stars), so remembering the raw
|
||||||
|
-- 10-scale would make every pulled odd rating look "changed"
|
||||||
|
-- at push time (9 remembered → 5★ local → push derives 10)
|
||||||
|
-- and silently round it up. Remember the star count we
|
||||||
|
-- actually wrote; conversion to 10 happens only at the POST.
|
||||||
|
local server5 = rating10to5(result.rating)
|
||||||
local local5 = summary.rating or 0
|
local local5 = summary.rating or 0
|
||||||
local local10 = rating5to10(local5) or 0
|
local remembered5 = remembered.rating or 0
|
||||||
local remembered10 = remembered.rating or 0
|
if server5 ~= local5 and remembered5 == local5 then
|
||||||
if server10 ~= nil and server10 ~= local10 and remembered10 == local10 then
|
|
||||||
-- Server moved, koreader didn't → apply.
|
-- Server moved, koreader didn't → apply.
|
||||||
summary.rating = server5
|
summary.rating = server5
|
||||||
self:writeSummary(summary)
|
self:writeSummary(summary)
|
||||||
remembered.rating = server10
|
remembered.rating = server5
|
||||||
table.insert(applied, T(_("rating %1/5"), server5))
|
table.insert(applied, T(_("rating %1/5"), server5))
|
||||||
elseif server10 ~= nil and server10 == local10 and remembered10 ~= local10 then
|
elseif server5 == local5 and remembered5 ~= local5 then
|
||||||
-- Values agree but our memory is stale; just re-sync memory.
|
-- Values agree but our memory is stale; just re-sync memory.
|
||||||
remembered.rating = server10
|
remembered.rating = server5
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -2068,12 +2077,15 @@ function Bookhoard:pushBookMeta(interactive)
|
|||||||
local api = self:getAPI()
|
local api = self:getAPI()
|
||||||
|
|
||||||
if self.settings.sync_ratings then
|
if self.settings.sync_ratings then
|
||||||
local local10 = rating5to10(summary.rating) or 0
|
-- 5-star space comparison (see the pull): the POST only fires
|
||||||
local remembered10 = remembered.rating or 0
|
-- when the star count itself changed; conversion happens at the
|
||||||
if local10 ~= remembered10 then
|
-- boundary (nil/0 → server clears).
|
||||||
local ok, result = api:setRating(ref, local10)
|
local local5 = summary.rating or 0
|
||||||
|
local remembered5 = remembered.rating or 0
|
||||||
|
if local5 ~= remembered5 then
|
||||||
|
local ok, result = api:setRating(ref, rating5to10(local5) or 0)
|
||||||
if ok and result and not result.error then
|
if ok and result and not result.error then
|
||||||
remembered.rating = local10
|
remembered.rating = local5
|
||||||
table.insert(pushed, _("rating"))
|
table.insert(pushed, _("rating"))
|
||||||
else
|
else
|
||||||
errors = errors + 1
|
errors = errors + 1
|
||||||
|
|||||||
Reference in new issue
Block a user