DKL9 GitList
Repositories
DKL9 home
memoire
Code
Commits
Branches
Tags
Search
Tree:
4bf99c8
Branches
Tags
master
memoire
review.lua
Greatly improve scheduling algorithm
John Smith
commited
4bf99c8
at 2022-206 08:31:53
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 (returns boolean) if `Prompt` `prompt` should be reviewed now ]] local function should(prompt) return os.time() - (prompt.time or 0) >= (prompt.delay or 0) end --[[ returns a shuffled version of the table, destroying the table in-place adapted from https://stackoverflow.com/q/55192727 ]] local function shuffle(t) local ret = {} local ci = 1 while #t > 0 do local ri = math.random(1, #t) ret[ci] = t[ri] table.remove(t, ri) ci = ci + 1 end return ret 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 if should(pr) and ff(pr) then table.insert(ctrt, { i, j }) end end end ctrt = shuffle(ctrt) return ctrt end return { schedule = schedule, update = update, should = should, list = toreviewlist }