mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
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:
parent
2dadb2c933
commit
e4cc3e3013
5 changed files with 58 additions and 33 deletions
|
@ -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
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
|
@ -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)
|
|
|
@ -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
|
||||||
##########################################################################
|
##########################################################################
|
||||||
|
|
||||||
|
|
|
@ -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 (
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue