spaced_repetition 1.0.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.
data/README.md ADDED
@@ -0,0 +1,35 @@
1
+ Spaced Repetition algorithm for Ruby.
2
+
3
+ ## Install
4
+ Add to your Gemfile:
5
+
6
+ gem 'spaced_repetition', :git => 'git://github.com/espresse/spaced_repetition.git'
7
+
8
+ and run
9
+
10
+ bundle install
11
+
12
+ ## Typical use-case:
13
+
14
+ require 'rubygems'
15
+ require 'spaced_repetition'
16
+
17
+ #user's quality_response is 5, no previous repetition had been done yet
18
+ sm2 = SpacedRepetition::Sm2.new(5)
19
+
20
+ #user's quality response is 3, his/her prevoius interval was 3 days and easiness factor was 2.1
21
+ sm2 = SpacedRepetition::Sm2.new(3,3,2.1)
22
+
23
+ You can fetch results:
24
+
25
+ #new interval
26
+ new_interval = sm2.interval
27
+
28
+ #new easiness_factor
29
+ new_ef = sm2.easniness_factor
30
+
31
+ #new repetition date
32
+ new_date = sm2.next_repetition_date
33
+
34
+ By default, SM2, uses 6 possible answers (0-5), where 0 is very bad and 5 is perfect. If you want to use 4 answers (0 /very bad/ - 3 /perfect/) you can choose SM2Mod. It works in the same manner as SM2 does.
35
+
@@ -0,0 +1,63 @@
1
+ #http://www.supermemo.com/english/ol/sm2.htm
2
+ require 'date'
3
+
4
+ module SpacedRepetition
5
+ class Sm2
6
+ def initialize(quality_response, prev_interval=0, prev_ef=2.5)
7
+ @prev_ef = prev_ef
8
+ @prev_interval = prev_interval
9
+ @quality_response = quality_response
10
+
11
+ @calculated_interval = nil
12
+ @calculated_ef = nil
13
+ @repetition_date = nil
14
+
15
+ #if quality_response is below 3 start repetition from the begining, but without changing easiness_factor
16
+ if @quality_response < 3
17
+ @prev_interval=0
18
+ @calculated_ef = @prev_ef
19
+ else
20
+ calculate_easiness_factor
21
+ end
22
+ calculate_interval
23
+
24
+ calculate_date
25
+ end
26
+
27
+ def interval
28
+ @calculated_interval
29
+ end
30
+
31
+ def easiness_factor
32
+ @calculated_ef
33
+ end
34
+
35
+ def next_repetition_date
36
+ @repetition_date
37
+ end
38
+
39
+ private
40
+
41
+ def calculate_interval
42
+ if @prev_interval == 0
43
+ @calculated_interval = 1
44
+ elsif @prev_interval == 1
45
+ @calculated_interval = 6
46
+ else
47
+ @calculated_interval = (@prev_interval*@prev_ef).to_i
48
+ end
49
+ end
50
+
51
+ def calculate_easiness_factor
52
+ @calculated_ef = @prev_ef+(0.1-(5-@quality_response)*(0.08+(5-@quality_response)*0.02))
53
+ if @calculated_ef < 1.3
54
+ @calculated_ef = 1.3
55
+ end
56
+ @calculated_ef
57
+ end
58
+
59
+ def calculate_date
60
+ @repetition_date = Date.today + @calculated_interval
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,69 @@
1
+ #modified sm2 algorithm
2
+ #changes:
3
+ # - initial interval depends on given quality_response
4
+ # - states (easiness_factor is calulated using that states, sm2 for ok uses 4)
5
+ # - 0 - bad (0, -0.8), 1 - so so(2, -0.3), 2 - ok(4, 0), 3 - more than better(5, 0.1)
6
+ require 'date'
7
+
8
+ module SpacedRepetition
9
+ class Sm2Mod
10
+ def initialize(quality_response, prev_interval=0, prev_ef=2.5)
11
+ @prev_ef = prev_ef
12
+ @prev_interval = prev_interval
13
+ @quality_response = quality_response
14
+
15
+ @calculated_interval = nil
16
+ @calculated_ef = nil
17
+ @repetition_date = nil
18
+
19
+ #if quality_response is below 3 start repetition from the begining, but without changing easiness_factor
20
+ if @quality_response < 2
21
+ @prev_interval=0
22
+ @calculated_ef = @prev_ef
23
+ else
24
+ calculate_easiness_factor
25
+ end
26
+ calculate_interval
27
+ calculate_date
28
+ end
29
+
30
+ def interval
31
+ @calculated_interval
32
+ end
33
+
34
+ def easiness_factor
35
+ @calculated_ef
36
+ end
37
+
38
+ def next_repetition_date
39
+ @repetition_date
40
+ end
41
+
42
+ private
43
+
44
+ def calculate_interval
45
+ if @prev_interval == 0
46
+ @calculated_interval = 1
47
+ if @quality_response == 3
48
+ @calculated_interval = 6
49
+ end
50
+ elsif @prev_interval == 1
51
+ @calculated_interval = 6
52
+ else
53
+ @calculated_interval = (@prev_interval*@prev_ef).to_i
54
+ end
55
+ end
56
+
57
+ def calculate_easiness_factor
58
+ @calculated_ef = @prev_ef+(0.1-(3-@quality_response)*((3-@quality_response)*0.1))
59
+ if @calculated_ef < 1.3
60
+ @calculated_ef = 1.3
61
+ end
62
+ @calculated_ef
63
+ end
64
+
65
+ def calculate_date
66
+ @repetition_date = Date.today + @calculated_interval
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,2 @@
1
+ require 'spaced_repetition/sm2'
2
+ require 'spaced_repetition/sm2_mod'
@@ -0,0 +1,18 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = "spaced_repetition"
5
+ s.version = "1.0.0"
6
+ s.platform = Gem::Platform::RUBY
7
+ s.authors = ["Michał Ostrowski"]
8
+ s.email = ["michol@linuxcsb.org"]
9
+ s.summary = %q{Ruby gem for calculating spaced repetition intervals}
10
+ s.description = %q{Ruby gem for calculating spaced repetition intervals.}
11
+
12
+ s.files = `git ls-files`.split("\n")
13
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.require_paths = ["lib"]
16
+
17
+ s.add_dependency("bundler", ["~> 1.0"])
18
+ end
data/test/test_sm2.rb ADDED
@@ -0,0 +1,54 @@
1
+ require "spaced_repetition"
2
+ require "test/unit"
3
+
4
+ class TestSm2 < Test::Unit::TestCase
5
+
6
+ def test_scenario_user_starts_learning_new_element
7
+ sm2 = SpacedRepetition::Sm2.new(5)
8
+ assert_equal(1, sm2.interval)
9
+ assert_in_delta 2.6, sm2.easiness_factor, 0.001
10
+
11
+ sm2 = SpacedRepetition::Sm2.new(4)
12
+ assert_equal(1, sm2.interval)
13
+ assert_in_delta 2.5, sm2.easiness_factor, 0.001
14
+
15
+ sm2 = SpacedRepetition::Sm2.new(3)
16
+ assert_equal(1, sm2.interval)
17
+ assert_in_delta 2.36, sm2.easiness_factor, 0.001
18
+ end
19
+
20
+ def test_scenario_user_is_doing_good
21
+ sm2 = SpacedRepetition::Sm2.new(4, 6, 2.1)
22
+ assert_equal(12, sm2.interval)
23
+ assert_in_delta 2.1, sm2.easiness_factor, 0.001
24
+
25
+ sm2 = SpacedRepetition::Sm2.new(5, 12, 2.1)
26
+ assert_equal(25, sm2.interval)
27
+ assert_in_delta 2.2, sm2.easiness_factor, 0.001
28
+
29
+ sm2 = SpacedRepetition::Sm2.new(5, 25, 2.1)
30
+ assert_equal(52, sm2.interval)
31
+ assert_in_delta 2.2, sm2.easiness_factor, 0.001
32
+ end
33
+
34
+ def test_scenario_user_is_doing_good_but_later_is_going_bad
35
+ sm2 = SpacedRepetition::Sm2.new(3, 6, 2.1)
36
+ assert_equal(12, sm2.interval)
37
+ assert_in_delta 1.96, sm2.easiness_factor, 0.001
38
+
39
+ sm2 = SpacedRepetition::Sm2.new(0, 12, 1.96)
40
+ assert_equal(1, sm2.interval)
41
+ assert_in_delta 1.96, sm2.easiness_factor, 0.001
42
+
43
+ sm2 = SpacedRepetition::Sm2.new(0, 1, 1.96)
44
+ assert_equal(1, sm2.interval)
45
+ assert_in_delta 1.96, sm2.easiness_factor, 0.001
46
+ end
47
+
48
+ def test_scenario_user_passed_char_instead_of_number
49
+ assert_raise( ArgumentError ) { SpacedRepetition::Sm2.new("a", 6, 2.1) }
50
+ end
51
+
52
+
53
+ end
54
+
metadata ADDED
@@ -0,0 +1,87 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: spaced_repetition
3
+ version: !ruby/object:Gem::Version
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
11
+ platform: ruby
12
+ authors:
13
+ - "Micha\xC5\x82 Ostrowski"
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-03-16 00:00:00 +01:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: bundler
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ~>
28
+ - !ruby/object:Gem::Version
29
+ hash: 15
30
+ segments:
31
+ - 1
32
+ - 0
33
+ version: "1.0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ description: Ruby gem for calculating spaced repetition intervals.
37
+ email:
38
+ - michol@linuxcsb.org
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ extra_rdoc_files: []
44
+
45
+ files:
46
+ - README.md
47
+ - lib/spaced_repetition.rb
48
+ - lib/spaced_repetition/sm2.rb
49
+ - lib/spaced_repetition/sm2_mod.rb
50
+ - spaced_repetition.gemspec
51
+ - test/test_sm2.rb
52
+ has_rdoc: true
53
+ homepage:
54
+ licenses: []
55
+
56
+ post_install_message:
57
+ rdoc_options: []
58
+
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ none: false
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ hash: 3
67
+ segments:
68
+ - 0
69
+ version: "0"
70
+ required_rubygems_version: !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ requirements: []
80
+
81
+ rubyforge_project:
82
+ rubygems_version: 1.3.7
83
+ signing_key:
84
+ specification_version: 3
85
+ summary: Ruby gem for calculating spaced repetition intervals
86
+ test_files: []
87
+