forked from stefan-peng/oboeta
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathREADME
388 lines (296 loc) · 15.2 KB
/
README
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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
Title: Oboeta Plain-Text Flashcard System
Author: Jordan Vaughan <jordan.t.vaughan@gmail.com>
Language: en-US
Created: 2012-11-07
Last-Modified: 2017-08-10
Revision: 2.0.0 Jordan Vaughan
Encoding: UTF-8
Preferred-Line-Width: 80
Table of Contents
1. Introduction
1.1. The Problem
1.2. The Solution
2. Requirements
3. Installation
4. The Scripts
4.1. oleitner
4.2. osm2
4.3. oboeta
4.4. oboetatty
4.5. oboetahttp
4.6. ocloze
5. Use
6. Sample Framework Built on Oboeta
7. License
8. Contributors
9. Copyright
1. Introduction
This collection of simple scripts helps users manage simple,
plain-text collections of flashcards. It focuses on the essence of
flashcard systems: scheduling. It also provides some very simple
programs for displaying flashcards. A lot of the inspiration for this
project comes from <http://suckless.org> and <http://cat-v.org>.
"Oboeta" is a Japanese verb in the simple past tense.
It means "remembered" or "memorized".
1.1. The Problem
I love electronic flashcards. There are so many things to like
about them:
1. They're easy to create, modify, and destroy.
2. It's especially easy to automatically generate hordes of cards
from a few sentences if they're formatted properly.
3. It's easy to apply changes across electronic flashcard decks.
4. Computers can schedule reviews and track progress more quickly
and accurately than humans.
5. Electronic flashcards are easy to back up and transport.
6. They occupy very little physical space. (Hence (5).)
But I also hate the most popular flashcard programs, such as Anki.
They're complex, buggy, too restrictive, and tied to GUIs
and storage formats that make my skin crawl. (OK, SQLite isn't
too bad, but extracting data from it is still a pain in the ass.)
I tried many programs and was never satisfied. All I wanted was
something that operated on plain text and separated flashcards
from their metadata.
Plain text is an awesome way to store flashcards and their metadata
because:
1. plain text is universal: it'll be around when your
grandchildren's grandchildren become worm food;
2. plain text can be easily edited via any text editor;
3. plain text files aren't tied to a particular program
or library; and
4. all standard UNIX/POSIX tools can manipulate plain text files.
And then there's my love for paper flashcards. I admit that they're
a pain to create and manage, but there are reasons to use them:
1. You can format paper flashcards however you want.
No supporting tools or complicated formatting algorithms
are necessary: Just write what you want and be done with it.
2. Sometimes paper flashcards are easier to carry around
and faster to use than a smart phone. I have a little
plastic pencil case that I bought for about $5 into which my
B7-sized flashcards fit perfectly. All I have to do to access
them is unzip the case and pull them out.
3. For people learning new languages with complex writing systems
(such as some East Asian languages), paper flashcards force them
to practice writing. Typing doesn't help.
4. Some people feel better when they use paper flashcards.
I'm one of them. I don't understand why, but I get that
mysteriously good feeling that a lot of people say they have
when they use paper products rather than electronic devices
(e.g., for reading).
5. Paper flashcards grab attention. Smart phones and laptops
don't do that because they're common and everyone around
the user assumes she's playing games, sending messages,
or surfing the web. For language learners, the best thing
about grabbing people's attention with flashcards is that
it creates opportunities to practice. Curious people start
conversations, which lead to new sentences, which lead to
new flashcards. It's a beautiful circle.
1.2. The Solution
I wrote Oboeta to combine electronic and paper flashcards into
a hybrid system. The scripts are deliberately minimalistic
so that you can format the flashcard data however you want.
You can use them to maintain a paper or electronic flashcard system.
Oboeta provides two scheduling systems. The first is based on the
Leitner system <http://en.wikipedia.org/wiki/Leitner_system>, which
forms BUCKETS of flashcards, each bucket of which contains an
associated interval in days. The intervals determine how much time
is added to a card's due date when you pass it. This simple system
provides only two responses for each card: "pass" and "fail".
Oboeta used to use this Leitner system exclusively: I have retained
it because others might like it.
The second scheduling system is a slight variation of version 2 of the
SuperMemo algorithm <http://www.supermemo.com/english/ol/sm2.htm>,
also called "SM-2". Each card has an associated EASINESS FACTOR,
an INTERVAL in days, and an INTERVAL NUMBER, all of which determine
how much time should be added to the card when you review it.
SM-2 provides more fine-grained responses than Leitner systems:
Instead of the binary pass/fail responses, you have to choose an
integer between 0 and 5, where 0 means complete memory blackout
and 5 means "Piece of cake!" Your response determines the card's
other parameters.
Here's how the overall system works: You maintain a collection of
(paper) flashcards organized any way you like provided that each one
has a unique identifier. (I use monotonically-increasing positive
integers for mine.) On the electronic side, you maintain two plain
UTF-8-encoded text files:
1. a delimiter-separated values (DSV) file (the DECK) containing
one flashcard per line, each beginning with the flashcard's
unique identifier; and
2. a DSV file (the LOG) containing records of flashcard reviews.
Oboeta is agnostic about the deck's data: It only expects that the
file is a DSV file and that the first field of each line is a unique
identifier. You can format everything else however you want.
This makes adding, editing, and reformatting flashcards a cinch:
Just edit the deck file. You can do this with any text editor.
On the other hand, the requirements for the log are more stringent:
1. Each nonempty line must have exactly three fields:
a flashcard's identifier, a timestamp, and either of the
'+' and '-' characters if your reviews use the Leitner system
OR an integer in the range [0,5] if you use SM-2.
2. The flashcard's identifier need not actually name a flashcard.
(This makes deleting flashcards easy: Just remove them from the
deck. You can remove their entries in the log, too, but you
don't have to.)
3. The timestamp can be formatted however you wish,
but you must be consistent.
4. If your reviews use the Leitner system, then the third field
must be either a single '+' character or a single '-' character.
'+' indicates that you successfully reviewed the associated
flashcard on the date represented by the timestamp,
whereas '-' indicates that you failed. On the other hand,
if your reviews use SM-2, then the third field must be
an integer between 0 and 5, inclusive.
Oboeta uses the log to schedule flashcards for review. You ask Oboeta
to dump a bunch of new or due cards to the screen, select the
corresponding paper flashcards, and review them. When you're finished
reviewing your cards, update the log accordingly. Alternatively, you
can use the console- and HTTP-based review scripts to review the cards
on your computer, which will automatically update the log.
2. Requirements
I wrote most of the code in Python 3.(Die-hard Python 2 fans
can cry me a river: Python 3 is the new standard.
Welcome to the present AND the future.) It runs fine with CPython,
the standard implementation.
3. Installation
Open a terminal, navigate to the directory containing Oboeta's
source code, and execute the install.sh script, passing the directory
where you want to install executables as the first parameter.
For example:
$ ./install.sh /usr/bin
This will copy the scripts to the specified directory.
You might have to change users (e.g., run sudo)
depending on which installation directory you select.
4. The Scripts
All of these scripts only depend on the standard Python 3 libraries.
They can be executed independently but are designed to be plugged
together via UNIX pipes or temporary files.
For detailed help on a script, run it with an "-h"
or "--help" argument.
4.1. oleitner
Process the deck and log files using the Leitner system
and display flashcards that are due for review on standard output.
4.2. osm2
This is like oleitner but uses SM-2 instead of the Leitner system.
4.3. oboeta
Review flashcards from standard input, shuffling and writing them
one at a time to standard output, while reading commands (pass, fail,
quit) from a file (usually a named pipe).
4.4. oboetatty
Read flashcards one at a time from a file (usually a named pipe)
and write them to standard output, get user input from standard input,
and write the results (pass, fail, quit) to a file (usually a named
pipe). This program is only suitable for text-only flashcards.
4.5. oboetahttp
This is like oboetatty but reads cards from standard input instead
and serves the cards as HTML5 over HTTP.
4.6. ocloze
Generate cloze deletion flashcards from standard input.
5. Use
oleitner and osm2 randomly choose new and due flashcards
from a deck using history stored in a log file.
They're simple filters reading from stdin and writing to stdout.
oboeta is designed to work with oboetatty and oboetahttp,
though you could write other programs to interact with it.
o oboeta functions as a flashcard randomizer and logger,
reading flashcards chosen by oleitner and osm2 via stdin.
o oboetatty and oboetahttp focus on displaying the flashcards
that oboeta chooses and sending results back to oboeta.
oboetatty requires two named pipes:
1. one for receiving cards from oboeta
2. one for sending commands to oboeta
On the other hand, oboetahttp requires only one named pipe,
which it uses to send commands to oboeta. oboetahttp reads cards
from standard input.
It gets a little more complicated, though. You have to break up
each card that oboeta prints into two lines per card
before feeding them to oboetatty or oboetahttp.
1. The first line contains the front side's fields.
2. The second line contains the back side's fields.
sed(1) and awk(1) scripts can usually handle this job.
Here's a diagram illustrating the data flow between scripts:
DECK FILE --. .-------- LOG FILE <---------.
| | |
| | |
| | |
stdin | | command line argument |
v v |
+-----------+ |
| oleitner/ | |
| osm2 | |
+-----------+ |
| stdout |
| |
v stdin |
named pipe +-----------+ |
.------------>| oboeta |------------------------'
| +-----------+ command line argument
| | stdout
| |
| v stdin
| +--------------------+
| | Split lines in two |
| | (front and back) |
| +--------------------+
| | stdout
| |
| v
| +------------+
| | oboetatty |--------.
'-------------| or | | User reviews flashcards
named pipe | oboetahttp |<-------'
+------------+
Let's check out some example pipelines. Suppose your deck uses
the SM-2 algorithm and you want reviews to have at most 20 old cards
and 10 new ones. If you want to review the cards on the console
using fields two and three as the front and back, respectively,
then this Bourne shell code will do it:
mkfifo -m 0700 cardpipe commandpipe
( osm2 -n 20 -e 10 deck.log <deck.csv | \
oboeta -2 $commandpipe deck.log | awk -F \\t '{
print $2
print $3
system("") # to flush awk's stdout buffer
}' >$cardpipe ) &
oboetatty -2 $cardpipe $commandpipe
The -2 flags enable SM-2 support in oboeta and oboetatty.
If you want to review cards via your favorite web browser,
do this instead:
mkfifo -m 0700 commandpipe
osm2 -n 20 -e 10 deck.log <deck.csv | \
oboeta -2 $commandpipe deck.log | awk -F \\t '{
print $2
print $3
system("") # to flush awk's stdout buffer
}' | oboetahttp -2 >$commandpipe
Of course, you can insert your own text processing pipelines
between the oboeta scripts: That's the beauty of writing
decoupled text-based programs. For example, I like to insert
a script between osm2 and oboeta to transform custom Japanese
furigana (rubi) annotations into HTML5 <ruby> tags.
6. Sample Framework Built on Oboeta
If you want an example of a framework built on top of Oboeta,
see my Honden repo at <https://github.com/joodan-van-github/honden>.
Beware: I no longer maintain Honden. It's kinda old.
7. License
All of the files in this collection have been dedicated to the
public domain via the Creative Commons CC0 Public Domain Dedication
in the hope that they would be circulated widely and without
restriction. I won't make any money from this code and I feel that
it's more important that other people are free to use, modify,
and distribute it as they please, with or without charge,
even if I could make money from this. Simply put, I like contributing
to a healthy public domain. See the file LICENSE for a complete copy
of the public domain dedication.
8. Contributors
o Jordan Vaughan (main contributor) <https://github.com/jtvaughan>
o wzel <https://github.com/wzel>
9. Copyright
##########
### ###
## ## ## To the extent possible under law,
# # ## # the authors have waived all copyright
# # ## # and related and neighboring rights to
# ## # # this work. For more information, please see
# ## # # <https://creativecommons.org/publicdomain/zero/1.0/>.
## ## ##
### ###
##########