Improves Prompt and recrw modules
John Smith

John Smith commited on 2021-312 21:47:52
Showing 2 changed files, with 39 additions and 10 deletions.


* added methods `Prompt:spt` and `Prompt:torec` for data conversion
* fixed bug in `recrw.write`
* clarified comments
... ...
@@ -1,13 +1,16 @@
1 1
 --[[
2 2
     a prompt consists of prompt text (with an answer-insertion point),
3 3
     a correct answer, the review timestamp, and the review delay
4
+
5
+    timestamps are seconds from the Unix epoch
6
+    review delay is in seconds
4 7
 ]]
5 8
 
6 9
 local Prompt = {}
7 10
 Prompt.__index = Prompt
8 11
 
9 12
 --[[
10
-    the answer-insertion point is indicated with a %A in the prompt text
13
+    the answer-insertion point is indicated with a "%A" in the prompt text
11 14
 ]]
12 15
 function Prompt:new(pt, ca, rts, rd)
13 16
     local o = {}
... ...
@@ -24,21 +27,28 @@ function Prompt:__tostring()
24 27
 end
25 28
 
26 29
 --[[
27
-    extracts prompts from a record-based deck
28
-    returns (on success) a table of Prompts
29
-    returns (on failure) nil
30
+    derive the `PromptText` used to create this `Prompt`
31
+]]
32
+function Prompt:spt()
33
+    return self.text:gsub("%%A", "{" .. self.ans .. "}")
34
+end
35
+
36
+--[[
37
+    extracts `Prompt`s from a record-based deck
38
+    returns a table of tables of `Prompt`s
30 39
 ]]
31 40
 function Prompt:fromrecs(recs)
32 41
     local ret = {}
33
-    for _i, rec in ipairs(recs) do
34
-        -- only bother with records with PromptText
42
+    for i, rec in ipairs(recs) do
43
+        -- only bother with records with `PromptText`
35 44
         if rec.PromptText then
45
+            ret[i] = {}
36 46
             local opt = rec.PromptText[1]
37 47
             local m, n = opt:find "%{[^%}]+%}"
38 48
             local ctr = 1
39 49
             while m do
40
-                local mpt = (opt:sub(1, m - 1) .. "%A" .. opt:sub(n + 1)):gsub("%{([^%}]+)%}", "%1")
41
-                table.insert(ret, Prompt:new(mpt, opt:sub(m + 1, n - 1), (rec.LastReview or {})[ctr], (rec.LastDelay)[ctr]))
50
+                local mpt = opt:sub(1, m - 1) .. "%A" .. opt:sub(n + 1)
51
+                table.insert(ret[i], Prompt:new(mpt, opt:sub(m + 1, n - 1), (rec.LastReview or {})[ctr], (rec.LastDelay)[ctr]))
42 52
                 m, n = opt:find("%{[^%}]+%}", n)
43 53
                 ctr = ctr + 1
44 54
             end
... ...
@@ -47,4 +57,23 @@ function Prompt:fromrecs(recs)
47 57
     return ret
48 58
 end
49 59
 
60
+--[[
61
+    serialises an ordered table of `Prompt`s derived from the same `PromptText` to a record
62
+    returns (on success) a table mapping labels to value-lists
63
+    returns (on failure) nil
64
+]]
65
+function Prompt:torec(prompts)
66
+    local fspt = prompts[1]:spt()
67
+    local ret = { PromptText = { fspt }, LastReview = {}, LastDelay = {} }
68
+    for i, pr in ipairs(prompts) do
69
+        if pr:spt() ~= fspt then
70
+            -- not from the same `PromptText`
71
+            return nil
72
+        end
73
+        ret.LastReview[i] = pr.time
74
+        ret.LastDelay[i] = pr.delay
75
+    end
76
+    return ret
77
+end
78
+
50 79
 return Prompt
... ...
@@ -8,7 +8,7 @@
8 8
 
9 9
 --[[
10 10
     converts text from a Recfile into a sequence of records
11
-    returns (on success) a table of tables of label-value-list pairs
11
+    returns (on success) a table of tables of pairs of labels and value-lists
12 12
     returns (on failure) nil
13 13
 ]]
14 14
 local function text2recs(str)
... ...
@@ -89,7 +89,7 @@ local function recs2text(recs)
89 89
     for i, rec in ipairs(recs) do
90 90
         for label, vl in pairs(rec) do
91 91
             for j, value in ipairs(vl) do
92
-                ret = ret .. string.format("\n%s: %s", label, value:gsub("\n", "\n+ "))
92
+                ret = ret .. string.format("\n%s: %s", label, tostring(value):gsub("\n", "\n+ "))
93 93
             end
94 94
         end
95 95
         ret = ret .. "\n"
96 96