Skip to content

Instantly share code, notes, and snippets.

@yrgoldteeth
Created May 23, 2012 15:14
Show Gist options
  • Save yrgoldteeth/2775824 to your computer and use it in GitHub Desktop.
Save yrgoldteeth/2775824 to your computer and use it in GitHub Desktop.
SuperMemo2 Repetition Spacing
class Datum < ActiveRecord::Base
has_many :repetition_intervals
has_many :difficulty_factors
has_many :datum_responses
after_create :initial_datum_setup
def recent_repetition_interval
repetition_intervals.last
end
def recent_difficulty_factor
difficulty_factors.last
end
def recent_response
datum_repsonses.last
end
private
def initial_datum_setup
update_attribute(:repetitions, 0)
repetition_intervals.create(:state => 'first_repetition')
difficulty_factors.create(:factor => 2.5)
end
end
class DatumResponse < ActiveRecord::Base
belongs_to :datum
after_create :initial_datum_response_setup
def next_repetition_interval_state
datum.recent_repetition_interval.next_successful_state
end
def difficulty_factor
datum.recent_difficulty_factor.factor
end
private
def initial_datum_response_setup
handle_difficulty_factor
case quality
when 0, 1, 2
datum.repetitions = 0
datum.save
datum.repetition_intervals.create(:state => 'first_repetition')
else
datum.repetitions += 1
datum.save
datum.repetition_intervals.create(:state => next_repetition_interval_state)
end
end
def handle_difficulty_factor
new_factor = difficulty_factor + (0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02))
if new_factor > 1.3
datum.difficulty_factors.create(:factor => new_factor)
else
datum.difficulty_factors.create(:factor => 1.3)
end
end
end
class DifficultyFactor < ActiveRecord::Base
belongs_to :datum
end
class RepetitionInterval < ActiveRecord::Base
belongs_to :datum
state_machine :initial => :created do
state :created
state :first_repetition do
def next_repetition_interval;1;end
end
state :second_repetition do
def next_repetition_interval;6;end
end
state :extended_repetition do
def next_repetition_interval;calculated_next_repetition_interval;end
end
end
after_create :initial_interval_setup
def next_successful_state
(second_repetition? || extended_repetition?) ? 'extended_repetition' : 'second_repetition'
end
def calculated_next_repetition_interval
((datum.repetitions - 1) * difficulty_factor).round
end
def next_repetition_date
created_at + next_repetition_interval.days
end
def difficulty_factor
datum.recent_difficulty_factor.factor
end
private
def initial_interval_setup
update_attribute(:interval, next_repetition_interval)
update_attribute(:next_repetition, next_repetition_date)
end
end
ActiveRecord::Schema.define(:version => 20110911190622) do
create_table "data", :force => true do |t|
t.string "state"
t.string "description"
t.text "body"
t.integer "repetitions"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "datum_responses", :force => true do |t|
t.integer "datum_id"
t.integer "quality"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "difficulty_factors", :force => true do |t|
t.integer "datum_id"
t.float "factor"
t.string "state"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "repetition_intervals", :force => true do |t|
t.string "state"
t.integer "datum_id"
t.integer "interval"
t.datetime "next_repetition"
t.datetime "created_at"
t.datetime "updated_at"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment