-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathwflashcard
More file actions
executable file
·149 lines (126 loc) · 3.84 KB
/
wflashcard
File metadata and controls
executable file
·149 lines (126 loc) · 3.84 KB
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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
#!/bin/sh -e
minweight=0.01
penalty=1.75
quick=3
quickreward=4.0
review=0
reviewreward=1.05
reward=1.75
help() {
cat - >&2 <<EOF
wflashcard - weighted flashcard viewer
wflashcard [-v] [-p penalty] [-r reward] [-q quickreward] [-s quick] [-m minweight] [-w reviewreward] 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 "minweight".
The -v flag enables review mode, which shows the front and back of each
flashcard and ignores answers. A small reward is given upon review by
default, this can be configured with the -w flag.
The defaults for these options are:
penalty=$penalty
reward=$reward
quickreward=$quickreward
quick=$quick
minweight=$minweight
reviewreward=$reviewreward
EOF
}
while getopts 'm:p:q:r:s:vw:h' o; do
case "$o" in
m) minweight="$OPTARG" ;;
p) penalty="$OPTARG" ;;
q) quickreward="$OPTARG" ;;
r) reward="$OPTARG" ;;
s) quick="$OPTARG" ;;
v) review=1 ;;
w) reviewreward="$OPTARG" ;;
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 reviewreward="$reviewreward" \
-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 }
# skip comments and blank lines
/^$/ || /^#/ { rawline[NR] = $0; filename[NR] = FILENAME; next }
$1 == "" || $2 == "" {
print "Invalid flashcard on line " NR > "/dev/stderr"
rawline[NR] = $0; filename[NR] = FILENAME
next
}
$3 == "" { $3 = $2; $2 = $1; $1 = 1; } # set missing weight to 1
{ sum += weight[NR] = $1; front[NR] = $2; back[NR] = $3; filename[NR] = FILENAME; }
END {
if (sum == 0) {
print "Sum of weights is zero" > "/dev/stderr"
exit
}
if (review && tty != "not a tty")
print "/quit to exit" > "/dev/stderr"
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])
if (tty != "not a tty")
printf("> ")
srand(); time = srand()
response = ""; getline response < tty;
srand(); response_time = srand() - time
if (review) {
new_weight = weight[i] / reviewreward
} else if (response == "" || response == "/quit") {
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
if (response == "/quit" || tty == "not a tty")
break
}
for (i = 1; i <= NR; i++) {
if (weight[i])
print weight[i], front[i], back[i] > filename[i]
else
print rawline[i] > filename[i]
}
}' "$@"