DKL9 GitList
Repositories
DKL9 home
memoire
Code
Commits
Branches
Tags
Search
Tree:
735ea73
Branches
Tags
master
memoire
review.lua
Improve review prioritisation sort
John Smith
commited
735ea73
at 2023-35 11:52:49
review.lua
Blame
History
Raw
--[[ stuff to help with the review mechanics ]] --[[ determines the delay until next review (in seconds) when `Prompt` `prompt` is reviewed at timestamp `revtime` with review success `revsucc` ]] local function schedule(prompt, revtime, revsucc, conf) if revsucc and revsucc > 0 then local ad = revtime - (prompt.time or revtime) local adm = ad + math.max(40000 - 0.5 * ad, 0) -- SM2, as explained by Bjornstad -- https://controlaltbackspace.org/memory/spaced-repetition-from-the-ground-up/ if revsucc < 0.8 then return (conf:get("HardRatio") or 1.2) * revsucc * 2 * adm else return prompt.ease * (1 + 2 * ((conf:get("EasyRatio") or 1.3) - 1) * (revsucc - 1)) * adm end else return 15 end end --[[ manipulates `Prompt` `prompt` in-place as it should be when reviewed at timestamp `revtime` with review success `revsucc` ]] local function update(prompt, revtime, revsucc, conf) if revsucc and revsucc > 0 then prompt.succ = (prompt.succ or 0) + 1 else prompt.fail = (prompt.fail or 0) + 1 end -- allowed random variation, as a fraction of the "optimal" duration local ARV = conf:get("AllowedRandomVariation") or 0.1 prompt.delay = schedule(prompt, revtime, revsucc, conf) * ((1 - ARV) + 2 * ARV * math.random()) prompt.ease = prompt.ease + ({ -0.2, -0.15, 0, 0.15 })[2 * revsucc + 1] prompt.time = revtime end --[[ checks if `Prompt` `prompt` should be reviewed now, returning `false` if not and a number to indicate urgency if it should ]] local function should(prompt) local ct = os.time() if not prompt.delay then return -1 end if prompt.delay >= 0 and ct - (prompt.time or 0) >= (prompt.delay or 0) then return (ct - (prompt.time or 0)) / prompt.delay / prompt.ease + 0.2 * math.random() end return false end --[[ shuffles a table in-place, intentionally biased to keep the list in a roughly-similar order to how it was originally (but so that the list may deviate more towards the end) ]] local function biasedshuffle(t) for i = 1, (#t-1) do if math.random() < (i / #t)^0.5 then local s = t[i] t[i] = t[i + 1] t[i + 1] = s end end end local function alwaystrue(x) return true end --[[ returns a table of pairs of integers to index the deck to get prompts to be reviewed now; prompts are shuffled in order if a filter function is provided, filters the list accordingly, calling the filter function on each `Prompt` ]] local function toreviewlist(deck, filter) local ctrt = {} local ff = filter or alwaystrue for i, cg in ipairs(deck) do for j, pr in ipairs(cg) do local sc = should(pr) if sc and ff(pr) then table.insert(ctrt, { i, j, sc or 0 }) end end end table.sort(ctrt, function(a, b) return a[3] > b[3] end) return ctrt end return { schedule = schedule, update = update, should = should, list = toreviewlist }