mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 08:46:37 -04:00
next time reports and associated unit tests
This commit is contained in:
parent
9e46db5b3e
commit
5e0cc2ff5d
2 changed files with 94 additions and 17 deletions
|
@ -6,7 +6,7 @@ import time, datetime, simplejson, random
|
|||
from operator import itemgetter
|
||||
from heapq import *
|
||||
#from anki.cards import Card
|
||||
from anki.utils import parseTags, ids2str, intTime
|
||||
from anki.utils import parseTags, ids2str, intTime, fmtTimeSpan
|
||||
from anki.lang import _, ngettext
|
||||
from anki.consts import *
|
||||
from anki.hooks import runHook
|
||||
|
@ -211,18 +211,20 @@ limit %d""" % self.reportLimit, lim=self.dayCutoff)
|
|||
card.queue = 1
|
||||
card.type = 1
|
||||
|
||||
def _rescheduleNew(self, card, conf, early):
|
||||
def _graduatingIvl(self, card, conf, early):
|
||||
if not early:
|
||||
# graduate
|
||||
int_ = conf['ints'][0]
|
||||
return conf['ints'][0]
|
||||
elif card.cycles:
|
||||
# remove
|
||||
int_ = conf['ints'][2]
|
||||
return conf['ints'][2]
|
||||
else:
|
||||
# first time bonus
|
||||
int_ = conf['ints'][1]
|
||||
card.ivl = int_
|
||||
card.due = self.today+int_
|
||||
return conf['ints'][1]
|
||||
|
||||
def _rescheduleNew(self, card, conf, early):
|
||||
card.ivl = self._graduatingIvl(card, conf, early)
|
||||
card.due = self.today+card.ivl
|
||||
card.factor = conf['initialFactor']
|
||||
|
||||
def _logLearn(self, card, ease, conf, leaving):
|
||||
|
@ -304,7 +306,7 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
card.streak = 0
|
||||
card.lapses += 1
|
||||
card.lastIvl = card.ivl
|
||||
card.ivl = int(card.ivl*conf['mult']) + 1
|
||||
card.ivl = self._nextLapseIvl(card, conf)
|
||||
card.factor = max(1300, card.factor-200)
|
||||
card.due = card.edue = self.today + card.ivl
|
||||
# put back in the learn queue?
|
||||
|
@ -314,11 +316,14 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
# leech?
|
||||
self._checkLeech(card, conf)
|
||||
|
||||
def _nextLapseIvl(self, card, conf):
|
||||
return int(card.ivl*conf['mult']) + 1
|
||||
|
||||
def _rescheduleReview(self, card, ease):
|
||||
card.streak += 1
|
||||
# update interval
|
||||
card.lastIvl = card.ivl
|
||||
self._updateInterval(card, ease)
|
||||
self._updateRevIvl(card, ease)
|
||||
# then the rest
|
||||
card.factor = max(1300, card.factor+[-150, 0, 150][ease-2])
|
||||
card.due = self.today + card.ivl
|
||||
|
@ -342,7 +347,7 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
# Interval management
|
||||
##########################################################################
|
||||
|
||||
def nextInterval(self, card, ease):
|
||||
def _nextRevIvl(self, card, ease):
|
||||
"Ideal next interval for CARD, given EASE."
|
||||
delay = self._daysLate(card)
|
||||
conf = self._cardConf(card)
|
||||
|
@ -356,18 +361,13 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
# must be at least one day greater than previous interval
|
||||
return max(card.ivl+1, int(interval))
|
||||
|
||||
def nextIntervalStr(self, card, ease, short=False):
|
||||
"Return the next interval for CARD given EASE as a string."
|
||||
int = self.nextInterval(card, ease)
|
||||
return anki.utils.fmtTimeSpan(int*86400, short=short)
|
||||
|
||||
def _daysLate(self, card):
|
||||
"Number of days later than scheduled."
|
||||
return max(0, self.today - card.due)
|
||||
|
||||
def _updateInterval(self, card, ease):
|
||||
def _updateRevIvl(self, card, ease):
|
||||
"Update CARD's interval, trying to avoid siblings."
|
||||
idealIvl = self.nextInterval(card, ease)
|
||||
idealIvl = self._nextRevIvl(card, ease)
|
||||
idealDue = self.today + idealIvl
|
||||
conf = self._cardConf(card)['rev']
|
||||
# find sibling positions
|
||||
|
@ -520,6 +520,45 @@ queue = 1 %s and due <= :lim order by %s limit %d""" % (
|
|||
"select count() from (select id from cards where "
|
||||
"queue = 2 limit %d)" % lim)
|
||||
|
||||
# Next time reports
|
||||
##########################################################################
|
||||
|
||||
def nextIvlStr(self, card, ease, short=False):
|
||||
"Return the next interval for CARD as a string."
|
||||
return fmtTimeSpan(
|
||||
self.nextIvl(card, ease), short=short)
|
||||
|
||||
def nextIvl(self, card, ease):
|
||||
"Return the next interval for CARD, in seconds."
|
||||
if card.queue in (0,2):
|
||||
# in learning
|
||||
return self._nextLrnIvl(card, ease)
|
||||
elif ease == 1:
|
||||
# lapsed
|
||||
conf = self._cardConf(card)['lapse']
|
||||
return self._nextLapseIvl(card, conf)*86400
|
||||
else:
|
||||
# review
|
||||
return self._nextRevIvl(card, ease)*86400
|
||||
|
||||
# this isn't easily extracted from the learn code
|
||||
def _nextLrnIvl(self, card, ease):
|
||||
conf = self._learnConf(card)
|
||||
if ease == 1:
|
||||
# grade 0
|
||||
return self._delayForGrade(conf, 0)
|
||||
elif ease == 3:
|
||||
# early removal
|
||||
return self._graduatingIvl(card, conf, True) * 86400
|
||||
else:
|
||||
grade = card.grade + 1
|
||||
if grade >= len(conf['delays']):
|
||||
# graduate
|
||||
return self._graduatingIvl(card, conf, False) * 86400
|
||||
else:
|
||||
# next level
|
||||
return self._delayForGrade(conf, grade)
|
||||
|
||||
# Suspending
|
||||
##########################################################################
|
||||
|
||||
|
|
|
@ -231,3 +231,41 @@ def test_finished():
|
|||
d.sched.answerCard(c, 3)
|
||||
# nothing should be due tomorrow, as it's due in a week
|
||||
assert "No cards are due" in d.sched.finishedMsg()
|
||||
|
||||
def test_nextIvl():
|
||||
d = getEmptyDeck()
|
||||
f = d.newFact()
|
||||
f['Front'] = u"one"; f['Back'] = u"two"
|
||||
d.addFact(f)
|
||||
c = f.cards()[0]
|
||||
# cards in learning
|
||||
##################################################
|
||||
ni = d.sched.nextIvl
|
||||
assert ni(c, 1) == 30
|
||||
assert ni(c, 2) == 180
|
||||
# immediate removal is 7 days
|
||||
assert ni(c, 3) == 7*86400
|
||||
c.cycles = 1
|
||||
c.grade = 1
|
||||
assert ni(c, 1) == 30
|
||||
assert ni(c, 2) == 600
|
||||
# no first time bonus
|
||||
assert ni(c, 3) == 4*86400
|
||||
c.grade = 2
|
||||
# normal graduation is tomorrow
|
||||
assert ni(c, 2) == 1*86400
|
||||
assert ni(c, 3) == 4*86400
|
||||
# review cards
|
||||
##################################################
|
||||
c.queue = 1
|
||||
c.ivl = 100
|
||||
c.factor = 2500
|
||||
# failing it puts it at tomorrow
|
||||
assert ni(c, 1) == 1*86400
|
||||
# (* 100 1.2 86400)10368000.0
|
||||
assert ni(c, 2) == 10368000
|
||||
# (* 100 2.5 86400)21600000.0
|
||||
assert ni(c, 3) == 21600000
|
||||
# (* 100 2.5 1.3 86400)28080000.0
|
||||
assert ni(c, 4) == 28080000
|
||||
print d.sched.nextIvlStr(c, 4) == "10.8 months"
|
||||
|
|
Loading…
Reference in a new issue