ref: f67009a6af1a85ec5aac543ca3e0e06db1911d37
dir: /bin/sr3/
#!/bin/awk -f
# tweaked version of supermemo 2 algorithm
# usage: sr3 deck > newdeck
# deck contains only card metadata.
# new cards are initialized with the values: 2.5 0 0 0 filepath.
# the script evaluates due cards, shuffles them, and shows them until all
# responses are graded >= 4, then writes a new deck db to stdout.
# card format is up to the user.
# tweaks:
# - new due date takes into account missed days
function setef(n, q){
ef = c[n,"ef"] + (0.1 - (5 - q) * (0.08 + (5 - q) * 0.02))
if(ef < 1.3)
ef = 1.3
else if(ef > 2.5)
ef = 2.5
c[n,"ef"] = ef
}
function setdue(n, t, dt, day){
dt = time - c[n,"due"]
day = 60 * 60 * 24
if(c[n,"nrep"] == 1)
dt = 1 * day
else if(c[n,"nrep"] == 2)
dt = 6 * day - dt
else
dt = int((c[n,"due"] - c[n,"mtime"] - dt) / day * ef + 0.5) * day
if(dt < 0)
dt = 1 * day
t = time + dt
c[n,"mtime"] = time
c[n,"due"] = t
}
function swap(X, a, b, t){
t = X[a]
X[a] = X[b]
X[b] = t
}
function qsort(X, l, r, i, e){
if(l >= r)
return
swap(X, l, l + int((r - l + 1) * rand()))
e = l
for(i=l+1; i<=r; i++)
if(X[i] < X[l])
swap(X, ++e, i)
swap(X, l, e)
qsort(X, l, e-1)
qsort(X, e+1, r)
}
function shuffle( r, nr){
for(i in dues){
nr++
do
r[nr] = rand()
while(r[r[nr]] != 0)
r[r[nr]] = dues[i]
}
delete dues
qsort(r, 1, nr)
for(i=1; i<=nr; i++)
dues[i] = r[r[i]]
}
BEGIN{
srand()
"date -n" | getline time
}
NF != 5{
exit (exits = "invalid db record " NR)
}
{
c[NR,"ef"] = $1
c[NR,"nrep"] = $2
c[NR,"mtime"] = $3
c[NR,"due"] = $4
c[NR,"path"] = $5
if(time >= $4)
dues[++dc] = NR
}
END{
if(exits != ""){
print exits
exit exits
}
while(length(dues) > 0){
shuffle()
for(i in dues){
n = dues[i]
#system("proof -m 1 " c[n,"path"])
system("page " c[n,"path"])
do
getline q < "-"
while(q !~ /^[0-9]$/ || q > 5)
setef(n, int(q))
if(q >= 4){
delete dues[i]
c[n,"nrep"]++
setdue(n)
}else if(q < 3)
c[n,"nrep"] = 0
}
}
for(i=1; i<=NR; i++)
print c[i,"ef"], c[i,"nrep"], c[i,"mtime"], c[i,"due"], c[i,"path"]
}