ref: a35484265f9fb32d9faa2064ad24d8dec99ba919
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"] }