spaced_repetition 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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
+