Class: Fsrs::Scheduler
- Inherits:
-
Object
- Object
- Fsrs::Scheduler
- Defined in:
- lib/fsrs/fsrs.rb
Overview
Scheduler
Instance Attribute Summary collapse
-
#decay ⇒ Object
Returns the value of attribute decay.
-
#factor ⇒ Object
Returns the value of attribute factor.
-
#p ⇒ Object
Returns the value of attribute p.
Instance Method Summary collapse
- #forgetting_curve(elapsed_days, stability) ⇒ Object
- #init_difficulty(r) ⇒ Object
- #init_ds(s) ⇒ Object
- #init_stability(r) ⇒ Object
-
#initialize ⇒ Scheduler
constructor
A new instance of Scheduler.
- #mean_reversion(init, current) ⇒ Object
- #next_difficulty(d, r) ⇒ Object
- #next_ds(s, last_d, last_s, retrievability) ⇒ Object
- #next_forget_stability(d, s, r) ⇒ Object
- #next_interval(s) ⇒ Object
- #next_recall_stability(d, s, r, rating) ⇒ Object
- #repeat(card, now) ⇒ Object
- #schedule_learning_relearning_state(s, now) ⇒ Object
- #schedule_new_state(s, now) ⇒ Object
- #schedule_review_state(s, card, now) ⇒ Object
Constructor Details
#initialize ⇒ Scheduler
Returns a new instance of Scheduler.
211 212 213 214 215 |
# File 'lib/fsrs/fsrs.rb', line 211 def initialize @p = Parameters.new @decay = -0.5 @factor = (0.9**(1 / @decay)) - 1 end |
Instance Attribute Details
#decay ⇒ Object
Returns the value of attribute decay.
209 210 211 |
# File 'lib/fsrs/fsrs.rb', line 209 def decay @decay end |
#factor ⇒ Object
Returns the value of attribute factor.
209 210 211 |
# File 'lib/fsrs/fsrs.rb', line 209 def factor @factor end |
#p ⇒ Object
Returns the value of attribute p.
209 210 211 |
# File 'lib/fsrs/fsrs.rb', line 209 def p @p end |
Instance Method Details
#forgetting_curve(elapsed_days, stability) ⇒ Object
303 304 305 |
# File 'lib/fsrs/fsrs.rb', line 303 def forgetting_curve(elapsed_days, stability) (1 + (factor * elapsed_days / stability))**decay end |
#init_difficulty(r) ⇒ Object
299 300 301 |
# File 'lib/fsrs/fsrs.rb', line 299 def init_difficulty(r) [[self.p.w[4] - (self.p.w[5] * (r - 3)), 1].max, 10].min end |
#init_ds(s) ⇒ Object
273 274 275 276 277 278 279 280 281 282 |
# File 'lib/fsrs/fsrs.rb', line 273 def init_ds(s) s.again.difficulty = init_difficulty(Rating::AGAIN) s.again.stability = init_stability(Rating::AGAIN) s.hard.difficulty = init_difficulty(Rating::HARD) s.hard.stability = init_stability(Rating::HARD) s.good.difficulty = init_difficulty(Rating::GOOD) s.good.stability = init_stability(Rating::GOOD) s.easy.difficulty = init_difficulty(Rating::EASY) s.easy.stability = init_stability(Rating::EASY) end |
#init_stability(r) ⇒ Object
295 296 297 |
# File 'lib/fsrs/fsrs.rb', line 295 def init_stability(r) [self.p.w[r - 1], 0.1].max end |
#mean_reversion(init, current) ⇒ Object
317 318 319 |
# File 'lib/fsrs/fsrs.rb', line 317 def mean_reversion(init, current) (self.p.w[7] * init) + ((1 - self.p.w[7]) * current) end |
#next_difficulty(d, r) ⇒ Object
312 313 314 315 |
# File 'lib/fsrs/fsrs.rb', line 312 def next_difficulty(d, r) next_d = d - (self.p.w[6] * (r - 3)) mean_reversion(self.p.w[4], next_d).clamp(1, 10) end |
#next_ds(s, last_d, last_s, retrievability) ⇒ Object
284 285 286 287 288 289 290 291 292 293 |
# File 'lib/fsrs/fsrs.rb', line 284 def next_ds(s, last_d, last_s, retrievability) s.again.difficulty = next_difficulty(last_d, Rating::AGAIN) s.again.stability = next_forget_stability(last_d, last_s, retrievability) s.hard.difficulty = next_difficulty(last_d, Rating::HARD) s.hard.stability = next_recall_stability(last_d, last_s, retrievability, Rating::HARD) s.good.difficulty = next_difficulty(last_d, Rating::GOOD) s.good.stability = next_recall_stability(last_d, last_s, retrievability, Rating::GOOD) s.easy.difficulty = next_difficulty(last_d, Rating::EASY) s.easy.stability = next_recall_stability(last_d, last_s, retrievability, Rating::EASY) end |
#next_forget_stability(d, s, r) ⇒ Object
327 328 329 |
# File 'lib/fsrs/fsrs.rb', line 327 def next_forget_stability(d, s, r) self.p.w[11] * (d**-self.p.w[12]) * (((s + 1)**self.p.w[13]) - 1) * Math.exp((1 - r) * self.p.w[14]) end |
#next_interval(s) ⇒ Object
307 308 309 310 |
# File 'lib/fsrs/fsrs.rb', line 307 def next_interval(s) new_interval = s / factor * ((self.p.request_retention**(1 / decay)) - 1) new_interval.round.clamp(1, self.p.maximum_interval) end |
#next_recall_stability(d, s, r, rating) ⇒ Object
321 322 323 324 325 |
# File 'lib/fsrs/fsrs.rb', line 321 def next_recall_stability(d, s, r, ) hard_penalty = == Rating::HARD ? self.p.w[15] : 1 easy_bonus = == Rating::EASY ? self.p.w[16] : 1 s * (1 + (Math.exp(self.p.w[8]) * (11 - d) * (s**-self.p.w[9]) * (Math.exp((1 - r) * self.p.w[10]) - 1) * hard_penalty * easy_bonus)) end |
#repeat(card, now) ⇒ Object
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 |
# File 'lib/fsrs/fsrs.rb', line 217 def repeat(card, now) raise Fsrs::InvalidDateError unless now.utc? card = card.clone card.elapsed_days = if card.state == State::NEW 0 else (now - card.last_review).to_i end card.last_review = now card.reps += 1 card_scheduler = CardScheduler.new(card) card_scheduler.update_state(card.state) case card.state when State::NEW schedule_new_state(card_scheduler, now) when State::LEARNING, State::RELEARNING schedule_learning_relearning_state(card_scheduler, now) when State::REVIEW schedule_review_state(card_scheduler, card, now) end card_scheduler.record_log(card, now) end |
#schedule_learning_relearning_state(s, now) ⇒ Object
252 253 254 255 256 257 |
# File 'lib/fsrs/fsrs.rb', line 252 def schedule_learning_relearning_state(s, now) hard_interval = 0 good_interval = next_interval(s.good.stability) easy_interval = [next_interval(s.easy.stability), good_interval + 1].max s.schedule(now, hard_interval, good_interval, easy_interval) end |
#schedule_new_state(s, now) ⇒ Object
242 243 244 245 246 247 248 249 250 |
# File 'lib/fsrs/fsrs.rb', line 242 def schedule_new_state(s, now) init_ds(s) s.again.due = now + 60 s.hard.due = now + (5 * 60) s.good.due = now + (10 * 60) easy_interval = next_interval(s.easy.stability) s.easy.scheduled_days = easy_interval s.easy.due = now + easy_interval.days end |
#schedule_review_state(s, card, now) ⇒ Object
259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'lib/fsrs/fsrs.rb', line 259 def schedule_review_state(s, card, now) interval = card.elapsed_days last_d = card.difficulty last_s = card.stability retrievability = forgetting_curve(interval, last_s) next_ds(s, last_d, last_s, retrievability) hard_interval = next_interval(s.hard.stability) good_interval = next_interval(s.good.stability) hard_interval = [hard_interval, good_interval].min good_interval = [good_interval, hard_interval + 1].max easy_interval = [next_interval(s.easy.stability), good_interval + 1].max s.schedule(now, hard_interval, good_interval, easy_interval) end |