DKL9 GitList
Repositories
DKL9 home
memoire
Code
Commits
Branches
Tags
Search
Tree:
3949c09
Branches
Tags
master
memoire
src
review.lua
Move Lua source code into src/ directory
John Smith
commited
3949c09
at 2023-133 18:56:28
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 --[[ rates the importance of `Prompt` `prompt` as an additive bias based on the rules given in `conf` ]] local function importance(prompt, conf) pt = conf["PriorityText"] or {} pb = conf["PriorityBias"] or {} s = 0 for i, t in ipairs(pt) do if prompt:spt():find(t) then s = s + pb[i] end end return s 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, conf) 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 / (prompt.succ + 1) + importance(prompt, conf) + 0.1 * math.random() end return false 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, conf, 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, conf) 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 --[[ gets the score (again/hard/good/easy/correction) from a string by first character scores are numbers, higher is easier, -1 is correction ]] local function succfromstr(s) local f = s:sub(1, 1):lower() if f == "0" or f == "a" then return 0 elseif f == "1" or f == "h" then return 0.5 elseif f == "2" or f == "g" then return 1 elseif f == "3" or f == "e" then return 1.5 elseif f == "-" or f == "c" then return -1 end return 1 end return { schedule = schedule, update = update, should = should, list = toreviewlist, succfromstr = succfromstr }