Revert "obsolote relativeDelay in favour of interval desc, should fix ubuntu too"

This reverts commit 4558a36d3a.
This commit is contained in:
Damien Elmes 2008-11-12 15:09:16 +09:00
parent 4558a36d3a
commit 2175fa2343
4 changed files with 66 additions and 63 deletions

View file

@ -60,6 +60,7 @@ cardsTable = Table(
Column('noCount', Integer, nullable=False, default=0), Column('noCount', Integer, nullable=False, default=0),
# cache # cache
Column('spaceUntil', Float, nullable=False, default=0), Column('spaceUntil', Float, nullable=False, default=0),
Column('relativeDelay', Float, nullable=False, default=0),
Column('isDue', Boolean, nullable=False, default=0), Column('isDue', Boolean, nullable=False, default=0),
Column('type', Integer, nullable=False, default=2), Column('type', Integer, nullable=False, default=2),
Column('combinedDue', Integer, nullable=False, default=0)) Column('combinedDue', Integer, nullable=False, default=0))
@ -146,14 +147,8 @@ class Card(object):
return findTag(tag, alltags) return findTag(tag, alltags)
def fromDB(self, s, id): def fromDB(self, s, id):
r = s.first("""select r = s.first("select * from cards where id = :id",
id, factId, cardModelId, created, modified, tags, ordinal, question, answer, id=id)
priority, interval, lastInterval, due, lastDue, factor,
lastFactor, firstAnswered, reps, successive, averageTime, reviewTime,
youngEase0, youngEase1, youngEase2, youngEase3, youngEase4,
matureEase0, matureEase1, matureEase2, matureEase3, matureEase4,
yesCount, noCount, spaceUntil, isDue, type, combinedDue
from cards where id = :id""", id=id)
if not r: if not r:
return return
(self.id, (self.id,
@ -190,6 +185,7 @@ from cards where id = :id""", id=id)
self.yesCount, self.yesCount,
self.noCount, self.noCount,
self.spaceUntil, self.spaceUntil,
self.relativeDelay,
self.isDue, self.isDue,
self.type, self.type,
self.combinedDue) = r self.combinedDue) = r
@ -230,6 +226,7 @@ matureEase4=:matureEase4,
yesCount=:yesCount, yesCount=:yesCount,
noCount=:noCount, noCount=:noCount,
spaceUntil = :spaceUntil, spaceUntil = :spaceUntil,
relativeDelay = :interval / (strftime("%s", "now") - :due + 1),
isDue = :isDue, isDue = :isDue,
type = :type, type = :type,
combinedDue = max(:spaceUntil, :due) combinedDue = max(:spaceUntil, :due)

View file

@ -29,7 +29,8 @@ PRIORITY_NORM = 2
PRIORITY_LOW = 1 PRIORITY_LOW = 1
PRIORITY_NONE = 0 PRIORITY_NONE = 0
MATURE_THRESHOLD = 21 MATURE_THRESHOLD = 21
NEW_INTERVAL = 0 # need interval > 0 to ensure relative delay is ordered properly
NEW_INTERVAL = 0.001
NEW_CARDS_LAST = 1 NEW_CARDS_LAST = 1
NEW_CARDS_DISTRIBUTE = 0 NEW_CARDS_DISTRIBUTE = 0
@ -40,7 +41,7 @@ decksTable = Table(
Column('created', Float, nullable=False, default=time.time), Column('created', Float, nullable=False, default=time.time),
Column('modified', Float, nullable=False, default=time.time), Column('modified', Float, nullable=False, default=time.time),
Column('description', UnicodeText, nullable=False, default=u""), Column('description', UnicodeText, nullable=False, default=u""),
Column('version', Integer, nullable=False, default=12), Column('version', Integer, nullable=False, default=11),
Column('currentModelId', Integer, ForeignKey("models.id")), Column('currentModelId', Integer, ForeignKey("models.id")),
# syncing # syncing
Column('syncName', UnicodeText), Column('syncName', UnicodeText),
@ -107,7 +108,6 @@ class Deck(object):
def getCard(self, orm=True): def getCard(self, orm=True):
"Return the next card object, or None." "Return the next card object, or None."
self.checkDue()
id = self.getCardId() id = self.getCardId()
if id: if id:
return self.cardFromId(id, orm) return self.cardFromId(id, orm)
@ -115,7 +115,6 @@ class Deck(object):
def getCards(self, limit=1, orm=True): def getCards(self, limit=1, orm=True):
"""Return LIMIT number of new card objects. """Return LIMIT number of new card objects.
Caller must ensure multiple cards of the same fact are not shown.""" Caller must ensure multiple cards of the same fact are not shown."""
self.checkDue()
ids = self.getCardIds(limit) ids = self.getCardIds(limit)
return [self.cardFromId(x, orm) for x in ids] return [self.cardFromId(x, orm) for x in ids]
@ -268,6 +267,8 @@ where id != :id and factId = :factId""",
entry = CardHistoryEntry(card, ease, lastDelay) entry = CardHistoryEntry(card, ease, lastDelay)
entry.writeSQL(self.s) entry.writeSQL(self.s)
self.modified = now self.modified = now
# update isDue for failed cards
self.markExpiredCardsDue()
# invalidate counts # invalidate counts
self._countsDirty = True self._countsDirty = True
@ -286,16 +287,24 @@ then 1 -- review
else 2 -- new else 2 -- new
end)""" + where) end)""" + where)
def checkDue(self): def markExpiredCardsDue(self):
"Mark expired cards due." "Mark expired cards due, and update their relativeDelay."
self.s.statement("""update cards self.s.statement("""update cards
set isDue = 1 set isDue = 1, relativeDelay = interval / (strftime("%s", "now") - due + 1)
where isDue = 0 and priority in (1,2,3,4) and type in (0, 1, 2) where isDue = 0 and priority in (1,2,3,4) and combinedDue < :now""",
and combinedDue < :now""",
now=time.time()) now=time.time())
def rebuildQueue(self): def updateRelativeDelays(self):
"Update relative delays for expired cards."
self.s.statement("""update cards
set relativeDelay = interval / (strftime("%s", "now") - due + 1)
where isDue = 1 and type = 1""")
def rebuildQueue(self, updateRelative=True):
"Update relative delays based on current time." "Update relative delays based on current time."
if updateRelative:
self.updateRelativeDelays()
self.markExpiredCardsDue()
# cache global/daily stats # cache global/daily stats
self._globalStats = globalStats(self) self._globalStats = globalStats(self)
self._dailyStats = dailyStats(self) self._dailyStats = dailyStats(self)
@ -406,7 +415,7 @@ factor = 2.5, reps = 0, successive = 0, averageTime = 0, reviewTime = 0,
youngEase0 = 0, youngEase1 = 0, youngEase2 = 0, youngEase3 = 0, youngEase0 = 0, youngEase1 = 0, youngEase2 = 0, youngEase3 = 0,
youngEase4 = 0, matureEase0 = 0, matureEase1 = 0, matureEase2 = 0, youngEase4 = 0, matureEase0 = 0, matureEase1 = 0, matureEase2 = 0,
matureEase3 = 0,matureEase4 = 0, yesCount = 0, noCount = 0, matureEase3 = 0,matureEase4 = 0, yesCount = 0, noCount = 0,
spaceUntil = 0, isDue = 0, type = 2, spaceUntil = 0, relativeDelay = 0, isDue = 0, type = 2,
combinedDue = created, modified = :now, due = created combinedDue = created, modified = :now, due = created
where id in %s""" % ids2str(ids), now=time.time(), new=NEW_INTERVAL) where id in %s""" % ids2str(ids), now=time.time(), new=NEW_INTERVAL)
self.flushMod() self.flushMod()
@ -576,15 +585,15 @@ suspended</a> cards.''') % {
def suspendedCardCount(self): def suspendedCardCount(self):
return self.s.scalar( return self.s.scalar(
"select count(id) from cards where type in (0,1,2) and priority = 0") "select count(id) from cards where priority = 0")
def seenCardCount(self): def seenCardCount(self):
return self.s.scalar( return self.s.scalar(
"select count(id) from cards where type in (0, 1)") "select count(id) from cards where reps != 0")
def newCardCount(self): def newCardCount(self):
return self.s.scalar( return self.s.scalar(
"select count(id) from cards where type = 2") "select count(id) from cards where reps = 0")
# Counts related to due cards # Counts related to due cards
########################################################################## ##########################################################################
@ -641,8 +650,7 @@ select count(id) from failedCardsNow""")
def spacedCardCount(self): def spacedCardCount(self):
return self.s.scalar(""" return self.s.scalar("""
select count(cards.id) from cards where select count(cards.id) from cards where
isDue = 0 and type in (0,1,2) and priority != 0 and due < :now and spaceUntil > :now""",
priority in (1,2,3,4) and due < :now and spaceUntil > :now""",
now=time.time()) now=time.time())
def isEmpty(self): def isEmpty(self):
@ -1599,17 +1607,23 @@ alter table decks add column utcOffset numeric(10, 2) not null default 0""")
"Add indices to the DB." "Add indices to the DB."
# card queues # card queues
deck.s.statement(""" deck.s.statement("""
create index if not exists ix_cards_combinedDue on cards create index if not exists ix_cards_markExpired on cards
(type, isDue, combinedDue, priority)""") (isDue, priority desc, combinedDue desc)""")
deck.s.statement("""
create index if not exists ix_cards_failedIsDue on cards
(type, isDue, combinedDue)""")
deck.s.statement("""
create index if not exists ix_cards_failedOrder on cards
(type, isDue, due)""")
deck.s.statement(""" deck.s.statement("""
create index if not exists ix_cards_revisionOrder on cards create index if not exists ix_cards_revisionOrder on cards
(type, isDue, priority desc, interval desc)""") (type, isDue, priority desc, relativeDelay)""")
deck.s.statement(""" deck.s.statement("""
create index if not exists ix_cards_newRandomOrder on cards create index if not exists ix_cards_newRandomOrder on cards
(type, isDue, priority desc, factId, ordinal)""") (priority desc, factId, ordinal)""")
deck.s.statement(""" deck.s.statement("""
create index if not exists ix_cards_newOrderedOrder on cards create index if not exists ix_cards_newOrderedOrder on cards
(type, isDue, priority desc, combinedDue)""") (priority desc, due)""")
# card spacing # card spacing
deck.s.statement(""" deck.s.statement("""
create index if not exists ix_cards_factId on cards (factId)""") create index if not exists ix_cards_factId on cards (factId)""")
@ -1640,47 +1654,48 @@ create index if not exists ix_mediaDeleted_factId on mediaDeleted (mediaId)""")
def _addViews(deck): def _addViews(deck):
"Add latest version of SQL views to DB." "Add latest version of SQL views to DB."
s = deck.s s = deck.s
# old views # old tables
s.statement("drop view if exists failedCards") s.statement("drop view if exists failedCards")
s.statement("drop view if exists acqCards") s.statement("drop view if exists acqCards")
s.statement("drop view if exists futureCards") s.statement("drop view if exists futureCards")
s.statement("drop view if exists typedCards") s.statement("drop view if exists typedCards")
s.statement("drop view if exists failedCards") s.statement("drop view if exists failedCards")
s.statement("drop view if exists failedCardsNow") s.statement("drop view if exists failedCardsNow")
s.statement("drop view if exists failedCardsSoon")
s.statement("drop view if exists revCards")
s.statement("drop view if exists acqCardsRandom")
s.statement("drop view if exists acqCardsOrdered")
s.statement(""" s.statement("""
create view failedCardsNow as create view failedCardsNow as
select * from cards select * from cards
where type = 0 and isDue = 1 where type = 0 and isDue = 1
and +priority in (1,2,3,4) and combinedDue <= (strftime("%s", "now") + 1)
order by type, isDue, combinedDue order by combinedDue
""") """)
s.statement("drop view if exists failedCardsSoon")
s.statement(""" s.statement("""
create view failedCardsSoon as create view failedCardsSoon as
select * from cards select * from cards
where type = 0 and +priority in (1,2,3,4) where type = 0 and priority != 0
and combinedDue <= (select max(delay0, delay1) + and combinedDue <=
strftime("%s", "now")+1 from decks where id = 1) (select max(delay0, delay1)+strftime("%s", "now")+1
order by type, isDue, combinedDue from decks)
order by modified
""") """)
s.statement("drop view if exists revCards")
s.statement(""" s.statement("""
create view revCards as create view revCards as
select * from cards select * from cards where
where type = 1 and isDue = 1 type = 1 and isDue = 1
order by priority desc, interval desc""") order by type, isDue, priority desc, relativeDelay""")
s.statement("drop view if exists acqCardsRandom")
s.statement(""" s.statement("""
create view acqCardsRandom as create view acqCardsRandom as
select * from cards select * from cards
where type = 2 and isDue = 1 where type = 2 and isDue = 1
order by priority desc, factId, ordinal""") order by priority desc, factId, ordinal""")
s.statement("drop view if exists acqCardsOrdered")
s.statement(""" s.statement("""
create view acqCardsOrdered as create view acqCardsOrdered as
select * from cards select * from cards
where type = 2 and isDue = 1 where type = 2 and isDue = 1
order by priority desc, combinedDue""") order by priority desc, due""")
_addViews = staticmethod(_addViews) _addViews = staticmethod(_addViews)
def _upgradeDeck(deck, path): def _upgradeDeck(deck, path):
@ -1692,6 +1707,8 @@ order by priority desc, combinedDue""")
deck.s.statement(""" deck.s.statement("""
alter table cards add column spaceUntil float not null default 0""") alter table cards add column spaceUntil float not null default 0""")
deck.s.statement(""" deck.s.statement("""
alter table cards add column relativeDelay float not null default 0.0""")
deck.s.statement("""
alter table cards add column isDue boolean not null default 0""") alter table cards add column isDue boolean not null default 0""")
deck.s.statement(""" deck.s.statement("""
alter table cards add column type integer not null default 0""") alter table cards add column type integer not null default 0""")
@ -1821,20 +1838,6 @@ alter table models add column source integer not null default 0""")
DeckStorage._setUTCOffset(deck) DeckStorage._setUTCOffset(deck)
deck.version = 11 deck.version = 11
deck.s.commit() deck.s.commit()
if deck.version < 12:
deck.s.statement("drop index if exists ix_cards_revisionOrder")
deck.s.statement("drop index if exists ix_cards_newRandomOrder")
deck.s.statement("drop index if exists ix_cards_newOrderedOrder")
deck.s.statement("drop index if exists ix_cards_markExpired")
deck.s.statement("drop index if exists ix_cards_failedIsDue")
deck.s.statement("drop index if exists ix_cards_failedOrder")
deck.s.statement("drop index if exists ix_cards_type")
deck.s.statement("drop index if exists ix_cards_priority")
DeckStorage._addViews(deck)
DeckStorage._addIndices(deck)
deck.s.statement("analyze")
deck.version = 12
deck.s.commit()
return deck return deck
_upgradeDeck = staticmethod(_upgradeDeck) _upgradeDeck = staticmethod(_upgradeDeck)

View file

@ -77,7 +77,7 @@ class AnkiExporter(Exporter):
delete from reviewHistory""") delete from reviewHistory""")
self.newDeck.s.statement(""" self.newDeck.s.statement("""
update cards set update cards set
interval = 0, interval = 0.001,
lastInterval = 0, lastInterval = 0,
due = created, due = created,
lastDue = 0, lastDue = 0,
@ -101,6 +101,7 @@ yesCount = 0,
noCount = 0, noCount = 0,
spaceUntil = 0, spaceUntil = 0,
isDue = 1, isDue = 1,
relativeDelay = 0,
type = 2, type = 2,
combinedDue = created, combinedDue = created,
modified = :now modified = :now

View file

@ -516,7 +516,8 @@ priority, interval, lastInterval, due, lastDue, factor,
firstAnswered, reps, successive, averageTime, reviewTime, youngEase0, firstAnswered, reps, successive, averageTime, reviewTime, youngEase0,
youngEase1, youngEase2, youngEase3, youngEase4, matureEase0, youngEase1, youngEase2, youngEase3, youngEase4, matureEase0,
matureEase1, matureEase2, matureEase3, matureEase4, yesCount, noCount, matureEase1, matureEase2, matureEase3, matureEase4, yesCount, noCount,
question, answer, lastFactor, spaceUntil, isDue, type, combinedDue) question, answer, lastFactor, spaceUntil, isDue, type, combinedDue,
relativeDelay)
values values
(:id, :factId, :cardModelId, :created, :modified, :tags, :ordinal, (:id, :factId, :cardModelId, :created, :modified, :tags, :ordinal,
:priority, :interval, :lastInterval, :due, :lastDue, :factor, :priority, :interval, :lastInterval, :due, :lastDue, :factor,
@ -524,7 +525,7 @@ values
:youngEase1, :youngEase2, :youngEase3, :youngEase4, :matureEase0, :youngEase1, :youngEase2, :youngEase3, :youngEase4, :matureEase0,
:matureEase1, :matureEase2, :matureEase3, :matureEase4, :yesCount, :matureEase1, :matureEase2, :matureEase3, :matureEase4, :yesCount,
:noCount, :question, :answer, :lastFactor, :spaceUntil, :isDue, :noCount, :question, :answer, :lastFactor, :spaceUntil, :isDue,
:type, :combinedDue)""", dlist) :type, :combinedDue, 0)""", dlist)
self.deck.s.statement( self.deck.s.statement(
"delete from cardsDeleted where cardId in %s" % "delete from cardsDeleted where cardId in %s" %
ids2str([c[0] for c in cards])) ids2str([c[0] for c in cards]))
@ -789,10 +790,11 @@ priority, interval, lastInterval, due, lastDue, factor,
firstAnswered, reps, successive, averageTime, reviewTime, youngEase0, firstAnswered, reps, successive, averageTime, reviewTime, youngEase0,
youngEase1, youngEase2, youngEase3, youngEase4, matureEase0, youngEase1, youngEase2, youngEase3, youngEase4, matureEase0,
matureEase1, matureEase2, matureEase3, matureEase4, yesCount, noCount, matureEase1, matureEase2, matureEase3, matureEase4, yesCount, noCount,
question, answer, lastFactor, spaceUntil, isDue, type, combinedDue) question, answer, lastFactor, spaceUntil, isDue, type, combinedDue,
relativeDelay)
values values
(:id, :factId, :cardModelId, :created, :t, "", :ordinal, (:id, :factId, :cardModelId, :created, :t, "", :ordinal,
1, 0, 0, :created, 0, 2.5, 1, 0.001, 0, :created, 0, 2.5,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,