mirror of
https://github.com/ankitects/anki.git
synced 2025-09-23 16:26:40 -04:00
implement cram
still to do: - altering intervals at cram exit - tidying up
This commit is contained in:
parent
308846aa93
commit
bd477de1a9
5 changed files with 116 additions and 18 deletions
84
anki/cram.py
84
anki/cram.py
|
@ -2,9 +2,12 @@
|
|||
# Copyright: Damien Elmes <anki@ichi2.net>
|
||||
# License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html
|
||||
|
||||
from anki.utils import ids2str
|
||||
from anki.utils import ids2str, intTime
|
||||
from anki.sched import Scheduler
|
||||
|
||||
# The order arg should be the opposite of what you want. So if you want
|
||||
# modified ascending, pass in 'mod desc'.
|
||||
|
||||
class CramScheduler(Scheduler):
|
||||
name = "cram"
|
||||
|
||||
|
@ -14,11 +17,80 @@ class CramScheduler(Scheduler):
|
|||
self.order = order
|
||||
self.reset()
|
||||
|
||||
def counts(self):
|
||||
return (self.newCount, self.lrnCount, 0)
|
||||
|
||||
def reset(self):
|
||||
pass
|
||||
self._resetConf()
|
||||
self._resetLrn()
|
||||
self._resetNew()
|
||||
self._resetRev()
|
||||
|
||||
def getCard(self):
|
||||
pass
|
||||
def answerCard(self, card, ease):
|
||||
if card.queue == 2:
|
||||
card.queue = 1
|
||||
card.edue = card.due
|
||||
if card.queue == 1:
|
||||
self._answerLrnCard(card, ease)
|
||||
else:
|
||||
raise Exception("Invalid queue")
|
||||
card.mod = intTime()
|
||||
card.flushSched()
|
||||
|
||||
def countIdx(self, card):
|
||||
if card.queue == 2:
|
||||
return 0
|
||||
else:
|
||||
return 1
|
||||
|
||||
# Fetching
|
||||
##########################################################################
|
||||
|
||||
def _resetNew(self):
|
||||
self.newQueue = self.db.list("""
|
||||
select id from cards where queue = 2
|
||||
and gid in %s order by %s limit %d""" % (ids2str(self.gids),
|
||||
self.order,
|
||||
self.reportLimit))
|
||||
self.newCount = len(self.newQueue)
|
||||
|
||||
def _resetRev(self):
|
||||
self.revQueue = []
|
||||
self.revCount = 0
|
||||
|
||||
def _timeForNewCard(self):
|
||||
return True
|
||||
|
||||
def _getNewCard(self):
|
||||
if self.newQueue:
|
||||
id = self.newQueue.pop()
|
||||
self.newCount -= 1
|
||||
return id
|
||||
|
||||
# Answering
|
||||
##########################################################################
|
||||
|
||||
def _rescheduleAsRev(self, card, conf, early):
|
||||
Scheduler._rescheduleAsRev(self, card, conf, early)
|
||||
card.ivl = self._graduatingIvl(card, conf, early)
|
||||
card.due = self.today + card.ivl
|
||||
# temporarily suspend it
|
||||
card.queue = -3
|
||||
|
||||
def _graduatingIvl(self, card, conf, early):
|
||||
if conf['resched']:
|
||||
print "fixme"
|
||||
return card.ivl
|
||||
else:
|
||||
return card.ivl
|
||||
|
||||
def _lrnConf(self, card):
|
||||
return self._cardConf(card)['cram']
|
||||
|
||||
# Next time reports
|
||||
##########################################################################
|
||||
|
||||
def nextIvl(self, card, ease):
|
||||
"Return the next interval for CARD, in seconds."
|
||||
return self._nextLrnIvl(card, ease)
|
||||
|
||||
def answerCard(self):
|
||||
pass
|
||||
|
|
|
@ -655,7 +655,7 @@ select conf from gconf where id = (select gcid from groups where id = ?)""",
|
|||
self.sched.onClose()
|
||||
self.sched = self._stdSched
|
||||
|
||||
def cramGroups(self, gids, order="mod"):
|
||||
def cramGroups(self, gids, order="mod desc"):
|
||||
self.stdSched()
|
||||
self.sched = anki.cram.CramScheduler(self, gids, order)
|
||||
|
||||
|
|
|
@ -23,11 +23,15 @@ defaultConf = {
|
|||
# one of [suspend], [tagonly]
|
||||
'leechAction': ["suspend"],
|
||||
},
|
||||
'cram': {
|
||||
'delays': [0.5, 3, 10],
|
||||
'resched': True,
|
||||
},
|
||||
'rev': {
|
||||
'ease4': 1.3,
|
||||
'fuzz': 0.05,
|
||||
'minSpace': 1,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
class GroupConfig(object):
|
||||
|
|
|
@ -57,7 +57,7 @@ class Scheduler(object):
|
|||
"Does not include fetched but unanswered."
|
||||
return (self.newCount, self.lrnCount, self.revCount)
|
||||
|
||||
def cardQueue(self, card):
|
||||
def countIdx(self, card):
|
||||
return card.queue
|
||||
|
||||
def onClose(self):
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# coding: utf-8
|
||||
|
||||
import time
|
||||
import time, copy
|
||||
from tests.shared import assertException, getEmptyDeck
|
||||
from anki.stdmodels import BasicModel
|
||||
from anki.utils import stripHTML, intTime
|
||||
|
@ -152,7 +152,6 @@ def test_reviews():
|
|||
c.startTimer()
|
||||
c.flush()
|
||||
# save it for later use as well
|
||||
import copy
|
||||
cardcopy = copy.copy(c)
|
||||
# failing it should put it in the learn queue with the default options
|
||||
##################################################
|
||||
|
@ -270,7 +269,7 @@ def test_nextIvl():
|
|||
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"
|
||||
assert d.sched.nextIvlStr(c, 4) == "10.8 months"
|
||||
|
||||
def test_misc():
|
||||
d = getEmptyDeck()
|
||||
|
@ -308,9 +307,32 @@ def test_cram():
|
|||
f = d.newFact()
|
||||
f['Front'] = u"one"
|
||||
d.addFact(f)
|
||||
f = d.newFact()
|
||||
f['Front'] = u"two"
|
||||
d.addFact(f)
|
||||
d.cramGroups(1)
|
||||
|
||||
|
||||
c = f.cards()[0]
|
||||
c.ivl = 100
|
||||
c.type = c.queue = 2
|
||||
c.due = d.sched.today + 50
|
||||
c.mod = 1
|
||||
c.flush()
|
||||
d.cramGroups([1])
|
||||
assert d.sched.counts() == (1, 0, 0)
|
||||
c = d.sched.getCard()
|
||||
assert d.sched.counts() == (0, 0, 0)
|
||||
# check that estimates work
|
||||
assert d.sched.nextIvl(c, 1) == 30
|
||||
assert d.sched.nextIvl(c, 2) == 180
|
||||
print "fixme"
|
||||
print d.sched.nextIvl(c, 3) == 86400*100
|
||||
# answer it
|
||||
d.sched.answerCard(c, 2)
|
||||
delta = c.due - time.time()
|
||||
assert delta > 175 and delta <= 180
|
||||
# another two answers should reschedule it
|
||||
assert c.queue == 1
|
||||
d.sched.answerCard(c, 2)
|
||||
d.sched.answerCard(c, 2)
|
||||
assert c.queue == -3
|
||||
print "fixme"
|
||||
assert c.ivl == 100
|
||||
# and if the queue is reset, it shouldn't appear in the new queue again
|
||||
d.reset()
|
||||
assert d.sched.counts() == (0, 0, 0)
|
||||
|
|
Loading…
Reference in a new issue