diff --git a/anki/decks.py b/anki/decks.py index 6d3a58b59..fe1c980bb 100644 --- a/anki/decks.py +++ b/anki/decks.py @@ -76,6 +76,7 @@ defaultConf = { 'maxIvl': 36500, # may not be set on old decks 'bury': False, + 'hardFactor': 1.2, }, 'maxTaken': 60, 'timer': 0, diff --git a/anki/schedv2.py b/anki/schedv2.py index 2fc9dda49..d310117ec 100644 --- a/anki/schedv2.py +++ b/anki/schedv2.py @@ -898,7 +898,12 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" delay = self._daysLate(card) conf = self._revConf(card) fct = card.factor / 1000 - ivl2 = self._constrainedIvl(card.ivl * 1.2, conf, card.ivl, fuzz) + hardFactor = conf.get("hardFactor", 1.2) + if hardFactor > 1: + hardMin = card.ivl + else: + hardMin = 0 + ivl2 = self._constrainedIvl(card.ivl * hardFactor, conf, hardMin, fuzz) if ease == 2: return ivl2 @@ -963,9 +968,10 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" minNewIvl = 1 if ease == 2: - factor = 1.2 + factor = conf.get("hardFactor", 1.2) # hard cards shouldn't have their interval decreased by more than 50% - minNewIvl = 0.5 + # of the normal factor + minNewIvl = factor / 2 elif ease == 3: factor = card.factor / 1000 else: # ease == 4: diff --git a/aqt/deckconf.py b/aqt/deckconf.py index c176b5fdf..e26a40187 100644 --- a/aqt/deckconf.py +++ b/aqt/deckconf.py @@ -185,6 +185,10 @@ class DeckConf(QDialog): f.maxIvl.setValue(c['maxIvl']) f.revplim.setText(self.parentLimText('rev')) f.buryRev.setChecked(c.get("bury", True)) + f.hardFactor.setValue(int(c.get("hardFactor", 1.2)*100)) + if self.mw.col.schedVer() == 1: + f.hardFactor.setVisible(False) + f.hardFactorLabel.setVisible(False) # lapse c = self.conf['lapse'] f.lapSteps.setText(self.listToUser(c['delays'])) @@ -267,6 +271,7 @@ class DeckConf(QDialog): c['ivlFct'] = f.fi1.value()/100.0 c['maxIvl'] = f.maxIvl.value() c['bury'] = f.buryRev.isChecked() + c['hardFactor'] = f.hardFactor.value()/100.0 # lapse c = self.conf['lapse'] self.updateList(c, 'delays', f.lapSteps, minSize=0) diff --git a/designer/dconf.ui b/designer/dconf.ui index 141b9d1b0..26eb6cc90 100644 --- a/designer/dconf.ui +++ b/designer/dconf.ui @@ -77,7 +77,16 @@ New Cards - + + 12 + + + 12 + + + 12 + + 12 @@ -227,7 +236,16 @@ Reviews - + + 12 + + + 12 + + + 12 + + 12 @@ -343,13 +361,30 @@ - + Bury related reviews until the next day + + + + Hard interval + + + + + + + 5 + + + 120 + + + @@ -372,7 +407,16 @@ Lapses - + + 12 + + + 12 + + + 12 + + 12 @@ -521,7 +565,16 @@ General - + + 12 + + + 12 + + + 12 + + 12 @@ -605,7 +658,16 @@ 12 - + + 12 + + + 12 + + + 12 + + 12 @@ -649,6 +711,7 @@ easyBonus fi1 maxIvl + hardFactor buryRev lapSteps lapMult @@ -659,7 +722,6 @@ showTimer autoplaySounds replayQuestion - buttonBox desc diff --git a/tests/test_schedv2.py b/tests/test_schedv2.py index 5e5f68a9b..96c0d48ee 100644 --- a/tests/test_schedv2.py +++ b/tests/test_schedv2.py @@ -451,6 +451,11 @@ def test_button_spacing(): assert ni(c, 3) == "3 days" assert ni(c, 4) == "4 days" + # if hard factor is <= 1, then hard may not increase + conf = d.decks.confForDid(1) + conf['rev']['hardFactor'] = 1 + assert ni(c, 2) == "1 day" + def test_overdue_lapse(): # disabled in commit 3069729776990980f34c25be66410e947e9d51a2 return @@ -695,7 +700,7 @@ def test_filt_reviewing_early_normal(): d.reset() c = d.sched.getCard() - assert d.sched.nextIvl(c, 2) == 50*86400 + assert d.sched.nextIvl(c, 2) == 60*86400 assert d.sched.nextIvl(c, 3) == 100*86400 assert d.sched.nextIvl(c, 4) == 101*86400