revlog work

- remove revlog.py and move code into scheduler
- add a routine to log a learn repetition
- rename flags to type and set type=0 for learn mode
- add to unit test
This commit is contained in:
Damien Elmes 2011-03-11 07:07:21 +09:00
parent 2dadb2c933
commit e4cc3e3013
5 changed files with 58 additions and 33 deletions

View file

@ -118,7 +118,8 @@ streak=?, lapses=?, grade=?, cycles=? where id = ?""",
self.timerStarted = time.time()
def timeTaken(self):
return min(time.time() - self.timerStarted, MAX_TIMER)
"Time taken to answer card, in integer MS."
return int(min(time.time() - self.timerStarted, MAX_TIMER)*1000)
# Questions and answers
##########################################################################

View file

@ -1,22 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright: Damien Elmes <anki@ichi2.net>
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
import time
# Flags: 0=standard review, 1=reschedule due to cram, drill, etc
# Rep: Repetition number. The same number may appear twice if a card has been
# manually rescheduled or answered on multiple sites before a sync.
#
# We store the times in integer milliseconds to avoid an extra index on the
# primary key.
def logReview(db, card, ease, flags=0):
db.execute("""
insert into revlog values (
:created, :cardId, :ease, :rep, :lastInterval, :interval, :factor,
:userTime, :flags)""",
created=int(time.time()*1000), cardId=card.id, ease=ease, rep=card.reps,
lastInterval=card.lastInterval, interval=card.interval,
factor=card.factor, userTime=int(card.userTime()*1000),
flags=flags)

View file

@ -25,7 +25,9 @@ class Scheduler(object):
self.checkDay()
id = self.getCardId()
if id:
return self.deck.getCard(id)
c = self.deck.getCard(id)
c.startTimer()
return c
def reset(self):
self.resetConf()
@ -167,8 +169,17 @@ limit %d""" % self.learnLimit, lim=self.dayCutoff)
card.grade = 0
if card.grade >= len(conf['delays']):
self.graduateLearnCard(card, conf)
return
else:
card.due = time.time() + conf['delays'][card.grade]*60
card.due = time.time() + self.delayForGrade(conf, card.grade)
try:
self.logLearn(card, ease, conf)
except:
time.sleep(0.01)
self.logLearn(card, ease, conf)
def delayForGrade(self, conf, grade):
return conf['delays'][grade]*60
def learnConf(self, card):
conf = self.confForCard(card)
@ -197,12 +208,23 @@ limit %d""" % self.learnLimit, lim=self.dayCutoff)
def rescheduleAsReview(self, card, conf, int_):
card.queue = 1
card.factor = conf['initialFactor']
if int_:
# new card
card.type = 1
card.interval = int_
print "handle log, etc"
card.factor = conf['initialFactor']
print "logs for learning cards?"
else:
# failed card
pass
def logLearn(self, card, ease, conf):
self.deck.db.execute(
"insert into revlog values (?,?,?,?,?,?,?,?,?)",
int(time.time()*1000), card.id, ease, card.cycles,
self.delayForGrade(conf, card.grade),
self.delayForGrade(conf, max(0, card.grade-1)),
0, card.timeTaken(), 0)
# Reviews
##########################################################################
@ -230,8 +252,8 @@ queue = 1 %s and due < :lim order by %s limit %d""" % (
return self.revQueue
def revOrder(self):
return ("interval desc",
"interval",
return ("ivl desc",
"ivl",
"due")[self.deck.qconf['revCardOrder']]
# FIXME: rewrite
@ -253,8 +275,7 @@ queue = 1 %s and due < :lim order by %s limit %d""" % (
oldSuc = card.successive
# update card details
last = card.interval
card.interval = self.nextInterval(card, ease)
card.lastInterval = last
card.ivl = self.nextInterval(card, ease)
if card.reps:
# only update if card was not new
card.lastDue = card.due
@ -329,6 +350,23 @@ and queue between 1 and 2""",
# update local cache of seen facts
self.spacedFacts[card.fid] = new
# Flags: 0=standard review, 1=reschedule due to cram, drill, etc
# Rep: Repetition number. The same number may appear twice if a card has been
# manually rescheduled or answered on multiple sites before a sync.
#
# We store the times in integer milliseconds to avoid an extra index on the
# primary key.
def logReview(db, card, ease, flags=0):
db.execute("""
insert into revlog values (
:created, :cardId, :ease, :rep, :lastInterval, :interval, :factor,
:userTime, :flags)""",
created=int(time.time()*1000), cardId=card.id, ease=ease, rep=card.reps,
lastInterval=card.lastInterval, interval=card.interval,
factor=card.factor, userTime=int(card.userTime()*1000),
flags=flags)
# Interval management
##########################################################################

View file

@ -151,7 +151,7 @@ create table if not exists revlog (
lastInt integer not null,
factor integer not null,
taken integer not null,
flags integer not null
type integer not null
);
create table if not exists tags (

View file

@ -3,7 +3,7 @@
import time
from tests.shared import assertException, getEmptyDeck
from anki.stdmodels import BasicModel
from anki.utils import stripHTML
from anki.utils import stripHTML, intTime
def test_basics():
d = getEmptyDeck()
@ -24,9 +24,11 @@ def test_new():
assert c.queue == 2
assert c.type == 2
# if we answer it, it should become a learn card
t = intTime()
d.sched.answerCard(c, 1)
assert c.queue == 0
assert c.type == 2
assert c.due >= t
# the default order should ensure siblings are not seen together, and
# should show all cards
m = d.currentModel()
@ -73,6 +75,12 @@ def test_learn():
# and it should be grade 1 now
assert c.grade == 1
assert c.cycles == 2
# check log is accurate
log = d.db.first("select * from revlog order by time desc")
assert log[2] == 2
assert log[3] == 2
assert log[4] == 180
assert log[5] == 30
# pass again
d.sched.answerCard(c, 2)
# it should by due in 10 minutes