-
Notifications
You must be signed in to change notification settings - Fork 1
/
wflashcard
executable file
·126 lines (108 loc) · 3.23 KB
/
wflashcard
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#!/bin/sh -e
minweight=0.01
penalty=1.75
quick=3
quickreward=4.0
review=0
reward=1.75
help() {
cat - >&2 <<EOF
wflashcard - weighted flashcard viewer
wflashcard [-v] [-p penalty] [-r reward] [-q quickreward] [-s quick] [-m minweight] files...
The file format is tab separated where the (optional) first field is the
weight, the second field is the "front" of the flashcard (shown to the
user), and the third field is the "back" of the flashcard (the expected
answer). If the weight is omitted then it will be set to 1.0. Blank
lines and comment lines are valid.
Incorrect answers will have their weight multiplied by "penalty",
correct answers will have their weight divided by "reward", quick &
correct (answered in <= "quick" seconds) answers will have their weight
divided by "quickreward", and the minimum weight will be capped at
"minweight".
The -v flag enables review mode, which shows the front and back of each
flashcard and ignores answers.
The defaults for these options are:
penalty=$penalty
reward=$reward
quickreward=$quickreward
quick=$quick
minweight=$minweight
EOF
}
while getopts 'm:p:q:r:s:vh' o; do
case "$o" in
m) minweight="$OPTARG" ;;
p) penalty="$OPTARG" ;;
q) quickreward="$OPTARG" ;;
r) reward="$OPTARG" ;;
s) quick="$OPTARG" ;;
v) review=1 ;;
h) help; exit 0 ;;
*) help; exit 1 ;;
esac
done
shift $((OPTIND-1))
awk -F "$(printf '\t')" -v tty="$(tty)" \
-v minweight="$minweight" \
-v penalty="$penalty" \
-v quick="$quick" \
-v quickreward="$quickreward" \
-v review="$review" \
-v reward="$reward" \
'
function emphatic(s) { printf("\n----------------\n%s\n----------------\n\n", s) }
function basename(s) { sub("/$", "", s); gsub(".*/", "", s); return s; }
BEGIN { OFS = FS }
/^$/ || /^#/ { next } # skip blank or comment lines
# handle missing weight by setting it to 1
$1 != "" && $2 != "" && $3 == "" { $3 = $2; $2 = $1; $1 = 1; }
{ sum += weight[NR] = $1; front[NR] = $2; back[NR] = $3; filename[NR] = FILENAME; }
END {
if (sum == 0) {
print "Sum of weights is zero"
exit
}
srand()
while (1) {
target = rand() * sum
isum = 0
for (i = 1; i <= NR; i++)
if (weight[i] && target <= (isum += weight[i]))
break
if (review)
printf("%s: %s\t%s\n> ", basename(filename[i]), front[i], back[i])
else
printf("%s: %s\n> ", basename(filename[i]), front[i])
srand(); time = srand()
response = ""; getline response < tty;
srand(); response_time = srand() - time
if (review) {
new_weight = weight[i]
continue
} else if (response == "") {
new_weight = weight[i]
break
} else if (response == back[i] && response_time <= quick) {
new_weight = weight[i] / quickreward
emphatic("Correct!")
} else if (response == back[i]) {
new_weight = weight[i] / reward
emphatic("Correct!")
} else {
emphatic("The correct answer was " back[i] ". Were you correct? (y/N)")
printf("> ")
response = ""; getline response < tty;
if (response == "y" || response == "Y")
new_weight = weight[i] / reward
else
new_weight = weight[i] * penalty
}
if (new_weight < minweight)
new_weight = minweight
updatew = new_weight - weight[i]
weight[i] = new_weight
sum += updatew
}
for (i = 1; i <= NR; i++)
print weight[i], front[i], back[i] > filename[i]
}' "$@"