John Smith commited on 2022-232 00:56:32
Showing 2 changed files, with 37 additions and 3 deletions.
Adds option "l" to the main utility, which sets it to detect and present leeches found in the active deckfile, measured as prompts with >= 8 recorded failures/lapses (excluding suspended prompts, as facilitated in a9f5760), sorted in order of decreasing leech-badness.
| ... | ... |
@@ -116,6 +116,13 @@ local function isatty() |
| 116 | 116 |
return succ |
| 117 | 117 |
end |
| 118 | 118 |
|
| 119 |
+--[[ |
|
| 120 |
+ return number indicating how much of a leech the prompt is |
|
| 121 |
+]] |
|
| 122 |
+local function badness(pr) |
|
| 123 |
+ return pr.fail / (pr.fail + pr.succ) * math.log(pr.fail) |
|
| 124 |
+end |
|
| 125 |
+ |
|
| 119 | 126 |
--[[ |
| 120 | 127 |
check action based on first command-line argument; |
| 121 | 128 |
if nothing valid given, default to help |
| ... | ... |
@@ -123,7 +130,7 @@ end |
| 123 | 130 |
local action = nil |
| 124 | 131 |
if arg[1] then |
| 125 | 132 |
local fc = arg[1]:sub(1, 1) |
| 126 |
- if fc == "a" or fc == "h" or fc == "r" or fc == "s" then |
|
| 133 |
+ if fc == "a" or fc == "h" or fc == "l" or fc == "r" or fc == "s" then |
|
| 127 | 134 |
action = fc |
| 128 | 135 |
else |
| 129 | 136 |
action = "h" |
| ... | ... |
@@ -225,9 +232,31 @@ if action == "a" then |
| 225 | 232 |
-- Help |
| 226 | 233 |
elseif action == "h" then |
| 227 | 234 |
io.write(string.format( |
| 228 |
- "Usage: %s ACTION\n\nACTION may be one of\n\t(a)dd card\n\t(h)elp\n\t(r)eview session\n\t(s)tatistics\n", |
|
| 235 |
+ "Usage: %s ACTION\n\nACTION may be one of\n\t(a)dd card\n\t(h)elp\n\t(l)eech search\n\t(r)eview session\n\t(s)tatistics\n", |
|
| 229 | 236 |
arg[0] |
| 230 | 237 |
)) |
| 238 |
+-- Leech search |
|
| 239 |
+elseif action == "l" then |
|
| 240 |
+ local deck = loader.load(deckfname, config) |
|
| 241 |
+ if deck then |
|
| 242 |
+ local leechqueue = {}
|
|
| 243 |
+ for i, cg in ipairs(deck) do |
|
| 244 |
+ for j, pr in ipairs(cg) do |
|
| 245 |
+ if pr.fail > 8 and pr.delay >= 0 then |
|
| 246 |
+ table.insert(leechqueue, { i, j })
|
|
| 247 |
+ end |
|
| 248 |
+ end |
|
| 249 |
+ end |
|
| 250 |
+ table.sort(leechqueue, function(a, b) |
|
| 251 |
+ return badness(deck[a[1]][a[2]]) > badness(deck[b[1]][b[2]]) |
|
| 252 |
+ end) |
|
| 253 |
+ io.write(string.format("Detected %d leeches:\n", #leechqueue))
|
|
| 254 |
+ for _, ij in ipairs(leechqueue) do |
|
| 255 |
+ io.write(string.format("%s\n", deck[ij[1]][ij[2]]))
|
|
| 256 |
+ end |
|
| 257 |
+ else |
|
| 258 |
+ io.write("Failed to load deck\n")
|
|
| 259 |
+ end |
|
| 231 | 260 |
-- Review session |
| 232 | 261 |
elseif action == "r" then |
| 233 | 262 |
local deck |
| ... | ... |
@@ -29,7 +29,12 @@ function Prompt:new(pt, ca, rts, rd, sc, fc, ct, ez) |
| 29 | 29 |
end |
| 30 | 30 |
|
| 31 | 31 |
function Prompt:__tostring() |
| 32 |
- return string.format("\"%s\" (\"%s\") %d -> %d+%d*%d %d/%d", self.text, self.ans, self.created, self.time, self.delay, self.ease, self.succ, self.fail)
|
|
| 32 |
+ return string.format( |
|
| 33 |
+ "\"%s\" (\"%s\") %d -> %d+%d*%f %d/%d", |
|
| 34 |
+ self.text, self.ans, self.created or 0, |
|
| 35 |
+ self.time, math.floor(self.delay), self.ease, |
|
| 36 |
+ self.succ, self.fail |
|
| 37 |
+ ) |
|
| 33 | 38 |
end |
| 34 | 39 |
|
| 35 | 40 |
--[[ |
| 36 | 41 |