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() self.timerStarted = time.time()
def timeTaken(self): 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 # 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() self.checkDay()
id = self.getCardId() id = self.getCardId()
if id: if id:
return self.deck.getCard(id) c = self.deck.getCard(id)
c.startTimer()
return c
def reset(self): def reset(self):
self.resetConf() self.resetConf()
@ -167,8 +169,17 @@ limit %d""" % self.learnLimit, lim=self.dayCutoff)
card.grade = 0 card.grade = 0
if card.grade >= len(conf['delays']): if card.grade >= len(conf['delays']):
self.graduateLearnCard(card, conf) self.graduateLearnCard(card, conf)
return
else: 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): def learnConf(self, card):
conf = self.confForCard(card) conf = self.confForCard(card)
@ -197,12 +208,23 @@ limit %d""" % self.learnLimit, lim=self.dayCutoff)
def rescheduleAsReview(self, card, conf, int_): def rescheduleAsReview(self, card, conf, int_):
card.queue = 1 card.queue = 1
card.factor = conf['initialFactor']
if int_: if int_:
# new card # new card
card.type = 1 card.type = 1
card.interval = int_ 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 # Reviews
########################################################################## ##########################################################################
@ -230,8 +252,8 @@ queue = 1 %s and due < :lim order by %s limit %d""" % (
return self.revQueue return self.revQueue
def revOrder(self): def revOrder(self):
return ("interval desc", return ("ivl desc",
"interval", "ivl",
"due")[self.deck.qconf['revCardOrder']] "due")[self.deck.qconf['revCardOrder']]
# FIXME: rewrite # FIXME: rewrite
@ -253,8 +275,7 @@ queue = 1 %s and due < :lim order by %s limit %d""" % (
oldSuc = card.successive oldSuc = card.successive
# update card details # update card details
last = card.interval last = card.interval
card.interval = self.nextInterval(card, ease) card.ivl = self.nextInterval(card, ease)
card.lastInterval = last
if card.reps: if card.reps:
# only update if card was not new # only update if card was not new
card.lastDue = card.due card.lastDue = card.due
@ -329,6 +350,23 @@ and queue between 1 and 2""",
# update local cache of seen facts # update local cache of seen facts
self.spacedFacts[card.fid] = new 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 # Interval management
########################################################################## ##########################################################################

View file

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

View file

@ -3,7 +3,7 @@
import time import time
from tests.shared import assertException, getEmptyDeck from tests.shared import assertException, getEmptyDeck
from anki.stdmodels import BasicModel from anki.stdmodels import BasicModel
from anki.utils import stripHTML from anki.utils import stripHTML, intTime
def test_basics(): def test_basics():
d = getEmptyDeck() d = getEmptyDeck()
@ -24,9 +24,11 @@ def test_new():
assert c.queue == 2 assert c.queue == 2
assert c.type == 2 assert c.type == 2
# if we answer it, it should become a learn card # if we answer it, it should become a learn card
t = intTime()
d.sched.answerCard(c, 1) d.sched.answerCard(c, 1)
assert c.queue == 0 assert c.queue == 0
assert c.type == 2 assert c.type == 2
assert c.due >= t
# the default order should ensure siblings are not seen together, and # the default order should ensure siblings are not seen together, and
# should show all cards # should show all cards
m = d.currentModel() m = d.currentModel()
@ -73,6 +75,12 @@ def test_learn():
# and it should be grade 1 now # and it should be grade 1 now
assert c.grade == 1 assert c.grade == 1
assert c.cycles == 2 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 # pass again
d.sched.answerCard(c, 2) d.sched.answerCard(c, 2)
# it should by due in 10 minutes # it should by due in 10 minutes