forgetful 0.3.0 → 0.3.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/forgetful +34 -31
- data/lib/forgetful/cli.rb +21 -11
- data/lib/forgetful/reminder.rb +4 -0
- data/spec/reminder_spec.rb +8 -0
- metadata +4 -4
data/Rakefile
CHANGED
@@ -10,7 +10,7 @@ begin
|
|
10
10
|
gem.email = "jonathan.palardy@gmail.com"
|
11
11
|
gem.homepage = "http://github.com/jpalardy/forgetful"
|
12
12
|
gem.authors = ["Jonathan Palardy"]
|
13
|
-
gem.add_development_dependency "rspec", "
|
13
|
+
gem.add_development_dependency "rspec", "= 1.2.9"
|
14
14
|
end
|
15
15
|
Jeweler::GemcutterTasks.new
|
16
16
|
rescue LoadError
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.3.
|
1
|
+
0.3.3
|
data/bin/forgetful
CHANGED
@@ -1,55 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
1
2
|
|
2
3
|
require "forgetful"
|
3
4
|
require "forgetful/cli"
|
4
|
-
require '
|
5
|
+
require 'optparse'
|
5
6
|
|
6
7
|
#-------------------------------------------------
|
7
8
|
|
8
|
-
def
|
9
|
-
|
10
|
-
|
9
|
+
def parse(args)
|
10
|
+
options = { :filenames => [],
|
11
|
+
:verbose => false,
|
12
|
+
:action => :quiz }
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
args.options do |arg|
|
15
|
+
arg.banner = "Usage: forgetful [OPTION]... [FILE]..."
|
16
|
+
arg.separator ""
|
17
|
+
arg.separator "Specific options:"
|
16
18
|
|
17
|
-
|
18
|
-
|
19
|
+
arg.on( '-t', '--touch', "Validate filename(s) and write back in full CSV format") do
|
20
|
+
options[:action] = :touch
|
21
|
+
end
|
22
|
+
|
23
|
+
arg.separator ""
|
24
|
+
arg.separator "Common options:"
|
25
|
+
|
26
|
+
arg.on( '-v', '--verbose', "Show more information") do
|
27
|
+
options[:verbose] = true
|
28
|
+
end
|
19
29
|
|
20
|
-
|
21
|
-
result = { :filenames => [],
|
22
|
-
:action => :quiz }
|
23
|
-
|
24
|
-
opts = GetoptLong.new(['--help', '-h', GetoptLong::NO_ARGUMENT],
|
25
|
-
['--touch', '-t', GetoptLong::NO_ARGUMENT],
|
26
|
-
['--version', GetoptLong::NO_ARGUMENT])
|
27
|
-
|
28
|
-
opts.each do |opt, arg|
|
29
|
-
case opt
|
30
|
-
when '--help'
|
31
|
-
usage
|
32
|
-
when '--touch'
|
33
|
-
result[:action] = :touch
|
34
|
-
when '--version'
|
30
|
+
arg.on( '--version', "Show version") do
|
35
31
|
puts File.read(File.join(File.dirname(__FILE__), "..", "VERSION"))
|
36
|
-
exit
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
|
35
|
+
arg.on_tail('-h', '--help', "Show this message") do
|
36
|
+
puts arg
|
37
|
+
exit
|
37
38
|
end
|
39
|
+
|
40
|
+
arg.parse!
|
38
41
|
end
|
39
42
|
|
40
|
-
|
41
|
-
|
43
|
+
options[:filenames] = args.dup
|
44
|
+
args.clear
|
42
45
|
|
43
|
-
|
46
|
+
options
|
44
47
|
end
|
45
48
|
|
46
49
|
#-------------------------------------------------
|
47
50
|
|
48
|
-
options =
|
51
|
+
options = parse(ARGV)
|
49
52
|
|
50
53
|
begin
|
51
54
|
options[:filenames].each do |filename|
|
52
|
-
ReminderFile.new(filename).send(options[:action])
|
55
|
+
ReminderFile.new(filename, options[:verbose]).send(options[:action])
|
53
56
|
end
|
54
57
|
rescue Interrupt
|
55
58
|
puts
|
data/lib/forgetful/cli.rb
CHANGED
@@ -1,16 +1,18 @@
|
|
1
1
|
|
2
2
|
class ReminderFile
|
3
|
-
attr_reader :filename
|
3
|
+
attr_reader :filename, :verbose
|
4
4
|
|
5
|
-
def initialize(filename)
|
5
|
+
def initialize(filename, verbose=false)
|
6
6
|
@filename = filename
|
7
|
+
@verbose = verbose
|
7
8
|
end
|
8
9
|
|
9
10
|
def reminders
|
10
11
|
@reminders ||= Reminder.read_csv(filename)
|
11
12
|
end
|
12
13
|
|
13
|
-
def
|
14
|
+
def write(reminders)
|
15
|
+
raise "Writing back a different number of reminders than read from file (#{reminders.size} != #{@reminders.size})" if reminders.size != @reminders.size
|
14
16
|
Reminder.write_csv(filename, reminders.sort)
|
15
17
|
end
|
16
18
|
|
@@ -20,30 +22,37 @@ class ReminderFile
|
|
20
22
|
# 3. sort the rows
|
21
23
|
def touch
|
22
24
|
puts "### TOUCH: #{filename}"
|
23
|
-
|
25
|
+
write(reminders)
|
24
26
|
end
|
25
27
|
|
26
28
|
def quiz
|
27
29
|
puts "### QUIZ: #{filename}"
|
28
30
|
dues, not_dues = reminders.partition { |reminder| reminder.due_on <= Date.today }
|
29
|
-
gradeds = quiz_map(dues.sort_by { rand })
|
31
|
+
gradeds, ungradeds = quiz_map(dues.sort_by { rand })
|
30
32
|
|
31
|
-
|
33
|
+
write(gradeds + ungradeds + not_dues)
|
32
34
|
|
33
35
|
faileds = gradeds.select { |reminder| reminder.review? }
|
34
|
-
until faileds.empty?
|
36
|
+
until faileds.empty? || ungradeds.any?
|
35
37
|
puts "### REVIEW: #{filename}"
|
36
|
-
gradeds = quiz_map(faileds.sort_by { rand })
|
38
|
+
gradeds, ungradeds = quiz_map(faileds.sort_by { rand })
|
37
39
|
faileds = gradeds.select { |reminder| reminder.review? }
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
43
|
private
|
42
44
|
def quiz_map(reminders)
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
gradeds = []
|
46
|
+
ungradeds = reminders.dup
|
47
|
+
|
48
|
+
reminders.each_with_index do |reminder, i|
|
49
|
+
q = ask(reminder, i+1, reminders.size)
|
50
|
+
gradeds << ungradeds.shift.next(q)
|
46
51
|
end
|
52
|
+
rescue EOFError
|
53
|
+
# tolerate Ctrl-D, skips the rest of the quiz
|
54
|
+
ensure
|
55
|
+
return gradeds, ungradeds
|
47
56
|
end
|
48
57
|
|
49
58
|
def ask(reminder, i, n)
|
@@ -54,6 +63,7 @@ class ReminderFile
|
|
54
63
|
readline
|
55
64
|
|
56
65
|
puts padding + "A: #{reminder.answer}"
|
66
|
+
puts padding + " %.2f -> %s" % [reminder.ef, reminder.history.join] if verbose
|
57
67
|
|
58
68
|
while true
|
59
69
|
print padding + "? "
|
data/lib/forgetful/reminder.rb
CHANGED
data/spec/reminder_spec.rb
CHANGED
@@ -16,6 +16,10 @@ describe "reminder" do
|
|
16
16
|
it "should be valid" do
|
17
17
|
@reminder.to_a.should == [@question, @answer, Date.today, []]
|
18
18
|
end
|
19
|
+
|
20
|
+
it "should have an ef of 2.5" do
|
21
|
+
@reminder.ef.should be_close(2.5, 0.0001)
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
describe "with full constructor" do
|
@@ -33,6 +37,10 @@ describe "reminder" do
|
|
33
37
|
@reminder.history.push(5)
|
34
38
|
}.should raise_error(error_type, "can't modify frozen array")
|
35
39
|
end
|
40
|
+
|
41
|
+
it "should have an ef of 2.8 (based on history)" do
|
42
|
+
@reminder.ef.should be_close(2.8, 0.0001)
|
43
|
+
end
|
36
44
|
end
|
37
45
|
|
38
46
|
describe "next" do
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 3
|
8
|
-
-
|
9
|
-
version: 0.3.
|
8
|
+
- 3
|
9
|
+
version: 0.3.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jonathan Palardy
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-
|
17
|
+
date: 2010-11-05 00:00:00 -04:00
|
18
18
|
default_executable: forgetful
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
@@ -23,7 +23,7 @@ dependencies:
|
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
24
|
none: false
|
25
25
|
requirements:
|
26
|
-
- - "
|
26
|
+
- - "="
|
27
27
|
- !ruby/object:Gem::Version
|
28
28
|
segments:
|
29
29
|
- 1
|