active_recall 1.1.0 → 1.2.0
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +4 -4
- data/README.md +12 -6
- data/lib/active_recall.rb +20 -0
- data/lib/active_recall/algorithms/fibonacci_sequence.rb +66 -0
- data/lib/active_recall/configuration.rb +11 -0
- data/lib/active_recall/models/item.rb +9 -3
- data/lib/active_recall/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cd98a58a0b310c84f7fb225ea5d7ab8f6a15f3f784b47b57c0b423d2b7ec4001
|
4
|
+
data.tar.gz: 94a4401f4adb97d724d0287d6edad73ae42a8a5e1073436132f90e3fb23bb4a8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2b7fb09f86a3513e82370c320833cf620ee9082371a27c2f404c913ff2717cc5f3fe0145acc8061a90623661266eb86d8cefcc37843081a3d998caba898c033d
|
7
|
+
data.tar.gz: 19d5f46d9df7f38c859adac7c2eae9eb90359529b5890ac1bf5c6f9f99251636b96be5ee2dbcb847410601826554f94f140d270bc499088c99e1cb776b9f471c
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
active_recall (1.
|
4
|
+
active_recall (1.2.0)
|
5
5
|
activerecord (>= 5.2.3)
|
6
6
|
activesupport (>= 5.2.3)
|
7
7
|
|
@@ -21,9 +21,9 @@ GEM
|
|
21
21
|
zeitwerk (~> 2.1, >= 2.1.8)
|
22
22
|
concurrent-ruby (1.1.5)
|
23
23
|
diff-lcs (1.3)
|
24
|
-
i18n (1.
|
24
|
+
i18n (1.7.0)
|
25
25
|
concurrent-ruby (~> 1.0)
|
26
|
-
minitest (5.
|
26
|
+
minitest (5.12.2)
|
27
27
|
rake (10.5.0)
|
28
28
|
rdoc (6.2.0)
|
29
29
|
rspec (3.8.0)
|
@@ -43,7 +43,7 @@ GEM
|
|
43
43
|
thread_safe (0.3.6)
|
44
44
|
tzinfo (1.2.5)
|
45
45
|
thread_safe (~> 0.1)
|
46
|
-
zeitwerk (2.
|
46
|
+
zeitwerk (2.2.0)
|
47
47
|
|
48
48
|
PLATFORMS
|
49
49
|
ruby
|
data/README.md
CHANGED
@@ -29,9 +29,15 @@ Or install it yourself as:
|
|
29
29
|
$ gem install active_recall
|
30
30
|
|
31
31
|
## Usage
|
32
|
+
You can configure the desired SRS algorithm during runtime:
|
33
|
+
```ruby
|
34
|
+
ActiveRecall.configure do |config|
|
35
|
+
config.algorithm_class = ActiveRecall::FibonacciSequence
|
36
|
+
end
|
37
|
+
```
|
38
|
+
For Rails applications, try doing this from within an [initializer file](https://guides.rubyonrails.org/configuring.html#using-initializer-files).
|
32
39
|
|
33
|
-
Assume you have an application allowing your users to study words in a foreign language. Using the
|
34
|
-
you can set up a deck of flashcards that the user will study:
|
40
|
+
Assume you have an application allowing your users to study words in a foreign language. Using the `has_deck` method you can set up a deck of flashcards that the user will study:
|
35
41
|
|
36
42
|
```ruby
|
37
43
|
class Word < ActiveRecord::Base
|
@@ -48,7 +54,7 @@ word = Word.create!(:kanji => "日本語", :kana => "にほんご", :translation
|
|
48
54
|
You can add words and record attempts to guess the word as right or wrong. Various methods exist to allow you to access subsets of this collection:
|
49
55
|
|
50
56
|
```ruby
|
51
|
-
#
|
57
|
+
# Initially adding a word
|
52
58
|
user.words << word
|
53
59
|
user.words.untested #=> [word]
|
54
60
|
|
@@ -64,7 +70,7 @@ user.words.failed #=> [word]
|
|
64
70
|
user.words #=> [word]
|
65
71
|
```
|
66
72
|
|
67
|
-
As time passes words need to be reviewed to keep them fresh in memory:
|
73
|
+
As time passes, words need to be reviewed to keep them fresh in memory:
|
68
74
|
|
69
75
|
```ruby
|
70
76
|
# Three days later...
|
@@ -72,7 +78,7 @@ user.words.known #=> []
|
|
72
78
|
user.words.expired #=> [word]
|
73
79
|
```
|
74
80
|
|
75
|
-
Guessing a word
|
81
|
+
Guessing a word correctly several times in a row results in the word taking longer to expire, and demonstrates mastery of that word.
|
76
82
|
|
77
83
|
```ruby
|
78
84
|
user.right_answer_for!(word)
|
@@ -89,7 +95,7 @@ user.words.expired #=> [word]
|
|
89
95
|
Reviewing
|
90
96
|
---------
|
91
97
|
|
92
|
-
In addition to an
|
98
|
+
In addition to an `expired` method, ActiveRecall provides a suggested reviewing sequence for all unknown words in the deck.
|
93
99
|
Words are randomly chosen from all untested words, failed, and finally expired in order of precedence.
|
94
100
|
|
95
101
|
```ruby
|
data/lib/active_recall.rb
CHANGED
@@ -3,9 +3,29 @@
|
|
3
3
|
require 'active_recall/base'
|
4
4
|
require 'active_recall/deck_methods'
|
5
5
|
require 'active_recall/item_methods'
|
6
|
+
require 'active_recall/algorithms/fibonacci_sequence'
|
6
7
|
require 'active_recall/algorithms/leitner_system'
|
8
|
+
require 'active_recall/configuration'
|
7
9
|
require 'active_recall/models/deck'
|
8
10
|
require 'active_recall/models/item'
|
9
11
|
require 'active_recall/version'
|
10
12
|
|
11
13
|
ActiveRecord::Base.send(:include, ActiveRecall::Base)
|
14
|
+
|
15
|
+
module ActiveRecall
|
16
|
+
class << self
|
17
|
+
attr_writer :configuration
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.configure
|
21
|
+
yield(configuration)
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.configuration
|
25
|
+
@configuration ||= Configuration.new
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.reset
|
29
|
+
@configuration = Configuration.new
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecall
|
4
|
+
class FibonacciSequence
|
5
|
+
def self.right(box:, current_time: Time.current, times_right:, times_wrong:)
|
6
|
+
new(
|
7
|
+
box: box,
|
8
|
+
current_time: current_time,
|
9
|
+
times_right: times_right,
|
10
|
+
times_wrong: times_wrong
|
11
|
+
).right
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.wrong(box:, current_time: Time.current, times_right:, times_wrong:)
|
15
|
+
new(
|
16
|
+
box: box,
|
17
|
+
current_time: current_time,
|
18
|
+
times_right: times_right,
|
19
|
+
times_wrong: times_wrong
|
20
|
+
).wrong
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(box:, current_time: Time.current, times_right:, times_wrong:)
|
24
|
+
@box = box
|
25
|
+
@current_time = current_time
|
26
|
+
@times_right = times_right
|
27
|
+
@times_wrong = times_wrong
|
28
|
+
end
|
29
|
+
|
30
|
+
def right
|
31
|
+
{
|
32
|
+
box: box + 1,
|
33
|
+
last_reviewed: current_time,
|
34
|
+
next_review: next_review,
|
35
|
+
times_right: times_right + 1,
|
36
|
+
times_wrong: times_wrong
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
def wrong
|
41
|
+
{
|
42
|
+
box: [0, box - 1].max,
|
43
|
+
last_reviewed: current_time,
|
44
|
+
next_review: nil,
|
45
|
+
times_right: times_right,
|
46
|
+
times_wrong: times_wrong + 1
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
attr_reader :box, :current_time, :times_right, :times_wrong
|
53
|
+
|
54
|
+
def fibonacci_number_at(index)
|
55
|
+
if (0..1).cover?(index)
|
56
|
+
index
|
57
|
+
else
|
58
|
+
fibonacci_number_at(index - 1) + fibonacci_number_at(index - 2)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def next_review
|
63
|
+
current_time + fibonacci_number_at(box + 1).days
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -3,10 +3,12 @@
|
|
3
3
|
module ActiveRecall
|
4
4
|
class Item < ActiveRecord::Base
|
5
5
|
self.table_name = 'active_recall_items'
|
6
|
+
|
6
7
|
belongs_to :deck
|
7
8
|
belongs_to :source, polymorphic: true
|
8
|
-
|
9
|
+
|
9
10
|
scope :failed, -> { where(['box = ? and last_reviewed is not null', 0]) }
|
11
|
+
scope :untested, -> { where(['box = ? and last_reviewed is null', 0]) }
|
10
12
|
|
11
13
|
def self.expired(current_time: Time.current)
|
12
14
|
where(['box > ? and next_review <= ?', 0, current_time])
|
@@ -17,15 +19,19 @@ module ActiveRecall
|
|
17
19
|
end
|
18
20
|
|
19
21
|
def right!
|
20
|
-
update!(
|
22
|
+
update!(algorithm_class.right(scoring_attributes))
|
21
23
|
end
|
22
24
|
|
23
25
|
def wrong!
|
24
|
-
update!(
|
26
|
+
update!(algorithm_class.wrong(scoring_attributes))
|
25
27
|
end
|
26
28
|
|
27
29
|
private
|
28
30
|
|
31
|
+
def algorithm_class
|
32
|
+
ActiveRecall.configuration.algorithm_class
|
33
|
+
end
|
34
|
+
|
29
35
|
def scoring_attributes
|
30
36
|
attributes.symbolize_keys.slice(:box, :times_right, :times_wrong)
|
31
37
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_recall
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robert Gravina
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date: 2019-
|
12
|
+
date: 2019-10-18 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bundler
|
@@ -130,8 +130,10 @@ files:
|
|
130
130
|
- bin/console
|
131
131
|
- bin/setup
|
132
132
|
- lib/active_recall.rb
|
133
|
+
- lib/active_recall/algorithms/fibonacci_sequence.rb
|
133
134
|
- lib/active_recall/algorithms/leitner_system.rb
|
134
135
|
- lib/active_recall/base.rb
|
136
|
+
- lib/active_recall/configuration.rb
|
135
137
|
- lib/active_recall/deck_methods.rb
|
136
138
|
- lib/active_recall/item_methods.rb
|
137
139
|
- lib/active_recall/models/deck.rb
|