From a473908dca79568bff1a7d8300cb62120cea2984 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:43:57 -0800 Subject: [PATCH 01/38] Adding constants for decks' type --- pylib/anki/consts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 89e9ba13a..6d69f6151 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -27,6 +27,8 @@ COUNT_REMAINING = 1 MEDIA_ADD = 0 MEDIA_REM = 1 +# Kind of decks + # dynamic deck order DYN_OLDEST = 0 DYN_RANDOM = 1 From 98e55e26bc299179777c7fed765fca2fed7f19ab Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:44:57 -0800 Subject: [PATCH 02/38] use DECK_STD --- pylib/anki/consts.py | 1 + pylib/anki/decks.py | 2 +- pylib/anki/storage.py | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 6d69f6151..a8d4a99b6 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -28,6 +28,7 @@ MEDIA_ADD = 0 MEDIA_REM = 1 # Kind of decks +DECK_STD = 0 # dynamic deck order DYN_OLDEST = 0 diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index c2998896f..14031c454 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -27,7 +27,7 @@ defaultDeck = { "conf": 1, "usn": 0, "desc": "", - "dyn": 0, # anki uses int/bool interchangably here + "dyn": DECK_STD, # anki uses int/bool interchangably here "collapsed": False, # added in beta11 "extendNew": 10, diff --git a/pylib/anki/storage.py b/pylib/anki/storage.py index b3099780e..3950e77a6 100644 --- a/pylib/anki/storage.py +++ b/pylib/anki/storage.py @@ -111,7 +111,7 @@ def _upgrade(col, ver) -> None: if ver < 3: # new deck properties for d in col.decks.all(): - d["dyn"] = 0 + d["dyn"] = DECK_STD d["collapsed"] = False col.decks.save(d) if ver < 4: From 957dc51fca0951957a339b4f07576ccd84616ddb Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:45:41 -0800 Subject: [PATCH 03/38] DECK_DYN --- pylib/anki/consts.py | 1 + pylib/anki/decks.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index a8d4a99b6..c35260c83 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -29,6 +29,7 @@ MEDIA_REM = 1 # Kind of decks DECK_STD = 0 +DECK_DYN = 1 # dynamic deck order DYN_OLDEST = 0 diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index 14031c454..94072fd90 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -40,7 +40,7 @@ defaultDynamicDeck = { "lrnToday": [0, 0], "timeToday": [0, 0], "collapsed": False, - "dyn": 1, + "dyn": DECK_DYN, "desc": "", "usn": 0, "delays": None, From a2eea7a1bb88a3fbc70542e51fe035e265def5bb Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:48:37 -0800 Subject: [PATCH 04/38] UPDATE_MODE --- pylib/anki/importing/noteimp.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pylib/anki/importing/noteimp.py b/pylib/anki/importing/noteimp.py index eb11504cc..eba6fd23a 100644 --- a/pylib/anki/importing/noteimp.py +++ b/pylib/anki/importing/noteimp.py @@ -52,9 +52,10 @@ class ForeignCard: # If the first field of the model is not in the map, the map is invalid. # The import mode is one of: -# 0: update if first field matches existing note +# UPDATE_MODE: update if first field matches existing note # 1: ignore if first field matches existing note # 2: import even if first field matches existing note +UPDATE_MODE = 0 class NoteImporter(Importer): @@ -62,7 +63,7 @@ class NoteImporter(Importer): needMapper = True needDelimiter = False allowHTML = False - importMode = 0 + importMode = UPDATE_MODE mapping: Optional[List[str]] tagModified: Optional[str] @@ -168,7 +169,7 @@ class NoteImporter(Importer): if fld0 == sflds[0]: # duplicate found = True - if self.importMode == 0: + if self.importMode == UPDATE_MODE: data = self.updateData(n, id, sflds) if data: updates.append(data) @@ -214,7 +215,7 @@ class NoteImporter(Importer): ngettext("%d note updated", "%d notes updated", self.updateCount) % self.updateCount ) - if self.importMode == 0: + if self.importMode == UPDATE_MODE: unchanged = dupeCount - self.updateCount elif self.importMode == 1: unchanged = dupeCount From cb7429c4337941913bb01767fbf74c8e0ccc6c11 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:49:11 -0800 Subject: [PATCH 05/38] IGNORE_MODE --- pylib/anki/importing/noteimp.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pylib/anki/importing/noteimp.py b/pylib/anki/importing/noteimp.py index eba6fd23a..648563947 100644 --- a/pylib/anki/importing/noteimp.py +++ b/pylib/anki/importing/noteimp.py @@ -53,9 +53,10 @@ class ForeignCard: # The import mode is one of: # UPDATE_MODE: update if first field matches existing note -# 1: ignore if first field matches existing note +# IGNORE_MODE: ignore if first field matches existing note # 2: import even if first field matches existing note UPDATE_MODE = 0 +IGNORE_MODE = 1 class NoteImporter(Importer): @@ -176,7 +177,7 @@ class NoteImporter(Importer): updateLog.append(updateLogTxt % fld0) dupeCount += 1 found = True - elif self.importMode == 1: + elif self.importMode == IGNORE_MODE: dupeCount += 1 elif self.importMode == 2: # allow duplicates in this case @@ -217,7 +218,7 @@ class NoteImporter(Importer): ) if self.importMode == UPDATE_MODE: unchanged = dupeCount - self.updateCount - elif self.importMode == 1: + elif self.importMode == IGNORE_MODE: unchanged = dupeCount else: unchanged = 0 From 8eaed49fd420127fde238ec9c36a5345af5de736 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:50:12 -0800 Subject: [PATCH 06/38] ADD_MODE --- pylib/anki/importing/noteimp.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/pylib/anki/importing/noteimp.py b/pylib/anki/importing/noteimp.py index 648563947..364d13bcd 100644 --- a/pylib/anki/importing/noteimp.py +++ b/pylib/anki/importing/noteimp.py @@ -54,9 +54,10 @@ class ForeignCard: # The import mode is one of: # UPDATE_MODE: update if first field matches existing note # IGNORE_MODE: ignore if first field matches existing note -# 2: import even if first field matches existing note +# ADD_MODE: import even if first field matches existing note UPDATE_MODE = 0 IGNORE_MODE = 1 +ADD_MODE = 2 class NoteImporter(Importer): @@ -155,7 +156,7 @@ class NoteImporter(Importer): self.log.append(_("Empty first field: %s") % " ".join(n.fields)) continue # earlier in import? - if fld0 in firsts and self.importMode != 2: + if fld0 in firsts and self.importMode != ADD_MODE: # duplicates in source file; log and ignore self.log.append(_("Appeared twice in file: %s") % fld0) continue @@ -179,7 +180,7 @@ class NoteImporter(Importer): found = True elif self.importMode == IGNORE_MODE: dupeCount += 1 - elif self.importMode == 2: + elif self.importMode == ADD_MODE: # allow duplicates in this case if fld0 not in dupes: # only show message once, no matter how many From da39ef378c994b139636e02896045cc6c8830e52 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:53:52 -0800 Subject: [PATCH 07/38] radioNew --- qt/aqt/customstudy.py | 4 ++-- qt/designer/customstudy.ui | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index 8416fd212..2fcbbcf51 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -32,12 +32,12 @@ class CustomStudy(QDialog): f.setupUi(self) self.setWindowModality(Qt.WindowModal) self.setupSignals() - f.radio1.click() + f.radioNew.click() self.exec_() def setupSignals(self): f = self.form - f.radio1.clicked.connect(lambda: self.onRadioChange(1)) + f.radioNew.clicked.connect(lambda: self.onRadioChange(RADIO_NEW)) f.radio2.clicked.connect(lambda: self.onRadioChange(2)) f.radio3.clicked.connect(lambda: self.onRadioChange(3)) f.radio4.clicked.connect(lambda: self.onRadioChange(4)) diff --git a/qt/designer/customstudy.ui b/qt/designer/customstudy.ui index a2638641f..34832f69a 100644 --- a/qt/designer/customstudy.ui +++ b/qt/designer/customstudy.ui @@ -31,7 +31,7 @@ - + Increase today's new card limit @@ -163,7 +163,7 @@ - radio1 + radioNew radio2 radio3 radio4 From c3bd16795828aae5d301f802c83ca359f04ec532 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:54:26 -0800 Subject: [PATCH 08/38] radiorRev --- qt/aqt/customstudy.py | 2 +- qt/designer/customstudy.ui | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index 2fcbbcf51..a4ffb08f9 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -38,7 +38,7 @@ class CustomStudy(QDialog): def setupSignals(self): f = self.form f.radioNew.clicked.connect(lambda: self.onRadioChange(RADIO_NEW)) - f.radio2.clicked.connect(lambda: self.onRadioChange(2)) + f.radioRev.clicked.connect(lambda: self.onRadioChange(RADIO_REV)) f.radio3.clicked.connect(lambda: self.onRadioChange(3)) f.radio4.clicked.connect(lambda: self.onRadioChange(4)) f.radio5.clicked.connect(lambda: self.onRadioChange(5)) diff --git a/qt/designer/customstudy.ui b/qt/designer/customstudy.ui index 34832f69a..73ef4f5c6 100644 --- a/qt/designer/customstudy.ui +++ b/qt/designer/customstudy.ui @@ -38,7 +38,7 @@ - + Increase today's review card limit @@ -164,7 +164,7 @@ radioNew - radio2 + radioRev radio3 radio4 radio6 From 20bb24a641ae9d07f296231469a83242043b5cbc Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:55:01 -0800 Subject: [PATCH 09/38] radioForgot --- qt/aqt/customstudy.py | 2 +- qt/designer/customstudy.ui | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index a4ffb08f9..d48538531 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -39,7 +39,7 @@ class CustomStudy(QDialog): f = self.form f.radioNew.clicked.connect(lambda: self.onRadioChange(RADIO_NEW)) f.radioRev.clicked.connect(lambda: self.onRadioChange(RADIO_REV)) - f.radio3.clicked.connect(lambda: self.onRadioChange(3)) + f.radioForgot.clicked.connect(lambda: self.onRadioChange(RADIO_FORGOT)) f.radio4.clicked.connect(lambda: self.onRadioChange(4)) f.radio5.clicked.connect(lambda: self.onRadioChange(5)) f.radio6.clicked.connect(lambda: self.onRadioChange(6)) diff --git a/qt/designer/customstudy.ui b/qt/designer/customstudy.ui index 73ef4f5c6..b926de17e 100644 --- a/qt/designer/customstudy.ui +++ b/qt/designer/customstudy.ui @@ -24,7 +24,7 @@ - + Review forgotten cards @@ -165,7 +165,7 @@ radioNew radioRev - radio3 + radioForgot radio4 radio6 spin From 7e0b4522fbffecd6f2969777ef0c70fce715f727 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:57:06 -0800 Subject: [PATCH 10/38] radioAhead --- qt/aqt/customstudy.py | 2 +- qt/designer/customstudy.ui | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index d48538531..7c17a57e1 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -40,7 +40,7 @@ class CustomStudy(QDialog): f.radioNew.clicked.connect(lambda: self.onRadioChange(RADIO_NEW)) f.radioRev.clicked.connect(lambda: self.onRadioChange(RADIO_REV)) f.radioForgot.clicked.connect(lambda: self.onRadioChange(RADIO_FORGOT)) - f.radio4.clicked.connect(lambda: self.onRadioChange(4)) + f.radioAhead.clicked.connect(lambda: self.onRadioChange(RADIO_AHEAD)) f.radio5.clicked.connect(lambda: self.onRadioChange(5)) f.radio6.clicked.connect(lambda: self.onRadioChange(6)) diff --git a/qt/designer/customstudy.ui b/qt/designer/customstudy.ui index b926de17e..145da6cf2 100644 --- a/qt/designer/customstudy.ui +++ b/qt/designer/customstudy.ui @@ -17,7 +17,7 @@ - + Review ahead @@ -166,7 +166,7 @@ radioNew radioRev radioForgot - radio4 + radioAhead radio6 spin buttonBox From fc7636c1945bf7d5d5a153389b9e77532f1238a9 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:57:52 -0800 Subject: [PATCH 11/38] radioPreview --- qt/aqt/customstudy.py | 2 +- qt/designer/customstudy.ui | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index 7c17a57e1..c2c2512bf 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -41,7 +41,7 @@ class CustomStudy(QDialog): f.radioRev.clicked.connect(lambda: self.onRadioChange(RADIO_REV)) f.radioForgot.clicked.connect(lambda: self.onRadioChange(RADIO_FORGOT)) f.radioAhead.clicked.connect(lambda: self.onRadioChange(RADIO_AHEAD)) - f.radio5.clicked.connect(lambda: self.onRadioChange(5)) + f.radioPreview.clicked.connect(lambda: self.onRadioChange(RADIO_PREVIEW)) f.radio6.clicked.connect(lambda: self.onRadioChange(6)) def onRadioChange(self, idx): diff --git a/qt/designer/customstudy.ui b/qt/designer/customstudy.ui index 145da6cf2..803fd30d5 100644 --- a/qt/designer/customstudy.ui +++ b/qt/designer/customstudy.ui @@ -52,7 +52,7 @@ - + Preview new cards @@ -167,6 +167,7 @@ radioRev radioForgot radioAhead + radioPreview radio6 spin buttonBox From 25c579926b10fdfacc7032e4118a4cfa13f30d5b Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 16:59:03 -0800 Subject: [PATCH 12/38] radioCram --- qt/aqt/customstudy.py | 2 +- qt/designer/customstudy.ui | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/qt/aqt/customstudy.py b/qt/aqt/customstudy.py index c2c2512bf..ffe8571c1 100644 --- a/qt/aqt/customstudy.py +++ b/qt/aqt/customstudy.py @@ -42,7 +42,7 @@ class CustomStudy(QDialog): f.radioForgot.clicked.connect(lambda: self.onRadioChange(RADIO_FORGOT)) f.radioAhead.clicked.connect(lambda: self.onRadioChange(RADIO_AHEAD)) f.radioPreview.clicked.connect(lambda: self.onRadioChange(RADIO_PREVIEW)) - f.radio6.clicked.connect(lambda: self.onRadioChange(6)) + f.radioCram.clicked.connect(lambda: self.onRadioChange(RADIO_CRAM)) def onRadioChange(self, idx): f = self.form diff --git a/qt/designer/customstudy.ui b/qt/designer/customstudy.ui index 803fd30d5..e2fae9dc9 100644 --- a/qt/designer/customstudy.ui +++ b/qt/designer/customstudy.ui @@ -45,7 +45,7 @@ - + Study by card state or tag @@ -168,7 +168,7 @@ radioForgot radioAhead radioPreview - radio6 + radioCram spin buttonBox From 72f8ae7b33b4680c8c38f34fcb0ac8d62cf63750 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 17:02:31 -0800 Subject: [PATCH 13/38] Add leech constants --- pylib/anki/consts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index c35260c83..7b996cd4e 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -59,6 +59,8 @@ SYNC_VER = 9 HELP_SITE = "http://ankisrs.net/docs/manual.html" +# Leech actions + # Labels ########################################################################## From dadf9042f77ef128686624c2d0a84534c3ff8aaa Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 17:03:51 -0800 Subject: [PATCH 14/38] LEECH_SUSPEND --- pylib/anki/consts.py | 1 + pylib/anki/decks.py | 2 +- pylib/anki/sched.py | 2 +- pylib/anki/schedv2.py | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 7b996cd4e..aa67cca5b 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -60,6 +60,7 @@ SYNC_VER = 9 HELP_SITE = "http://ankisrs.net/docs/manual.html" # Leech actions +LEECH_SUSPEND = 0 # Labels ########################################################################## diff --git a/pylib/anki/decks.py b/pylib/anki/decks.py index 94072fd90..58d605996 100644 --- a/pylib/anki/decks.py +++ b/pylib/anki/decks.py @@ -71,7 +71,7 @@ defaultConf = { "minInt": 1, "leechFails": 8, # type 0=suspend, 1=tagonly - "leechAction": 0, + "leechAction": LEECH_SUSPEND, }, "rev": { "perDay": 200, diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 2a77e38c2..eebb6f541 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -1145,7 +1145,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?""" f.flush() # handle a = conf["leechAction"] - if a == 0: + if a == LEECH_SUSPEND: # if it has an old due, remove it from cram/relearning if card.odue: card.due = card.odue diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 8ce085f58..444190bb1 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -1284,7 +1284,7 @@ where id = ? f.flush() # handle a = conf["leechAction"] - if a == 0: + if a == LEECH_SUSPEND: card.queue = -1 # notify UI hooks.card_did_leech(card) From 8264be1964ffce2b9109e458daf3875f0e6efabc Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 18:07:52 -0800 Subject: [PATCH 15/38] LEECH_TAGONLY --- pylib/anki/consts.py | 1 + 1 file changed, 1 insertion(+) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index aa67cca5b..79763fedf 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -61,6 +61,7 @@ HELP_SITE = "http://ankisrs.net/docs/manual.html" # Leech actions LEECH_SUSPEND = 0 +LEECH_TAGONLY = 1 # Labels ########################################################################## From be148ce8a189b4aee1e701aeed7983f7f4d7ad5a Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 17:04:33 -0800 Subject: [PATCH 16/38] Adding constants for buttons The point being that, when we read BUTTON_ONE, we know that the type of the element is: a button --- pylib/anki/consts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 79763fedf..e917f6d8a 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -63,6 +63,8 @@ HELP_SITE = "http://ankisrs.net/docs/manual.html" LEECH_SUSPEND = 0 LEECH_TAGONLY = 1 +# Buttons + # Labels ########################################################################## From 5104cac97f9d08e218d03edf321e25d7f6d16c21 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 17:05:51 -0800 Subject: [PATCH 17/38] BUTTON_ONE --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 6 +++--- pylib/anki/schedv2.py | 10 +++++----- 3 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index e917f6d8a..e7618fa16 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -64,6 +64,7 @@ LEECH_SUSPEND = 0 LEECH_TAGONLY = 1 # Buttons +BUTTON_ONE = 1 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index eebb6f541..d2ca09ed0 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -874,7 +874,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" def _answerRevCard(self, card, ease): delay = 0 - if ease == 1: + if ease == BUTTON_ONE: delay = self._rescheduleLapse(card) else: self._rescheduleRev(card, ease) @@ -1349,7 +1349,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" "Return the next interval for CARD, in seconds." if card.queue in (0, 1, 3): return self._nextLrnIvl(card, ease) - elif ease == 1: + elif ease == BUTTON_ONE: # lapsed conf = self._lapseConf(card) if conf["delays"]: @@ -1364,7 +1364,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" if card.queue == 0: card.left = self._startingLeft(card) conf = self._lrnConf(card) - if ease == 1: + if ease == BUTTON_ONE: # fail return self._delayForGrade(conf, len(conf["delays"])) elif ease == 3: diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 444190bb1..dcdfe54d8 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -121,7 +121,7 @@ class Scheduler: def _answerCardPreview(self, card: Card, ease: int) -> None: assert 1 <= ease <= 2 - if ease == 1: + if ease == BUTTON_ONE: # repeat after delay card.queue = QUEUE_TYPE_PREVIEW card.due = intTime() + self._previewDelay(card) @@ -962,7 +962,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" early = bool(card.odid and (card.odue > self.today)) type = early and 3 or 1 - if ease == 1: + if ease == BUTTON_ONE: delay = self._rescheduleLapse(card) else: self._rescheduleRev(card, ease, early) @@ -1557,14 +1557,14 @@ To study outside of the normal schedule, click the Custom Study button below.""" "Return the next interval for CARD, in seconds." # preview mode? if self._previewingCard(card): - if ease == 1: + if ease == BUTTON_ONE: return self._previewDelay(card) return 0 # (re)learning? if card.queue in (0, 1, QUEUE_TYPE_DAY_LEARN_RELEARN): return self._nextLrnIvl(card, ease) - elif ease == 1: + elif ease == BUTTON_ONE: # lapse conf = self._lapseConf(card) if conf["delays"]: @@ -1583,7 +1583,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" if card.queue == 0: card.left = self._startingLeft(card) conf = self._lrnConf(card) - if ease == 1: + if ease == BUTTON_ONE: # fail return self._delayForGrade(conf, len(conf["delays"])) elif ease == 2: From 4fb0a48962b8cbb3f902b026019f8e1518ed49f3 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 17:07:17 -0800 Subject: [PATCH 18/38] BUTTON_TWO --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 6 +++--- pylib/anki/schedv2.py | 11 ++++++----- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index e7618fa16..e8625d07e 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -65,6 +65,7 @@ LEECH_TAGONLY = 1 # Buttons BUTTON_ONE = 1 +BUTTON_TWO = 2 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index d2ca09ed0..f2428b07c 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -569,12 +569,12 @@ did = ? and queue = 3 and due <= ? limit ?""", self._rescheduleAsRev(card, conf, True) leaving = True # graduation time? - elif ease == 2 and (card.left % 1000) - 1 <= 0: + elif ease == BUTTON_TWO and (card.left % 1000) - 1 <= 0: self._rescheduleAsRev(card, conf, False) leaving = True else: # one step towards graduation - if ease == 2: + if ease == BUTTON_TWO: # decrement real left count and recalculate left today left = (card.left % 1000) - 1 card.left = self._leftToday(conf["delays"], left) * 1000 + left @@ -969,7 +969,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" ivl4 = self._constrainedIvl( (card.ivl + delay) * fct * conf["ease4"], conf, ivl3 ) - if ease == 2: + if ease == BUTTON_TWO: interval = ivl2 elif ease == 3: interval = ivl3 diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index dcdfe54d8..8b9885e90 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -127,6 +127,7 @@ class Scheduler: card.due = intTime() + self._previewDelay(card) self.lrnCount += 1 else: + # BUTTON_TWO # restore original card state and remove from filtered deck self._restorePreviewCard(card) self._removeFromFiltered(card) @@ -627,7 +628,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", leaving = True else: self._moveToNextStep(card, conf) - elif ease == 2: + elif ease == BUTTON_TWO: self._repeatStep(card, conf) else: # back to first step @@ -801,7 +802,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", if leaving: ivl = card.ivl else: - if ease == 2: + if ease == BUTTON_TWO: ivl = -self._delayForRepeatingGrade(conf, card.left) else: ivl = -self._delayForGrade(conf, card.left) @@ -1047,7 +1048,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" else: hardMin = 0 ivl2 = self._constrainedIvl(card.ivl * hardFactor, conf, hardMin, fuzz) - if ease == 2: + if ease == BUTTON_TWO: return ivl2 ivl3 = self._constrainedIvl((card.ivl + delay // 2) * fct, conf, ivl2, fuzz) @@ -1113,7 +1114,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" # early 3/4 reviews shouldn't decrease previous interval minNewIvl = 1 - if ease == 2: + if ease == BUTTON_TWO: factor = conf.get("hardFactor", 1.2) # hard cards shouldn't have their interval decreased by more than 50% # of the normal factor @@ -1586,7 +1587,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" if ease == BUTTON_ONE: # fail return self._delayForGrade(conf, len(conf["delays"])) - elif ease == 2: + elif ease == BUTTON_TWO: return self._delayForRepeatingGrade(conf, card.left) elif ease == 4: return self._graduatingIvl(card, conf, True, fuzz=False) * 86400 From e4022eeb478810eaa85d699a05899a22916ea5a6 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 17:07:56 -0800 Subject: [PATCH 19/38] BUTTON_THREE --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 6 +++--- pylib/anki/schedv2.py | 8 ++++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index e8625d07e..778e44d87 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -66,6 +66,7 @@ LEECH_TAGONLY = 1 # Buttons BUTTON_ONE = 1 BUTTON_TWO = 2 +BUTTON_THREE = 3 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index f2428b07c..5ad5ecf82 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -565,7 +565,7 @@ did = ? and queue = 3 and due <= ? limit ?""", # lrnCount was decremented once when card was fetched lastLeft = card.left # immediate graduate? - if ease == 3: + if ease == BUTTON_THREE: self._rescheduleAsRev(card, conf, True) leaving = True # graduation time? @@ -971,7 +971,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" ) if ease == BUTTON_TWO: interval = ivl2 - elif ease == 3: + elif ease == BUTTON_THREE: interval = ivl3 elif ease == 4: interval = ivl4 @@ -1367,7 +1367,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" if ease == BUTTON_ONE: # fail return self._delayForGrade(conf, len(conf["delays"])) - elif ease == 3: + elif ease == BUTTON_THREE: # early removal if not self._resched(card): return 0 diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 8b9885e90..e0a8dd2dc 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -621,7 +621,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", self._rescheduleAsRev(card, conf, True) leaving = True # next step? - elif ease == 3: + elif ease == BUTTON_THREE: # graduation time? if (card.left % 1000) - 1 <= 0: self._rescheduleAsRev(card, conf, False) @@ -1052,7 +1052,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" return ivl2 ivl3 = self._constrainedIvl((card.ivl + delay // 2) * fct, conf, ivl2, fuzz) - if ease == 3: + if ease == BUTTON_THREE: return ivl3 ivl4 = self._constrainedIvl( @@ -1119,7 +1119,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" # hard cards shouldn't have their interval decreased by more than 50% # of the normal factor minNewIvl = factor / 2 - elif ease == 3: + elif ease == BUTTON_THREE: factor = card.factor / 1000 else: # ease == 4: factor = card.factor / 1000 @@ -1591,7 +1591,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" return self._delayForRepeatingGrade(conf, card.left) elif ease == 4: return self._graduatingIvl(card, conf, True, fuzz=False) * 86400 - else: # ease == 3 + else: # ease == BUTTON_THREE left = card.left % 1000 - 1 if left <= 0: # graduate From 4d088e14c799776c041d8e62b5e2c491a7d6741e Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 17:08:23 -0800 Subject: [PATCH 20/38] BUTTON_FOUR --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 2 +- pylib/anki/schedv2.py | 6 +++--- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 778e44d87..1e01829b2 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -67,6 +67,7 @@ LEECH_TAGONLY = 1 BUTTON_ONE = 1 BUTTON_TWO = 2 BUTTON_THREE = 3 +BUTTON_FOUR = 4 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 5ad5ecf82..1d8c1b6d8 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -973,7 +973,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" interval = ivl2 elif ease == BUTTON_THREE: interval = ivl3 - elif ease == 4: + elif ease == BUTTON_FOUR: interval = ivl4 # interval capped? return min(interval, conf["maxIvl"]) diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index e0a8dd2dc..60073125d 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -617,7 +617,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", leaving = False # immediate graduate? - if ease == 4: + if ease == BUTTON_FOUR: self._rescheduleAsRev(card, conf, True) leaving = True # next step? @@ -1121,7 +1121,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" minNewIvl = factor / 2 elif ease == BUTTON_THREE: factor = card.factor / 1000 - else: # ease == 4: + else: # ease == BUTTON_FOUR: factor = card.factor / 1000 ease4 = conf["ease4"] # 1.3 -> 1.15 @@ -1589,7 +1589,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" return self._delayForGrade(conf, len(conf["delays"])) elif ease == BUTTON_TWO: return self._delayForRepeatingGrade(conf, card.left) - elif ease == 4: + elif ease == BUTTON_FOUR: return self._graduatingIvl(card, conf, True, fuzz=False) * 86400 else: # ease == BUTTON_THREE left = card.left % 1000 - 1 From dd258ca62c575cd22e7f79f21cc33fb06cd6d9fa Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 18:01:31 -0800 Subject: [PATCH 21/38] Add revlog constants --- pylib/anki/consts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 1e01829b2..bbb2bfae2 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -69,6 +69,8 @@ BUTTON_TWO = 2 BUTTON_THREE = 3 BUTTON_FOUR = 4 +# Revlog types + # Labels ########################################################################## From dca1cd03d1e6467471ce7096b2091638193cae6f Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 18:03:11 -0800 Subject: [PATCH 22/38] REVLOG_LRN --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 2 +- pylib/anki/schedv2.py | 2 +- pylib/anki/stats.py | 21 +++++++++++---------- 4 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index bbb2bfae2..001bf7a46 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -70,6 +70,7 @@ BUTTON_THREE = 3 BUTTON_FOUR = 4 # Revlog types +REVLOG_LRN = 0 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 1d8c1b6d8..530368875 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -560,7 +560,7 @@ did = ? and queue = 3 and due <= ? limit ?""", elif card.type == 2: type = 2 else: - type = 0 + type = REVLOG_LRN leaving = False # lrnCount was decremented once when card was fetched lastLeft = card.left diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 60073125d..6b11a5e5a 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -610,7 +610,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", if card.type in (2, CARD_TYPE_RELEARNING): type = 2 else: - type = 0 + type = REVLOG_LRN # lrnCount was decremented once when card was fetched lastLeft = card.left diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index 50a4ccf7c..b2a6f8bd9 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -6,6 +6,7 @@ import json import time from typing import Any, Dict, List, Optional, Tuple +from anki.consts import * from anki.lang import _, ngettext from anki.utils import fmtTimeSpan, ids2str @@ -149,10 +150,10 @@ body {background-image: url(data:image/png;base64,%s); } if lim: lim = " and " + lim cards, thetime, failed, lrn, rev, relrn, filt = self.col.db.first( - """ + f""" select count(), sum(time)/1000, sum(case when ease = 1 then 1 else 0 end), /* failed */ -sum(case when type = 0 then 1 else 0 end), /* learning */ +sum(case when type = {REVLOG_LRN} then 1 else 0 end), /* learning */ sum(case when type = 1 then 1 else 0 end), /* review */ sum(case when type = 2 then 1 else 0 end), /* relearn */ sum(case when type = 3 then 1 else 0 end) /* filter */ @@ -544,15 +545,15 @@ group by day order by day""" else: tf = 3600.0 # hours return self.col.db.all( - """ + f""" select (cast((id/1000.0 - :cut) / 86400.0 as int))/:chunk as day, -sum(case when type = 0 then 1 else 0 end), -- lrn count +sum(case when type = {REVLOG_LRN} then 1 else 0 end), -- lrn count sum(case when type = 1 and lastIvl < 21 then 1 else 0 end), -- yng count sum(case when type = 1 and lastIvl >= 21 then 1 else 0 end), -- mtr count sum(case when type = 2 then 1 else 0 end), -- lapse count sum(case when type = 3 then 1 else 0 end), -- cram count -sum(case when type = 0 then time/1000.0 else 0 end)/:tf, -- lrn time +sum(case when type = {REVLOG_LRN} then time/1000.0 else 0 end)/:tf, -- lrn time -- yng + mtr time sum(case when type = 1 and lastIvl < 21 then time/1000.0 else 0 end)/:tf, sum(case when type = 1 and lastIvl >= 21 then time/1000.0 else 0 end)/:tf, @@ -755,12 +756,12 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" else: ease4repl = "ease" return self.col.db.all( - """ + f""" select (case -when type in (0,2) then 0 +when type in ({REVLOG_LRN},2) then 0 when lastIvl < 21 then 1 else 2 end) as thetype, -(case when type in (0,2) and ease = 4 then %s else ease end), count() from revlog %s +(case when type in ({REVLOG_LRN},2) and ease = 4 then %s else ease end), count() from revlog %s group by thetype, ease order by thetype, ease""" % (ease4repl, lim) @@ -849,13 +850,13 @@ order by thetype, ease""" if pd: lim += " and id > %d" % ((self.col.sched.dayCutoff - (86400 * pd)) * 1000) return self.col.db.all( - """ + f""" select 23 - ((cast((:cut - id/1000) / 3600.0 as int)) %% 24) as hour, sum(case when ease = 1 then 0 else 1 end) / cast(count() as float) * 100, count() -from revlog where type in (0,1,2) %s +from revlog where type in ({REVLOG_LRN},1,2) %s group by hour having count() > 30 order by hour""" % lim, cut=self.col.sched.dayCutoff - (rolloverHour * 3600), From dd5d73f3a3eda0dfe6d4f89a70d2a0d8b48f29b7 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 18:04:10 -0800 Subject: [PATCH 23/38] REVLOG_REV --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 2 +- pylib/anki/schedv2.py | 2 +- pylib/anki/stats.py | 12 ++++++------ 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 001bf7a46..22da0d552 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -71,6 +71,7 @@ BUTTON_FOUR = 4 # Revlog types REVLOG_LRN = 0 +REVLOG_REV = 1 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 530368875..04b65ba4c 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -946,7 +946,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" card.lastIvl, card.factor, card.timeTaken(), - 1, + REVLOG_REV, ) try: diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 6b11a5e5a..12b64f923 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -961,7 +961,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" def _answerRevCard(self, card: Card, ease: int) -> None: delay = 0 early = bool(card.odid and (card.odue > self.today)) - type = early and 3 or 1 + type = early and 3 or REVLOG_REV if ease == BUTTON_ONE: delay = self._rescheduleLapse(card) diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index b2a6f8bd9..f606bef0e 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -154,7 +154,7 @@ body {background-image: url(data:image/png;base64,%s); } select count(), sum(time)/1000, sum(case when ease = 1 then 1 else 0 end), /* failed */ sum(case when type = {REVLOG_LRN} then 1 else 0 end), /* learning */ -sum(case when type = 1 then 1 else 0 end), /* review */ +sum(case when type = {REVLOG_REV} then 1 else 0 end), /* review */ sum(case when type = 2 then 1 else 0 end), /* relearn */ sum(case when type = 3 then 1 else 0 end) /* filter */ from revlog where id > ? """ @@ -549,14 +549,14 @@ group by day order by day""" select (cast((id/1000.0 - :cut) / 86400.0 as int))/:chunk as day, sum(case when type = {REVLOG_LRN} then 1 else 0 end), -- lrn count -sum(case when type = 1 and lastIvl < 21 then 1 else 0 end), -- yng count -sum(case when type = 1 and lastIvl >= 21 then 1 else 0 end), -- mtr count +sum(case when type = {REVLOG_REV} and lastIvl < 21 then 1 else 0 end), -- yng count +sum(case when type = {REVLOG_REV} and lastIvl >= 21 then 1 else 0 end), -- mtr count sum(case when type = 2 then 1 else 0 end), -- lapse count sum(case when type = 3 then 1 else 0 end), -- cram count sum(case when type = {REVLOG_LRN} then time/1000.0 else 0 end)/:tf, -- lrn time -- yng + mtr time -sum(case when type = 1 and lastIvl < 21 then time/1000.0 else 0 end)/:tf, -sum(case when type = 1 and lastIvl >= 21 then time/1000.0 else 0 end)/:tf, +sum(case when type = {REVLOG_REV} and lastIvl < 21 then time/1000.0 else 0 end)/:tf, +sum(case when type = {REVLOG_REV} and lastIvl >= 21 then time/1000.0 else 0 end)/:tf, sum(case when type = 2 then time/1000.0 else 0 end)/:tf, -- lapse time sum(case when type = 3 then time/1000.0 else 0 end)/:tf -- cram time from revlog %s @@ -856,7 +856,7 @@ select sum(case when ease = 1 then 0 else 1 end) / cast(count() as float) * 100, count() -from revlog where type in ({REVLOG_LRN},1,2) %s +from revlog where type in ({REVLOG_LRN},{REVLOG_REV},2) %s group by hour having count() > 30 order by hour""" % lim, cut=self.col.sched.dayCutoff - (rolloverHour * 3600), From e1a283b1683007ae22511ec4a40e5d3d38a490ce Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 18:04:59 -0800 Subject: [PATCH 24/38] REVLOG_RELRN --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 2 +- pylib/anki/schedv2.py | 2 +- pylib/anki/stats.py | 12 ++++++------ 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 22da0d552..2dc9962fc 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -72,6 +72,7 @@ BUTTON_FOUR = 4 # Revlog types REVLOG_LRN = 0 REVLOG_REV = 1 +REVLOG_RELRN = 2 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 04b65ba4c..e277c06ce 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -558,7 +558,7 @@ did = ? and queue = 3 and due <= ? limit ?""", if card.odid and not card.wasNew: type = 3 elif card.type == 2: - type = 2 + type = REVLOG_RELRN else: type = REVLOG_LRN leaving = False diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 12b64f923..f27552f90 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -608,7 +608,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", def _answerLrnCard(self, card: Card, ease: int) -> None: conf = self._lrnConf(card) if card.type in (2, CARD_TYPE_RELEARNING): - type = 2 + type = REVLOG_RELRN else: type = REVLOG_LRN # lrnCount was decremented once when card was fetched diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index f606bef0e..fe3f1e3a2 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -155,7 +155,7 @@ select count(), sum(time)/1000, sum(case when ease = 1 then 1 else 0 end), /* failed */ sum(case when type = {REVLOG_LRN} then 1 else 0 end), /* learning */ sum(case when type = {REVLOG_REV} then 1 else 0 end), /* review */ -sum(case when type = 2 then 1 else 0 end), /* relearn */ +sum(case when type = {REVLOG_RELRN} then 1 else 0 end), /* relearn */ sum(case when type = 3 then 1 else 0 end) /* filter */ from revlog where id > ? """ + lim, @@ -551,13 +551,13 @@ select sum(case when type = {REVLOG_LRN} then 1 else 0 end), -- lrn count sum(case when type = {REVLOG_REV} and lastIvl < 21 then 1 else 0 end), -- yng count sum(case when type = {REVLOG_REV} and lastIvl >= 21 then 1 else 0 end), -- mtr count -sum(case when type = 2 then 1 else 0 end), -- lapse count +sum(case when type = {REVLOG_RELRN} then 1 else 0 end), -- lapse count sum(case when type = 3 then 1 else 0 end), -- cram count sum(case when type = {REVLOG_LRN} then time/1000.0 else 0 end)/:tf, -- lrn time -- yng + mtr time sum(case when type = {REVLOG_REV} and lastIvl < 21 then time/1000.0 else 0 end)/:tf, sum(case when type = {REVLOG_REV} and lastIvl >= 21 then time/1000.0 else 0 end)/:tf, -sum(case when type = 2 then time/1000.0 else 0 end)/:tf, -- lapse time +sum(case when type = {REVLOG_RELRN} then time/1000.0 else 0 end)/:tf, -- lapse time sum(case when type = 3 then time/1000.0 else 0 end)/:tf -- cram time from revlog %s group by day order by day""" @@ -758,10 +758,10 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" return self.col.db.all( f""" select (case -when type in ({REVLOG_LRN},2) then 0 +when type in ({REVLOG_LRN},{REVLOG_RELRN}) then 0 when lastIvl < 21 then 1 else 2 end) as thetype, -(case when type in ({REVLOG_LRN},2) and ease = 4 then %s else ease end), count() from revlog %s +(case when type in ({REVLOG_LRN},{REVLOG_RELRN}) and ease = 4 then %s else ease end), count() from revlog %s group by thetype, ease order by thetype, ease""" % (ease4repl, lim) @@ -856,7 +856,7 @@ select sum(case when ease = 1 then 0 else 1 end) / cast(count() as float) * 100, count() -from revlog where type in ({REVLOG_LRN},{REVLOG_REV},2) %s +from revlog where type in ({REVLOG_LRN},{REVLOG_REV},{REVLOG_RELRN}) %s group by hour having count() > 30 order by hour""" % lim, cut=self.col.sched.dayCutoff - (rolloverHour * 3600), From 600c70edcb6d8cb5fa13994f2d5342b6132050e3 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 18:09:54 -0800 Subject: [PATCH 25/38] REVLOG_CRAM --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 2 +- pylib/anki/schedv2.py | 2 +- pylib/anki/stats.py | 6 +++--- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 2dc9962fc..c3efab33e 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -73,6 +73,7 @@ BUTTON_FOUR = 4 REVLOG_LRN = 0 REVLOG_REV = 1 REVLOG_RELRN = 2 +REVLOG_CRAM = 3 # Labels ########################################################################## diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index e277c06ce..06b039c11 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -556,7 +556,7 @@ did = ? and queue = 3 and due <= ? limit ?""", # ease 1=no, 2=yes, 3=remove conf = self._lrnConf(card) if card.odid and not card.wasNew: - type = 3 + type = REVLOG_CRAM elif card.type == 2: type = REVLOG_RELRN else: diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index f27552f90..72a73f020 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -961,7 +961,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" def _answerRevCard(self, card: Card, ease: int) -> None: delay = 0 early = bool(card.odid and (card.odue > self.today)) - type = early and 3 or REVLOG_REV + type = early and REVLOG_CRAM or REVLOG_REV if ease == BUTTON_ONE: delay = self._rescheduleLapse(card) diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index fe3f1e3a2..d462a9d37 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -156,7 +156,7 @@ sum(case when ease = 1 then 1 else 0 end), /* failed */ sum(case when type = {REVLOG_LRN} then 1 else 0 end), /* learning */ sum(case when type = {REVLOG_REV} then 1 else 0 end), /* review */ sum(case when type = {REVLOG_RELRN} then 1 else 0 end), /* relearn */ -sum(case when type = 3 then 1 else 0 end) /* filter */ +sum(case when type = {REVLOG_CRAM} then 1 else 0 end) /* filter */ from revlog where id > ? """ + lim, (self.col.sched.dayCutoff - 86400) * 1000, @@ -552,13 +552,13 @@ sum(case when type = {REVLOG_LRN} then 1 else 0 end), -- lrn count sum(case when type = {REVLOG_REV} and lastIvl < 21 then 1 else 0 end), -- yng count sum(case when type = {REVLOG_REV} and lastIvl >= 21 then 1 else 0 end), -- mtr count sum(case when type = {REVLOG_RELRN} then 1 else 0 end), -- lapse count -sum(case when type = 3 then 1 else 0 end), -- cram count +sum(case when type = {REVLOG_CRAM} then 1 else 0 end), -- cram count sum(case when type = {REVLOG_LRN} then time/1000.0 else 0 end)/:tf, -- lrn time -- yng + mtr time sum(case when type = {REVLOG_REV} and lastIvl < 21 then time/1000.0 else 0 end)/:tf, sum(case when type = {REVLOG_REV} and lastIvl >= 21 then time/1000.0 else 0 end)/:tf, sum(case when type = {REVLOG_RELRN} then time/1000.0 else 0 end)/:tf, -- lapse time -sum(case when type = 3 then time/1000.0 else 0 end)/:tf -- cram time +sum(case when type = {REVLOG_CRAM} then time/1000.0 else 0 end)/:tf -- cram time from revlog %s group by day order by day""" % lim, From 3fa0a07e2e0627c7b8e47db1b8c749a0fb1fd586 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Mon, 3 Feb 2020 01:44:17 -0800 Subject: [PATCH 26/38] PERIOD_MONTH --- pylib/anki/stats.py | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index d462a9d37..9dd9ecba9 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -13,6 +13,8 @@ from anki.utils import fmtTimeSpan, ids2str # Card stats ########################################################################## +PERIOD_MONTH = 0 + class CardStats: def __init__(self, col, card) -> None: @@ -103,14 +105,14 @@ class CollectionStats: def __init__(self, col) -> None: self.col = col self._stats = None - self.type = 0 + self.type = PERIOD_MONTH self.width = 600 self.height = 200 self.wholeCollection = False # assumes jquery & plot are available in document - def report(self, type=0) -> str: - # 0=days, 1=weeks, 2=months + def report(self, type=PERIOD_MONTH) -> str: + # 0=month, 1=weeks, 2=months self.type = type from .statsbg import bg @@ -216,7 +218,7 @@ from revlog where id > ? """ def get_start_end_chunk(self, by="review") -> Tuple[int, Optional[int], int]: start = 0 - if self.type == 0: + if self.type == PERIOD_MONTH: end, chunk = 31, 1 elif self.type == 1: end, chunk = 52, 7 @@ -397,7 +399,7 @@ group by day order by day""" (10, colCram, _("Cram")), ), ) - if self.type == 0: + if self.type == PERIOD_MONTH: t = _("Minutes") convHours = False else: @@ -510,7 +512,7 @@ group by day order by day""" lim = "where " + " and ".join(lims) else: lim = "" - if self.type == 0: + if self.type == PERIOD_MONTH: tf = 60.0 # minutes else: tf = 3600.0 # hours @@ -540,7 +542,7 @@ group by day order by day""" lim = "where " + " and ".join(lims) else: lim = "" - if self.type == 0: + if self.type == PERIOD_MONTH: tf = 60.0 # minutes else: tf = 3600.0 # hours @@ -603,7 +605,7 @@ group by day order by day)""" for (grp, cnt) in ivls: tot += cnt totd.append((grp, tot / float(all) * 100)) - if self.type == 0: + if self.type == PERIOD_MONTH: ivlmax = 31 elif self.type == 1: ivlmax = 52 @@ -711,7 +713,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" return txt def _easeInfo(self, eases) -> str: - types = {0: [0, 0], 1: [0, 0], 2: [0, 0]} + types = {PERIOD_MONTH: [0, 0], 1: [0, 0], 2: [0, 0]} for (type, ease, cnt) in eases: if ease == 1: types[type][0] += cnt From c6013c40c5672081e98e31d67e05326de7199b3d Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Mon, 3 Feb 2020 01:47:24 -0800 Subject: [PATCH 27/38] PERIOD_YEAR --- pylib/anki/stats.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index 9dd9ecba9..afc266c8b 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -14,6 +14,7 @@ from anki.utils import fmtTimeSpan, ids2str ########################################################################## PERIOD_MONTH = 0 +PERIOD_YEAR = 1 class CardStats: @@ -112,7 +113,7 @@ class CollectionStats: # assumes jquery & plot are available in document def report(self, type=PERIOD_MONTH) -> str: - # 0=month, 1=weeks, 2=months + # 0=month, 1=year, 2=months self.type = type from .statsbg import bg @@ -220,7 +221,7 @@ from revlog where id > ? """ start = 0 if self.type == PERIOD_MONTH: end, chunk = 31, 1 - elif self.type == 1: + elif self.type == PERIOD_YEAR: end, chunk = 52, 7 else: # self.type == 2: end = None @@ -607,7 +608,7 @@ group by day order by day)""" totd.append((grp, tot / float(all) * 100)) if self.type == PERIOD_MONTH: ivlmax = 31 - elif self.type == 1: + elif self.type == PERIOD_YEAR: ivlmax = 52 else: ivlmax = max(5, ivls[-1][0]) @@ -713,7 +714,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" return txt def _easeInfo(self, eases) -> str: - types = {PERIOD_MONTH: [0, 0], 1: [0, 0], 2: [0, 0]} + types = {PERIOD_MONTH: [0, 0], PERIOD_YEAR: [0, 0], 2: [0, 0]} for (type, ease, cnt) in eases: if ease == 1: types[type][0] += cnt From 871de0f543209e619ee42424e4ac57c1b9938362 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Mon, 3 Feb 2020 01:49:55 -0800 Subject: [PATCH 28/38] PERIOD_LIFE --- pylib/anki/stats.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index afc266c8b..b855ee7bb 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -15,6 +15,7 @@ from anki.utils import fmtTimeSpan, ids2str PERIOD_MONTH = 0 PERIOD_YEAR = 1 +PERIOD_LIFE = 2 class CardStats: @@ -113,7 +114,7 @@ class CollectionStats: # assumes jquery & plot are available in document def report(self, type=PERIOD_MONTH) -> str: - # 0=month, 1=year, 2=months + # 0=month, 1=year, 2=deck life self.type = type from .statsbg import bg @@ -714,7 +715,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" return txt def _easeInfo(self, eases) -> str: - types = {PERIOD_MONTH: [0, 0], PERIOD_YEAR: [0, 0], 2: [0, 0]} + types = {PERIOD_MONTH: [0, 0], PERIOD_YEAR: [0, 0], PERIOD_LIFE: [0, 0]} for (type, ease, cnt) in eases: if ease == 1: types[type][0] += cnt From cd86fee03f6f219840547bae4fd7b5824a93b1a9 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 18:11:04 -0800 Subject: [PATCH 29/38] Card and queue type --- pylib/anki/consts.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index c3efab33e..e9b1f37c7 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -14,6 +14,8 @@ NEW_CARDS_FIRST = 2 NEW_CARDS_RANDOM = 0 NEW_CARDS_DUE = 1 +# Card and queue types + # removal types REM_CARD = 0 REM_NOTE = 1 From a1cc0787d2eddd6cc6e15d8e0a57b03b8f9ea09c Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 2 Feb 2020 01:19:45 -0800 Subject: [PATCH 30/38] QUEUE_TYPE_NEW and CARD_TYPE_NEW --- pylib/anki/cards.py | 4 +-- pylib/anki/consts.py | 6 +++- pylib/anki/find.py | 4 +-- pylib/anki/importing/anki2.py | 5 +-- pylib/anki/sched.py | 60 +++++++++++++++++------------------ pylib/anki/schedv2.py | 56 ++++++++++++++++---------------- pylib/anki/stats.py | 10 +++--- pylib/tests/test_schedv1.py | 10 +++--- pylib/tests/test_schedv2.py | 24 +++++++------- pylib/tests/test_undo.py | 4 +-- qt/aqt/browser.py | 8 ++--- 11 files changed, 98 insertions(+), 93 deletions(-) diff --git a/pylib/anki/cards.py b/pylib/anki/cards.py index a94f271be..19845566a 100644 --- a/pylib/anki/cards.py +++ b/pylib/anki/cards.py @@ -48,8 +48,8 @@ class Card: self.id = timestampID(col.db, "cards") self.did = 1 self.crt = intTime() - self.type = 0 - self.queue = 0 + self.type = CARD_TYPE_NEW + self.queue = QUEUE_TYPE_NEW self.ivl = 0 self.factor = 0 self.reps = 0 diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index e9b1f37c7..f3d9fd1a9 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -14,7 +14,11 @@ NEW_CARDS_FIRST = 2 NEW_CARDS_RANDOM = 0 NEW_CARDS_DUE = 1 -# Card and queue types +# Queue types +QUEUE_TYPE_NEW = 0 + +# Card types +CARD_TYPE_NEW = 0 # removal types REM_CARD = 0 diff --git a/pylib/anki/find.py b/pylib/anki/find.py index ccd6844d3..57a66d03b 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -240,7 +240,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ elif type == "cardDue": sort = "c.type, c.due" elif type == "cardEase": - sort = "c.type == 0, c.factor" + sort = f"c.type == {CARD_TYPE_NEW}, c.factor" elif type == "cardLapses": sort = "c.lapses" elif type == "cardIvl": @@ -271,7 +271,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ if val == "review": n = 2 elif val == "new": - n = 0 + n = CARD_TYPE_NEW else: return "queue in (1, 3)" return "type = %d" % n diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index 46d54000c..ee681d570 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -6,6 +6,7 @@ import unicodedata from typing import Any, Dict, List, Optional, Tuple from anki.collection import _Collection +from anki.consts import * from anki.importing.base import Importer from anki.lang import _ from anki.storage import Collection @@ -357,12 +358,12 @@ class Anki2Importer(Importer): card[14] = 0 # queue if card[6] == 1: # type - card[7] = 0 + card[7] = QUEUE_TYPE_NEW else: card[7] = card[6] # type if card[6] == 1: - card[6] = 0 + card[6] = CARD_TYPE_NEW cards.append(card) # we need to import revlog, rewriting card ids and bumping usn for rev in self.src.db.execute("select * from revlog where cid = ?", scid): diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 06b039c11..2bf2fbafb 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -67,13 +67,13 @@ class Scheduler: self._burySiblings(card) card.reps += 1 # former is for logging new cards, latter also covers filt. decks - card.wasNew = card.type == 0 - wasNewQ = card.queue == 0 + card.wasNew = card.type == CARD_TYPE_NEW + wasNewQ = card.queue == QUEUE_TYPE_NEW if wasNewQ: # came from the new queue, move to learning card.queue = 1 # if it was a new card, it's now a learning card - if card.type == 0: + if card.type == CARD_TYPE_NEW: card.type = 1 # init reps to graduation card.left = self._startingLeft(card) @@ -142,7 +142,7 @@ order by due""" if card.odid and card.queue == 2: return 4 conf = self._lrnConf(card) - if card.type in (0, 1) or len(conf["delays"]) > 1: + if card.type in (CARD_TYPE_NEW, 1) or len(conf["delays"]) > 1: return 3 return 2 elif card.queue == 2: @@ -348,9 +348,9 @@ order by due""" def _resetNewCount(self): cntFn = lambda did, lim: self.col.db.scalar( - """ + f""" select count() from (select 1 from cards where -did = ? and queue = 0 limit ?)""", +did = ? and queue = {QUEUE_TYPE_NEW} limit ?)""", did, lim, ) @@ -373,8 +373,8 @@ did = ? and queue = 0 limit ?)""", if lim: # fill the queue with the current did self._newQueue = self.col.db.list( - """ - select id from cards where did = ? and queue = 0 order by due,ord limit ?""", + f""" + select id from cards where did = ? and queue = {QUEUE_TYPE_NEW} order by due,ord limit ?""", did, lim, ) @@ -436,9 +436,9 @@ did = ? and queue = 0 limit ?)""", return 0 lim = min(lim, self.reportLimit) return self.col.db.scalar( - """ + f""" select count() from -(select 1 from cards where did = ? and queue = 0 limit ?)""", +(select 1 from cards where did = ? and queue = {QUEUE_TYPE_NEW} limit ?)""", did, lim, ) @@ -452,9 +452,9 @@ select count() from def totalNewForCurrentDeck(self): return self.col.db.scalar( - """ + f""" select count() from cards where id in ( -select id from cards where did in %s and queue = 0 limit ?)""" +select id from cards where did in %s and queue = {QUEUE_TYPE_NEW} limit ?)""" % ids2str(self.col.decks.active()), self.reportLimit, ) @@ -652,7 +652,7 @@ did = ? and queue = 3 and due <= ? limit ?""", card.odid = 0 # if rescheduling is off, it needs to be set back to a new card if not resched and not lapse: - card.queue = card.type = 0 + card.queue = card.type = CARD_TYPE_NEW card.due = self.col.nextID("pos") def _startingLeft(self, card): @@ -1058,9 +1058,9 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" self.col.log(self.col.db.list("select id from cards where %s" % lim)) # move out of cram queue self.col.db.execute( - """ -update cards set did = odid, queue = (case when type = 1 then 0 -else type end), type = (case when type = 1 then 0 else type end), + f""" +update cards set did = odid, queue = (case when type = 1 then {QUEUE_TYPE_NEW} +else type end), type = (case when type = 1 then {CARD_TYPE_NEW} else type end), due = odue, odue = 0, odid = 0, usn = ? where %s""" % lim, self.col.usn(), @@ -1106,9 +1106,9 @@ due = odue, odue = 0, odid = 0, usn = ? where %s""" data.append((did, -100000 + c, u, id)) # due reviews stay in the review queue. careful: can't use # "odid or did", as sqlite converts to boolean - queue = """ + queue = f""" (case when type=2 and (case when odue then odue <= %d else due <= %d end) - then 2 else 0 end)""" + then 2 else {QUEUE_TYPE_NEW} end)""" queue %= (self.today, self.today) self.col.db.executemany( """ @@ -1321,7 +1321,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" def newDue(self): "True if there are any new cards due." return self.col.db.scalar( - ("select 1 from cards where did in %s and queue = 0 " "limit 1") + (f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_NEW} " "limit 1") % self._deckLimit() ) @@ -1347,7 +1347,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" def nextIvl(self, card, ease): "Return the next interval for CARD, in seconds." - if card.queue in (0, 1, 3): + if card.queue in (QUEUE_TYPE_NEW, 1, 3): return self._nextLrnIvl(card, ease) elif ease == BUTTON_ONE: # lapsed @@ -1436,9 +1436,9 @@ update cards set queue=-2,mod=?,usn=? where id in """ buryRev = rconf.get("bury", True) # loop through and remove from queues for cid, queue in self.col.db.execute( - """ + f""" select id, queue from cards where nid=? and id!=? -and (queue=0 or (queue=2 and due<=?))""", +and (queue={QUEUE_TYPE_NEW} or (queue=2 and due<=?))""", card.nid, card.id, self.today, @@ -1475,11 +1475,11 @@ and (queue=0 or (queue=2 and due<=?))""", "Put cards at the end of the new queue." self.remFromDyn(ids) self.col.db.execute( - "update cards set type=0,queue=0,ivl=0,due=0,odue=0,factor=?" + f"update cards set type={CARD_TYPE_NEW},queue={QUEUE_TYPE_NEW},ivl=0,due=0,odue=0,factor=?" " where id in " + ids2str(ids), STARTING_FACTOR, ) - pmax = self.col.db.scalar("select max(due) from cards where type=0") or 0 + pmax = self.col.db.scalar(f"select max(due) from cards where type={CARD_TYPE_NEW}") or 0 # takes care of mod + usn self.sortCards(ids, start=pmax + 1) self.col.log(ids) @@ -1515,11 +1515,11 @@ usn=:usn,mod=:mod,factor=:fact where id=:id""", sids = ids2str(ids) # we want to avoid resetting due number of existing new cards on export nonNew = self.col.db.list( - "select id from cards where id in %s and (queue != 0 or type != 0)" % sids + f"select id from cards where id in %s and (queue != {QUEUE_TYPE_NEW} or type != {CARD_TYPE_NEW})" % sids ) # reset all cards self.col.db.execute( - "update cards set reps=0,lapses=0,odid=0,odue=0,queue=0" + f"update cards set reps=0,lapses=0,odid=0,odue=0,queue={QUEUE_TYPE_NEW}" " where id in %s" % sids ) # and forget any non-new cards, changing their due numbers @@ -1553,16 +1553,16 @@ usn=:usn,mod=:mod,factor=:fact where id=:id""", # shift? if shift: low = self.col.db.scalar( - "select min(due) from cards where due >= ? and type = 0 " + f"select min(due) from cards where due >= ? and type = {CARD_TYPE_NEW} " "and id not in %s" % scids, start, ) if low is not None: shiftby = high - low + 1 self.col.db.execute( - """ + f""" update cards set mod=?, usn=?, due=due+? where id not in %s -and due >= ? and queue = 0""" +and due >= ? and queue = {QUEUE_TYPE_NEW}""" % scids, now, self.col.usn(), @@ -1572,7 +1572,7 @@ and due >= ? and queue = 0""" # reorder cards d = [] for id, nid in self.col.db.execute( - "select id, nid from cards where type = 0 and id in " + scids + f"select id, nid from cards where type = {CARD_TYPE_NEW} and id in " + scids ): d.append(dict(now=now, due=due[nid], usn=self.col.usn(), cid=id)) self.col.db.executemany( diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 72a73f020..8c1d1e2fe 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -95,7 +95,7 @@ class Scheduler: card.reps += 1 - if card.queue == 0: + if card.queue == QUEUE_TYPE_NEW: # came from the new queue, move to learning card.queue = 1 card.type = 1 @@ -369,9 +369,9 @@ order by due""" def _resetNewCount(self) -> None: cntFn = lambda did, lim: self.col.db.scalar( - """ + f""" select count() from (select 1 from cards where -did = ? and queue = 0 limit ?)""", +did = ? and queue = {QUEUE_TYPE_NEW} limit ?)""", did, lim, ) @@ -394,8 +394,8 @@ did = ? and queue = 0 limit ?)""", if lim: # fill the queue with the current did self._newQueue = self.col.db.list( - """ - select id from cards where did = ? and queue = 0 order by due,ord limit ?""", + f""" + select id from cards where did = ? and queue = {QUEUE_TYPE_NEW} order by due,ord limit ?""", did, lim, ) @@ -463,9 +463,9 @@ did = ? and queue = 0 limit ?)""", return 0 lim = min(lim, self.reportLimit) return self.col.db.scalar( - """ + f""" select count() from -(select 1 from cards where did = ? and queue = 0 limit ?)""", +(select 1 from cards where did = ? and queue = {QUEUE_TYPE_NEW} limit ?)""", did, lim, ) @@ -479,9 +479,9 @@ select count() from def totalNewForCurrentDeck(self) -> Any: return self.col.db.scalar( - """ + f""" select count() from cards where id in ( -select id from cards where did in %s and queue = 0 limit ?)""" +select id from cards where did in %s and queue = {QUEUE_TYPE_NEW} limit ?)""" % self._deckLimit(), self.reportLimit, ) @@ -1520,7 +1520,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" def newDue(self) -> Any: "True if there are any new cards due." return self.col.db.scalar( - ("select 1 from cards where did in %s and queue = 0 " "limit 1") + (f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_NEW} " "limit 1") % self._deckLimit() ) @@ -1563,7 +1563,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" return 0 # (re)learning? - if card.queue in (0, 1, QUEUE_TYPE_DAY_LEARN_RELEARN): + if card.queue in (QUEUE_TYPE_NEW, 1, QUEUE_TYPE_DAY_LEARN_RELEARN): return self._nextLrnIvl(card, ease) elif ease == BUTTON_ONE: # lapse @@ -1581,7 +1581,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" # this isn't easily extracted from the learn code def _nextLrnIvl(self, card: Card, ease: int) -> Any: - if card.queue == 0: + if card.queue == QUEUE_TYPE_NEW: card.left = self._startingLeft(card) conf = self._lrnConf(card) if ease == BUTTON_ONE: @@ -1647,7 +1647,7 @@ update cards set queue=?,mod=?,usn=? where id in """ def buryNote(self, nid) -> None: "Bury all cards for note until next session." cids = self.col.db.list( - "select id from cards where nid = ? and queue >= 0", nid + f"select id from cards where nid = ? and queue >= {QUEUE_TYPE_NEW}", nid ) self.buryCards(cids) @@ -1699,9 +1699,9 @@ update cards set queue=?,mod=?,usn=? where id in """ buryRev = rconf.get("bury", True) # loop through and remove from queues for cid, queue in self.col.db.execute( - """ + f""" select id, queue from cards where nid=? and id!=? -and (queue=0 or (queue=2 and due<=?))""", +and (queue={QUEUE_TYPE_NEW} or (queue=2 and due<=?))""", card.nid, card.id, self.today, @@ -1733,11 +1733,11 @@ and (queue=0 or (queue=2 and due<=?))""", "Put cards at the end of the new queue." self.remFromDyn(ids) self.col.db.execute( - "update cards set type=0,queue=0,ivl=0,due=0,odue=0,factor=?" + f"update cards set type={CARD_TYPE_NEW},queue={QUEUE_TYPE_NEW},ivl=0,due=0,odue=0,factor=?" " where id in " + ids2str(ids), STARTING_FACTOR, ) - pmax = self.col.db.scalar("select max(due) from cards where type=0") or 0 + pmax = self.col.db.scalar(f"select max(due) from cards where type={CARD_TYPE_NEW}") or 0 # takes care of mod + usn self.sortCards(ids, start=pmax + 1) self.col.log(ids) @@ -1773,11 +1773,11 @@ usn=:usn,mod=:mod,factor=:fact where id=:id""", sids = ids2str(ids) # we want to avoid resetting due number of existing new cards on export nonNew = self.col.db.list( - "select id from cards where id in %s and (queue != 0 or type != 0)" % sids + f"select id from cards where id in %s and (queue != {QUEUE_TYPE_NEW} or type != {CARD_TYPE_NEW})" % sids ) # reset all cards self.col.db.execute( - "update cards set reps=0,lapses=0,odid=0,odue=0,queue=0" + f"update cards set reps=0,lapses=0,odid=0,odue=0,queue={QUEUE_TYPE_NEW}" " where id in %s" % sids ) # and forget any non-new cards, changing their due numbers @@ -1818,16 +1818,16 @@ usn=:usn,mod=:mod,factor=:fact where id=:id""", # shift? if shift: low = self.col.db.scalar( - "select min(due) from cards where due >= ? and type = 0 " + f"select min(due) from cards where due >= ? and type = {CARD_TYPE_NEW} " "and id not in %s" % scids, start, ) if low is not None: shiftby = high - low + 1 self.col.db.execute( - """ + f""" update cards set mod=?, usn=?, due=due+? where id not in %s -and due >= ? and queue = 0""" +and due >= ? and queue = {QUEUE_TYPE_NEW}""" % scids, now, self.col.usn(), @@ -1837,7 +1837,7 @@ and due >= ? and queue = 0""" # reorder cards d = [] for id, nid in self.col.db.execute( - "select id, nid from cards where type = 0 and id in " + scids + f"select id, nid from cards where type = {CARD_TYPE_NEW} and id in " + scids ): d.append(dict(now=now, due=due[nid], usn=self.col.usn(), cid=id)) self.col.db.executemany( @@ -1875,10 +1875,10 @@ and due >= ? and queue = 0""" self.col.db.execute( f""" update cards set did = odid, queue = (case -when type = 1 then 0 +when type = 1 then {QUEUE_TYPE_NEW} when type = {CARD_TYPE_RELEARNING} then 2 else type end), type = (case -when type = 1 then 0 +when type = 1 then {CARD_TYPE_NEW} when type = {CARD_TYPE_RELEARNING} then 2 else type end), due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", @@ -1917,13 +1917,13 @@ due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", self.col.db.execute( f""" update cards set type = (case -when type = 1 then 0 +when type = 1 then {CARD_TYPE_NEW} when type in (2, {CARD_TYPE_RELEARNING}) then 2 else type end), due = (case when odue then odue else due end), odue = 0, mod = %d, usn = %d -where queue < 0""" +where queue < {QUEUE_TYPE_NEW}""" % (intTime(), self.col.usn()) ) @@ -1937,7 +1937,7 @@ where queue < 0""" # adding 'hard' in v2 scheduler means old ease entries need shifting # up or down def _remapLearningAnswers(self, sql: str) -> None: - self.col.db.execute("update revlog set %s and type in (0,2)" % sql) + self.col.db.execute(f"update revlog set %s and type in ({CARD_TYPE_NEW},2)" % sql) def moveToV1(self) -> None: self._emptyAllFiltered() diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index b855ee7bb..32e24341a 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -36,7 +36,7 @@ class CardStats: self.addLine(_("First Review"), self.date(first / 1000)) self.addLine(_("Latest Review"), self.date(last / 1000)) if c.type in (1, 2): - if c.odid or c.queue < 0: + if c.odid or c.queue < QUEUE_TYPE_NEW: next = None else: if c.queue in (2, 3): @@ -57,7 +57,7 @@ class CardStats: if cnt: self.addLine(_("Average Time"), self.time(total / float(cnt))) self.addLine(_("Total Time"), self.time(total)) - elif c.queue == 0: + elif c.queue == QUEUE_TYPE_NEW: self.addLine(_("Position"), c.due) self.addLine(_("Card Type"), c.template()["name"]) self.addLine(_("Note Type"), c.model()["name"]) @@ -941,12 +941,12 @@ from cards where did in %s and queue = 2""" def _cards(self) -> Any: return self.col.db.first( - """ + f""" select sum(case when queue=2 and ivl >= 21 then 1 else 0 end), -- mtr sum(case when queue in (1,3) or (queue=2 and ivl < 21) then 1 else 0 end), -- yng/lrn -sum(case when queue=0 then 1 else 0 end), -- new -sum(case when queue<0 then 1 else 0 end) -- susp +sum(case when queue={QUEUE_TYPE_NEW} then 1 else 0 end), -- new +sum(case when queue<{QUEUE_TYPE_NEW} then 1 else 0 end) -- susp from cards where did in %s""" % self._limit() ) diff --git a/pylib/tests/test_schedv1.py b/pylib/tests/test_schedv1.py index bd5de3f08..186637340 100644 --- a/pylib/tests/test_schedv1.py +++ b/pylib/tests/test_schedv1.py @@ -4,7 +4,7 @@ import copy import time from anki import hooks -from anki.consts import STARTING_FACTOR +from anki.consts import * from anki.utils import intTime from tests.shared import getEmptyCol as getEmptyColOrig @@ -46,8 +46,8 @@ def test_new(): # fetch it c = d.sched.getCard() assert c - assert c.queue == 0 - assert c.type == 0 + assert c.queue == QUEUE_TYPE_NEW + assert c.type == CARD_TYPE_NEW # if we answer it, it should become a learn card t = intTime() d.sched.answerCard(c, 1) @@ -707,7 +707,7 @@ def test_cram_rem(): # if we terminate cramming prematurely it should be set back to new d.sched.emptyDyn(did) c.load() - assert c.type == c.queue == 0 + assert c.type == CARD_TYPE_NEW and c.queue == QUEUE_TYPE_NEW assert c.due == oldDue @@ -731,7 +731,7 @@ def test_cram_resched(): assert ni(c, 3) == 0 assert d.sched.nextIvlStr(c, 3) == "(end)" d.sched.answerCard(c, 3) - assert c.queue == c.type == 0 + assert c.type == CARD_TYPE_NEW and c.queue == QUEUE_TYPE_NEW # undue reviews should also be unaffected c.ivl = 100 c.type = c.queue = 2 diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index 2f3865ff5..be4cfa144 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -4,7 +4,7 @@ import copy import time from anki import hooks -from anki.consts import STARTING_FACTOR +from anki.consts import * from anki.utils import intTime from tests.shared import getEmptyCol as getEmptyColOrig @@ -57,8 +57,8 @@ def test_new(): # fetch it c = d.sched.getCard() assert c - assert c.queue == 0 - assert c.type == 0 + assert c.queue == QUEUE_TYPE_NEW + assert c.type == CARD_TYPE_NEW # if we answer it, it should become a learn card t = intTime() d.sched.answerCard(c, 1) @@ -634,7 +634,7 @@ def test_bury(): d.sched.unburyCardsForDeck(type="manual") # pylint: disable=unexpected-keyword-arg c.load() - assert c.queue == 0 + assert c.queue == QUEUE_TYPE_NEW c2.load() assert c2.queue == -2 @@ -642,7 +642,7 @@ def test_bury(): type="siblings" ) c2.load() - assert c2.queue == 0 + assert c2.queue == QUEUE_TYPE_NEW d.sched.buryCards([c.id, c2.id]) d.sched.unburyCardsForDeck(type="all") # pylint: disable=unexpected-keyword-arg @@ -833,9 +833,9 @@ def test_preview(): # passing it will remove it d.sched.answerCard(c2, 2) - assert c2.queue == 0 + assert c2.queue == QUEUE_TYPE_NEW assert c2.reps == 0 - assert c2.type == 0 + assert c2.type == CARD_TYPE_NEW # the other card should appear again c = d.sched.getCard() @@ -844,9 +844,9 @@ def test_preview(): # emptying the filtered deck should restore card d.sched.emptyDyn(did) c.load() - assert c.queue == 0 + assert c.queue == QUEUE_TYPE_NEW assert c.reps == 0 - assert c.type == 0 + assert c.type == CARD_TYPE_NEW def test_ordcycle(): @@ -1217,8 +1217,8 @@ def test_moveVersions(): # the move to v2 should reset it to new col.changeSchedulerVer(2) c.load() - assert c.queue == 0 - assert c.type == 0 + assert c.queue == QUEUE_TYPE_NEW + assert c.type == CARD_TYPE_NEW # fail it again, and manually bury it col.reset() @@ -1238,7 +1238,7 @@ def test_moveVersions(): # and it should be new again when unburied col.sched.unburyCards() c.load() - assert c.queue == c.type == 0 + assert c.type == CARD_TYPE_NEW and c.queue == QUEUE_TYPE_NEW # make sure relearning cards transition correctly to v1 col.changeSchedulerVer(2) diff --git a/pylib/tests/test_undo.py b/pylib/tests/test_undo.py index d37a8baa6..a4a8a7098 100644 --- a/pylib/tests/test_undo.py +++ b/pylib/tests/test_undo.py @@ -55,7 +55,7 @@ def test_review(): # answer assert d.sched.counts() == (1, 0, 0) c = d.sched.getCard() - assert c.queue == 0 + assert c.queue == QUEUE_TYPE_NEW d.sched.answerCard(c, 3) assert c.left == 1001 assert d.sched.counts() == (0, 1, 0) @@ -66,7 +66,7 @@ def test_review(): d.reset() assert d.sched.counts() == (1, 0, 0) c.load() - assert c.queue == 0 + assert c.queue == QUEUE_TYPE_NEW assert c.left != 1001 assert not d.undoName() # we should be able to undo multiple answers too diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index 6080dab34..77af12b3f 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -335,7 +335,7 @@ class DataModel(QAbstractTableModel): return _("(filtered)") elif c.queue == 1: date = c.due - elif c.queue == 0 or c.type == 0: + elif c.queue == QUEUE_TYPE_NEW or c.type == CARD_TYPE_NEW: return str(c.due) elif c.queue in (2, 3) or (c.type == 2 and c.queue < 0): date = time.time() + ((c.due - self.col.sched.today) * 86400) @@ -1428,7 +1428,7 @@ border: 1px solid #000; padding: 3px; '>%s""" import anki.stats as st fmt = "%s" - if type == 0: + if type == CARD_TYPE_NEW: tstr = fmt % (st.colLearn, tstr) elif type == 1: tstr = fmt % (st.colMature, tstr) @@ -1936,7 +1936,7 @@ update cards set usn=?, mod=?, did=? where id in """ def _reposition(self): cids = self.selectedCards() cids2 = self.col.db.list( - "select id from cards where type = 0 and id in " + ids2str(cids) + f"select id from cards where type = {CARD_TYPE_NEW} and id in " + ids2str(cids) ) if not cids2: return showInfo(_("Only new cards can be repositioned.")) @@ -1945,7 +1945,7 @@ update cards set usn=?, mod=?, did=? where id in """ frm = aqt.forms.reposition.Ui_Dialog() frm.setupUi(d) (pmin, pmax) = self.col.db.first( - "select min(due), max(due) from cards where type=0 and odid=0" + f"select min(due), max(due) from cards where type={CARD_TYPE_NEW} and odid=0" ) pmin = pmin or 0 pmax = pmax or 0 From 69436643fe7a0a3802486d38a824bade293e2141 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 2 Feb 2020 01:28:04 -0800 Subject: [PATCH 31/38] CARD_TYPE_LRN and QUEUE_TYPE_LRN --- pylib/anki/consts.py | 2 ++ pylib/anki/find.py | 6 +++--- pylib/anki/importing/anki2.py | 4 ++-- pylib/anki/sched.py | 36 ++++++++++++++++----------------- pylib/anki/schedv2.py | 38 +++++++++++++++++------------------ pylib/anki/stats.py | 6 +++--- pylib/tests/test_schedv1.py | 20 +++++++++--------- pylib/tests/test_schedv2.py | 26 ++++++++++++------------ pylib/tests/test_undo.py | 2 +- qt/aqt/browser.py | 4 ++-- 10 files changed, 73 insertions(+), 71 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index f3d9fd1a9..58af8955b 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -16,9 +16,11 @@ NEW_CARDS_DUE = 1 # Queue types QUEUE_TYPE_NEW = 0 +QUEUE_TYPE_LRN = 1 # Card types CARD_TYPE_NEW = 0 +CARD_TYPE_LRN = 1 # removal types REM_CARD = 0 diff --git a/pylib/anki/find.py b/pylib/anki/find.py index 57a66d03b..45fa8851d 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -273,16 +273,16 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ elif val == "new": n = CARD_TYPE_NEW else: - return "queue in (1, 3)" + return f"queue in ({QUEUE_TYPE_LRN}, 3)" return "type = %d" % n elif val == "suspended": return "c.queue = -1" elif val == "buried": return "c.queue in (-2, -3)" elif val == "due": - return """ + return f""" (c.queue in (2,3) and c.due <= %d) or -(c.queue = 1 and c.due <= %d)""" % ( +(c.queue = {QUEUE_TYPE_LRN} and c.due <= %d)""" % ( self.col.sched.today, self.col.sched.dayCutoff, ) diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index ee681d570..35a56309e 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -357,12 +357,12 @@ class Anki2Importer(Importer): card[8] = card[14] card[14] = 0 # queue - if card[6] == 1: # type + if card[6] == CARD_TYPE_LRN: # type card[7] = QUEUE_TYPE_NEW else: card[7] = card[6] # type - if card[6] == 1: + if card[6] == CARD_TYPE_LRN: card[6] = CARD_TYPE_NEW cards.append(card) # we need to import revlog, rewriting card ids and bumping usn diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 2bf2fbafb..626bf656d 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -71,10 +71,10 @@ class Scheduler: wasNewQ = card.queue == QUEUE_TYPE_NEW if wasNewQ: # came from the new queue, move to learning - card.queue = 1 + card.queue = QUEUE_TYPE_LRN # if it was a new card, it's now a learning card if card.type == CARD_TYPE_NEW: - card.type = 1 + card.type = CARD_TYPE_LRN # init reps to graduation card.left = self._startingLeft(card) # dynamic? @@ -84,7 +84,7 @@ class Scheduler: card.ivl = self._dynIvlBoost(card) card.odue = self.today + card.ivl self._updateStats(card, "new") - if card.queue in (1, 3): + if card.queue in (QUEUE_TYPE_LRN, 3): self._answerLrnCard(card, ease) if not wasNewQ: self._updateStats(card, "lrn") @@ -142,7 +142,7 @@ order by due""" if card.odid and card.queue == 2: return 4 conf = self._lrnConf(card) - if card.type in (CARD_TYPE_NEW, 1) or len(conf["delays"]) > 1: + if card.type in (CARD_TYPE_NEW, CARD_TYPE_LRN) or len(conf["delays"]) > 1: return 3 return 2 elif card.queue == 2: @@ -466,9 +466,9 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_NEW} limit ?)""" # sub-day self.lrnCount = ( self.col.db.scalar( - """ + f""" select sum(left/1000) from (select left from cards where -did in %s and queue = 1 and due < ? limit %d)""" +did in %s and queue = {QUEUE_TYPE_LRN} and due < ? limit %d)""" % (self._deckLimit(), self.reportLimit), self.dayCutoff, ) @@ -496,9 +496,9 @@ and due <= ? limit %d""" if self._lrnQueue: return True self._lrnQueue = self.col.db.all( - """ + f""" select due, id from cards where -did in %s and queue = 1 and due < :lim +did in %s and queue = {QUEUE_TYPE_LRN} and due < :lim limit %d""" % (self._deckLimit(), self.reportLimit), lim=self.dayCutoff, @@ -601,7 +601,7 @@ did = ? and queue = 3 and due <= ? limit ?""", # if the queue is not empty and there's nothing else to do, make # sure we don't put it at the head of the queue and end up showing # it twice in a row - card.queue = 1 + card.queue = QUEUE_TYPE_LRN if self._lrnQueue and not self.revCount and not self.newCount: smallestDue = self._lrnQueue[0][0] card.due = max(card.due, smallestDue + 1) @@ -736,25 +736,25 @@ did = ? and queue = 3 and due <= ? limit ?""", extra = " and did in " + ids2str(self.col.decks.allIds()) # review cards in relearning self.col.db.execute( - """ + f""" update cards set due = odue, queue = 2, mod = %d, usn = %d, odue = 0 -where queue in (1,3) and type = 2 +where queue in ({QUEUE_TYPE_LRN},3) and type = 2 %s """ % (intTime(), self.col.usn(), extra) ) # new cards in learning self.forgetCards( - self.col.db.list("select id from cards where queue in (1,3) %s" % extra) + self.col.db.list(f"select id from cards where queue in ({QUEUE_TYPE_LRN},3) %s" % extra) ) def _lrnForDeck(self, did): cnt = ( self.col.db.scalar( - """ + f""" select sum(left/1000) from -(select left from cards where did = ? and queue = 1 and due < ? limit ?)""", +(select left from cards where did = ? and queue = {QUEUE_TYPE_LRN} and due < ? limit ?)""", did, intTime() + self.col.conf["collapseTime"], self.reportLimit, @@ -907,7 +907,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" # queue 1 if card.due < self.dayCutoff: self.lrnCount += card.left // 1000 - card.queue = 1 + card.queue = QUEUE_TYPE_LRN heappush(self._lrnQueue, (card.due, card.id)) else: # day learn queue @@ -1059,8 +1059,8 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" # move out of cram queue self.col.db.execute( f""" -update cards set did = odid, queue = (case when type = 1 then {QUEUE_TYPE_NEW} -else type end), type = (case when type = 1 then {CARD_TYPE_NEW} else type end), +update cards set did = odid, queue = (case when type = {CARD_TYPE_LRN} then {QUEUE_TYPE_NEW} +else type end), type = (case when type = {CARD_TYPE_LRN} then {CARD_TYPE_NEW} else type end), due = odue, odue = 0, odid = 0, usn = ? where %s""" % lim, self.col.usn(), @@ -1347,7 +1347,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" def nextIvl(self, card, ease): "Return the next interval for CARD, in seconds." - if card.queue in (QUEUE_TYPE_NEW, 1, 3): + if card.queue in (QUEUE_TYPE_NEW, QUEUE_TYPE_LRN, 3): return self._nextLrnIvl(card, ease) elif ease == BUTTON_ONE: # lapsed diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 8c1d1e2fe..efc6030c5 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -97,14 +97,14 @@ class Scheduler: if card.queue == QUEUE_TYPE_NEW: # came from the new queue, move to learning - card.queue = 1 - card.type = 1 + card.queue = QUEUE_TYPE_LRN + card.type = CARD_TYPE_LRN # init reps to graduation card.left = self._startingLeft(card) # update daily limit self._updateStats(card, "new") - if card.queue in (1, QUEUE_TYPE_DAY_LEARN_RELEARN): + if card.queue in (QUEUE_TYPE_LRN, QUEUE_TYPE_DAY_LEARN_RELEARN): self._answerLrnCard(card, ease) elif card.queue == 2: self._answerRevCard(card, ease) @@ -505,8 +505,8 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_NEW} limit ?)""" # sub-day self.lrnCount = ( self.col.db.scalar( - """ -select count() from cards where did in %s and queue = 1 + f""" +select count() from cards where did in %s and queue = {QUEUE_TYPE_LRN} and due < ?""" % (self._deckLimit()), self._lrnCutoff, @@ -546,7 +546,7 @@ select count() from cards where did in %s and queue = {QUEUE_TYPE_PREVIEW} self._lrnQueue = self.col.db.all( f""" select due, id from cards where -did in %s and queue in (1,{QUEUE_TYPE_PREVIEW}) and due < :lim +did in %s and queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_PREVIEW}) and due < :lim limit %d""" % (self._deckLimit(), self.reportLimit), lim=cutoff, @@ -674,7 +674,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", maxExtra = min(300, int(delay * 0.25)) fuzz = random.randrange(0, maxExtra) card.due = min(self.dayCutoff - 1, card.due + fuzz) - card.queue = 1 + card.queue = QUEUE_TYPE_LRN if card.due < (intTime() + self.col.conf["collapseTime"]): self.lrnCount += 1 # if the queue is not empty and there's nothing else to do, make @@ -831,9 +831,9 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", def _lrnForDeck(self, did: int) -> Any: cnt = ( self.col.db.scalar( - """ + f""" select count() from -(select null from cards where did = ? and queue = 1 and due < ? limit ?)""", +(select null from cards where did = ? and queue = {QUEUE_TYPE_LRN} and due < ? limit ?)""", did, intTime() + self.col.conf["collapseTime"], self.reportLimit, @@ -1261,9 +1261,9 @@ where id = ? # learning and relearning cards may be seconds-based or day-based; # other types map directly to queues - if card.type in (1, CARD_TYPE_RELEARNING): + if card.type in (CARD_TYPE_LRN, CARD_TYPE_RELEARNING): if card.odue > 1000000000: - card.queue = 1 + card.queue = QUEUE_TYPE_LRN else: card.queue = QUEUE_TYPE_DAY_LEARN_RELEARN else: @@ -1563,7 +1563,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" return 0 # (re)learning? - if card.queue in (QUEUE_TYPE_NEW, 1, QUEUE_TYPE_DAY_LEARN_RELEARN): + if card.queue in (QUEUE_TYPE_NEW, QUEUE_TYPE_LRN, QUEUE_TYPE_DAY_LEARN_RELEARN): return self._nextLrnIvl(card, ease) elif ease == BUTTON_ONE: # lapse @@ -1605,7 +1605,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" # learning and relearning cards may be seconds-based or day-based; # other types map directly to queues _restoreQueueSnippet = f""" -queue = (case when type in (1,{CARD_TYPE_RELEARNING}) then +queue = (case when type in ({CARD_TYPE_LRN},{CARD_TYPE_RELEARNING}) then (case when (case when odue then odue else due end) > 1000000000 then 1 else {QUEUE_TYPE_DAY_LEARN_RELEARN} end) else @@ -1875,10 +1875,10 @@ and due >= ? and queue = {QUEUE_TYPE_NEW}""" self.col.db.execute( f""" update cards set did = odid, queue = (case -when type = 1 then {QUEUE_TYPE_NEW} +when type = {CARD_TYPE_LRN} then {QUEUE_TYPE_NEW} when type = {CARD_TYPE_RELEARNING} then 2 else type end), type = (case -when type = 1 then {CARD_TYPE_NEW} +when type = {CARD_TYPE_LRN} then {CARD_TYPE_NEW} when type = {CARD_TYPE_RELEARNING} then 2 else type end), due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", @@ -1892,7 +1892,7 @@ due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", f""" update cards set due = odue, queue = 2, type = 2, mod = %d, usn = %d, odue = 0 - where queue in (1,{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in (2, {CARD_TYPE_RELEARNING}) + where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in (2, {CARD_TYPE_RELEARNING}) """ % (intTime(), self.col.usn()) ) @@ -1901,14 +1901,14 @@ due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", f""" update cards set due = %d+ivl, queue = 2, type = 2, mod = %d, usn = %d, odue = 0 - where queue in (1,{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in (2, {CARD_TYPE_RELEARNING}) + where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in (2, {CARD_TYPE_RELEARNING}) """ % (self.today, intTime(), self.col.usn()) ) # remove new cards from learning self.forgetCards( self.col.db.list( - f"select id from cards where queue in (1,{QUEUE_TYPE_DAY_LEARN_RELEARN})" + f"select id from cards where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN})" ) ) @@ -1917,7 +1917,7 @@ due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", self.col.db.execute( f""" update cards set type = (case -when type = 1 then {CARD_TYPE_NEW} +when type = {CARD_TYPE_LRN} then {CARD_TYPE_NEW} when type in (2, {CARD_TYPE_RELEARNING}) then 2 else type end), due = (case when odue then odue else due end), diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index 32e24341a..ed8c318eb 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -35,7 +35,7 @@ class CardStats: if first: self.addLine(_("First Review"), self.date(first / 1000)) self.addLine(_("Latest Review"), self.date(last / 1000)) - if c.type in (1, 2): + if c.type in (CARD_TYPE_LRN, 2): if c.odid or c.queue < QUEUE_TYPE_NEW: next = None else: @@ -676,7 +676,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" types = ("lrn", "yng", "mtr") eases = self._eases() for (type, ease, cnt) in eases: - if type == 1: + if type == CARD_TYPE_LRN: ease += 5 elif type == 2: ease += 10 @@ -944,7 +944,7 @@ from cards where did in %s and queue = 2""" f""" select sum(case when queue=2 and ivl >= 21 then 1 else 0 end), -- mtr -sum(case when queue in (1,3) or (queue=2 and ivl < 21) then 1 else 0 end), -- yng/lrn +sum(case when queue in ({QUEUE_TYPE_LRN},3) or (queue=2 and ivl < 21) then 1 else 0 end), -- yng/lrn sum(case when queue={QUEUE_TYPE_NEW} then 1 else 0 end), -- new sum(case when queue<{QUEUE_TYPE_NEW} then 1 else 0 end) -- susp from cards where did in %s""" diff --git a/pylib/tests/test_schedv1.py b/pylib/tests/test_schedv1.py index 186637340..9e69873c7 100644 --- a/pylib/tests/test_schedv1.py +++ b/pylib/tests/test_schedv1.py @@ -51,8 +51,8 @@ def test_new(): # if we answer it, it should become a learn card t = intTime() d.sched.answerCard(c, 1) - assert c.queue == 1 - assert c.type == 1 + assert c.queue == QUEUE_TYPE_LRN + assert c.type == CARD_TYPE_LRN assert c.due >= t # disabled for now, as the learn fudging makes this randomly fail @@ -163,8 +163,8 @@ def test_learn(): assert c.left % 1000 == 1 assert c.left // 1000 == 1 # the next pass should graduate the card - assert c.queue == 1 - assert c.type == 1 + assert c.queue == QUEUE_TYPE_LRN + assert c.type == CARD_TYPE_LRN d.sched.answerCard(c, 2) assert c.queue == 2 assert c.type == 2 @@ -259,7 +259,7 @@ def test_learn_day(): assert ni(c, 2) == 86400 * 2 # if we fail it, it should be back in the correct queue d.sched.answerCard(c, 1) - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN d.undo() d.reset() c = d.sched.getCard() @@ -311,7 +311,7 @@ def test_reviews(): d.reset() d.sched._cardConf(c)["lapse"]["delays"] = [2, 20] d.sched.answerCard(c, 1) - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN # it should be due tomorrow, with an interval of 1 assert c.odue == d.sched.today + 1 assert c.ivl == 1 @@ -558,7 +558,7 @@ def test_suspend(): c = d.sched.getCard() d.sched.answerCard(c, 1) assert c.due >= time.time() - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN assert c.type == 2 d.sched.suspendCards([c.id]) d.sched.unsuspendCards([c.id]) @@ -622,7 +622,7 @@ def test_cram(): # int(75*1.85) = 138 assert c.ivl == 138 assert c.odue == 138 - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN # should be logged as a cram rep assert d.db.scalar("select type from revlog order by id desc limit 1") == 3 # check ivls again @@ -702,7 +702,7 @@ def test_cram_rem(): c = d.sched.getCard() d.sched.answerCard(c, 2) # answering the card will put it in the learning queue - assert c.type == c.queue == 1 + assert c.type == CARD_TYPE_LRN and c.queue == QUEUE_TYPE_LRN assert c.due != oldDue # if we terminate cramming prematurely it should be set back to new d.sched.emptyDyn(did) @@ -950,7 +950,7 @@ def test_timing(): time.time = adjusted_time c = d.sched.getCard() - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN time.time = orig_time diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index be4cfa144..2ab46fca5 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -62,8 +62,8 @@ def test_new(): # if we answer it, it should become a learn card t = intTime() d.sched.answerCard(c, 1) - assert c.queue == 1 - assert c.type == 1 + assert c.queue == QUEUE_TYPE_LRN + assert c.type == CARD_TYPE_LRN assert c.due >= t # disabled for now, as the learn fudging makes this randomly fail @@ -176,8 +176,8 @@ def test_learn(): assert c.left % 1000 == 1 assert c.left // 1000 == 1 # the next pass should graduate the card - assert c.queue == 1 - assert c.type == 1 + assert c.queue == QUEUE_TYPE_LRN + assert c.type == CARD_TYPE_LRN d.sched.answerCard(c, 3) assert c.queue == 2 assert c.type == 2 @@ -210,7 +210,7 @@ def test_relearn(): d.reset() c = d.sched.getCard() d.sched.answerCard(c, 1) - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN assert c.type == 3 assert c.ivl == 1 @@ -303,7 +303,7 @@ def test_learn_day(): assert ni(c, 3) == 86400 * 2 # if we fail it, it should be back in the correct queue d.sched.answerCard(c, 1) - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN d.undo() d.reset() c = d.sched.getCard() @@ -679,12 +679,12 @@ def test_suspend(): d.sched.answerCard(c, 1) assert c.due >= time.time() due = c.due - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN assert c.type == 3 d.sched.suspendCards([c.id]) d.sched.unsuspendCards([c.id]) c.load() - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN assert c.type == 3 assert c.due == due # should cope with cards in cram decks @@ -771,11 +771,11 @@ def test_filt_keep_lrn_state(): d.sched.answerCard(c, 1) - assert c.type == c.queue == 1 + assert c.type == CARD_TYPE_LRN and c.queue == QUEUE_TYPE_LRN assert c.left == 3003 d.sched.answerCard(c, 3) - assert c.type == c.queue == 1 + assert c.type == CARD_TYPE_LRN and c.queue == QUEUE_TYPE_LRN # create a dynamic deck and refresh it did = d.decks.newDyn("Cram") @@ -784,7 +784,7 @@ def test_filt_keep_lrn_state(): # card should still be in learning state c.load() - assert c.type == c.queue == 1 + assert c.type == CARD_TYPE_LRN and c.queue == QUEUE_TYPE_LRN assert c.left == 2002 # should be able to advance learning steps @@ -795,7 +795,7 @@ def test_filt_keep_lrn_state(): # emptying the deck preserves learning state d.sched.emptyDyn(did) c.load() - assert c.type == c.queue == 1 + assert c.type == CARD_TYPE_LRN and c.queue == QUEUE_TYPE_LRN assert c.left == 1001 assert c.due - intTime() > 60 * 60 @@ -977,7 +977,7 @@ def test_timing(): c.flush() d.reset() c = d.sched.getCard() - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN def test_collapse(): diff --git a/pylib/tests/test_undo.py b/pylib/tests/test_undo.py index a4a8a7098..89e0fac0e 100644 --- a/pylib/tests/test_undo.py +++ b/pylib/tests/test_undo.py @@ -59,7 +59,7 @@ def test_review(): d.sched.answerCard(c, 3) assert c.left == 1001 assert d.sched.counts() == (0, 1, 0) - assert c.queue == 1 + assert c.queue == QUEUE_TYPE_LRN # undo assert d.undoName() d.undo() diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index 77af12b3f..57af170eb 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -333,7 +333,7 @@ class DataModel(QAbstractTableModel): def nextDue(self, c, index): if c.odid: return _("(filtered)") - elif c.queue == 1: + elif c.queue == QUEUE_TYPE_LRN: date = c.due elif c.queue == QUEUE_TYPE_NEW or c.type == CARD_TYPE_NEW: return str(c.due) @@ -1430,7 +1430,7 @@ border: 1px solid #000; padding: 3px; '>%s""" fmt = "%s" if type == CARD_TYPE_NEW: tstr = fmt % (st.colLearn, tstr) - elif type == 1: + elif type == CARD_TYPE_LRN: tstr = fmt % (st.colMature, tstr) elif type == 2: tstr = fmt % (st.colRelearn, tstr) From 4a21911d74a9f346e0a76afc7bfda1ebbb936b0e Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 19:21:20 -0800 Subject: [PATCH 32/38] QUEUE_USER_BURIED --- pylib/anki/consts.py | 1 + pylib/anki/find.py | 2 +- pylib/anki/schedv2.py | 2 +- pylib/tests/test_schedv2.py | 4 ++-- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 58af8955b..363ef1b9d 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -15,6 +15,7 @@ NEW_CARDS_RANDOM = 0 NEW_CARDS_DUE = 1 # Queue types +QUEUE_TYPE_MANUALLY_BURIED = -3 QUEUE_TYPE_NEW = 0 QUEUE_TYPE_LRN = 1 diff --git a/pylib/anki/find.py b/pylib/anki/find.py index 45fa8851d..e44726153 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -278,7 +278,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ elif val == "suspended": return "c.queue = -1" elif val == "buried": - return "c.queue in (-2, -3)" + return f"c.queue in (-2, {QUEUE_TYPE_MANUALLY_BURIED})" elif val == "due": return f""" (c.queue in (2,3) and c.due <= %d) or diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index efc6030c5..0c70e399b 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -28,7 +28,7 @@ CARD_TYPE_RELEARNING = 3 QUEUE_TYPE_PREVIEW = 4 QUEUE_TYPE_DAY_LEARN_RELEARN = 3 QUEUE_TYPE_SIBLING_BURIED = -2 -QUEUE_TYPE_MANUALLY_BURIED = -3 + # revlog types: 0=lrn, 1=rev, 2=relrn, 3=early review # positive revlog intervals are in days (rev), negative in seconds (lrn) # odue/odid store original due/did when cards moved to filtered deck diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index 2ab46fca5..22fef573c 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -624,7 +624,7 @@ def test_bury(): # burying d.sched.buryCards([c.id], manual=True) # pylint: disable=unexpected-keyword-arg c.load() - assert c.queue == -3 + assert c.queue == QUEUE_TYPE_MANUALLY_BURIED d.sched.buryCards([c2.id], manual=False) # pylint: disable=unexpected-keyword-arg c2.load() assert c2.queue == -2 @@ -1226,7 +1226,7 @@ def test_moveVersions(): col.sched.answerCard(c, 1) col.sched.buryCards([c.id]) c.load() - assert c.queue == -3 + assert c.queue == QUEUE_TYPE_MANUALLY_BURIED # revert to version 1 col.changeSchedulerVer(1) From 9fc3f17f5cd203532298913daad226709acf8c25 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 19:40:51 -0800 Subject: [PATCH 33/38] QUEUE_TYPE_SIBLING_BURIED --- pylib/anki/consts.py | 1 + pylib/anki/find.py | 2 +- pylib/anki/sched.py | 16 ++++++++-------- pylib/anki/schedv2.py | 5 ++--- pylib/tests/test_schedv2.py | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index 363ef1b9d..ddeddd03b 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -16,6 +16,7 @@ NEW_CARDS_DUE = 1 # Queue types QUEUE_TYPE_MANUALLY_BURIED = -3 +QUEUE_TYPE_SIBLING_BURIED = -2 QUEUE_TYPE_NEW = 0 QUEUE_TYPE_LRN = 1 diff --git a/pylib/anki/find.py b/pylib/anki/find.py index e44726153..4fbb209b2 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -278,7 +278,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ elif val == "suspended": return "c.queue = -1" elif val == "buried": - return f"c.queue in (-2, {QUEUE_TYPE_MANUALLY_BURIED})" + return f"c.queue in ({QUEUE_TYPE_SIBLING_BURIED}, {QUEUE_TYPE_MANUALLY_BURIED})" elif val == "due": return f""" (c.queue in (2,3) and c.due <= %d) or diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 626bf656d..7fcc07257 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -153,18 +153,18 @@ order by due""" def unburyCards(self): "Unbury cards." self.col.conf["lastUnburied"] = self.today - self.col.log(self.col.db.list("select id from cards where queue = -2")) - self.col.db.execute("update cards set queue=type where queue = -2") + self.col.log(self.col.db.list(f"select id from cards where queue = {QUEUE_TYPE_SIBLING_BURIED}")) + self.col.db.execute(f"update cards set queue=type where queue = {QUEUE_TYPE_SIBLING_BURIED}") def unburyCardsForDeck(self): sids = ids2str(self.col.decks.active()) self.col.log( self.col.db.list( - "select id from cards where queue = -2 and did in %s" % sids + f"select id from cards where queue = {QUEUE_TYPE_SIBLING_BURIED} and did in %s" % sids ) ) self.col.db.execute( - "update cards set mod=?,usn=?,queue=type where queue = -2 and did in %s" + f"update cards set mod=?,usn=?,queue=type where queue = {QUEUE_TYPE_SIBLING_BURIED} and did in %s" % sids, intTime(), self.col.usn(), @@ -1328,7 +1328,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" def haveBuried(self): sdids = ids2str(self.col.decks.active()) cnt = self.col.db.scalar( - "select 1 from cards where queue = -2 and did in %s limit 1" % sdids + f"select 1 from cards where queue = {QUEUE_TYPE_SIBLING_BURIED} and did in %s limit 1" % sdids ) return not not cnt @@ -1411,8 +1411,8 @@ To study outside of the normal schedule, click the Custom Study button below.""" self.remFromDyn(cids) self.removeLrn(cids) self.col.db.execute( - """ -update cards set queue=-2,mod=?,usn=? where id in """ + f""" +update cards set queue={QUEUE_TYPE_SIBLING_BURIED},mod=?,usn=? where id in """ + ids2str(cids), intTime(), self.col.usn(), @@ -1462,7 +1462,7 @@ and (queue={QUEUE_TYPE_NEW} or (queue=2 and due<=?))""", # then bury if toBury: self.col.db.execute( - "update cards set queue=-2,mod=?,usn=? where id in " + ids2str(toBury), + f"update cards set queue={QUEUE_TYPE_SIBLING_BURIED},mod=?,usn=? where id in " + ids2str(toBury), intTime(), self.col.usn(), ) diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 0c70e399b..9dc4a4c5d 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -27,7 +27,6 @@ CARD_TYPE_RELEARNING = 3 # 4=preview, -1=suspended, -2=sibling buried, -3=manually buried QUEUE_TYPE_PREVIEW = 4 QUEUE_TYPE_DAY_LEARN_RELEARN = 3 -QUEUE_TYPE_SIBLING_BURIED = -2 # revlog types: 0=lrn, 1=rev, 2=relrn, 3=early review # positive revlog intervals are in days (rev), negative in seconds (lrn) @@ -1655,11 +1654,11 @@ update cards set queue=?,mod=?,usn=? where id in """ "Unbury all buried cards in all decks." self.col.log( self.col.db.list( - f"select id from cards where queue in (-2, {QUEUE_TYPE_MANUALLY_BURIED})" + f"select id from cards where queue in ({QUEUE_TYPE_SIBLING_BURIED}, {QUEUE_TYPE_MANUALLY_BURIED})" ) ) self.col.db.execute( - f"update cards set %s where queue in (-2, {QUEUE_TYPE_MANUALLY_BURIED})" + f"update cards set %s where queue in ({QUEUE_TYPE_SIBLING_BURIED}, {QUEUE_TYPE_MANUALLY_BURIED})" % self._restoreQueueSnippet ) diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index 22fef573c..88181b100 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -627,7 +627,7 @@ def test_bury(): assert c.queue == QUEUE_TYPE_MANUALLY_BURIED d.sched.buryCards([c2.id], manual=False) # pylint: disable=unexpected-keyword-arg c2.load() - assert c2.queue == -2 + assert c2.queue == QUEUE_TYPE_SIBLING_BURIED d.reset() assert not d.sched.getCard() @@ -636,7 +636,7 @@ def test_bury(): c.load() assert c.queue == QUEUE_TYPE_NEW c2.load() - assert c2.queue == -2 + assert c2.queue == QUEUE_TYPE_SIBLING_BURIED d.sched.unburyCardsForDeck( # pylint: disable=unexpected-keyword-arg type="siblings" @@ -1233,7 +1233,7 @@ def test_moveVersions(): # card should have moved queues c.load() - assert c.queue == -2 + assert c.queue == QUEUE_TYPE_SIBLING_BURIED # and it should be new again when unburied col.sched.unburyCards() From 7d4506afdbf90204279bb9b92c91bc851c373ffa Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 19:48:14 -0800 Subject: [PATCH 34/38] QUEUE_TYPE_SUSPENDED --- pylib/anki/consts.py | 1 + pylib/anki/sched.py | 8 ++++---- pylib/anki/schedv2.py | 10 +++++----- pylib/tests/test_schedv1.py | 4 ++-- pylib/tests/test_schedv2.py | 4 ++-- 5 files changed, 14 insertions(+), 13 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index ddeddd03b..c512f091d 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -17,6 +17,7 @@ NEW_CARDS_DUE = 1 # Queue types QUEUE_TYPE_MANUALLY_BURIED = -3 QUEUE_TYPE_SIBLING_BURIED = -2 +QUEUE_TYPE_SUSPENDED = -1 QUEUE_TYPE_NEW = 0 QUEUE_TYPE_LRN = 1 diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 7fcc07257..26e065635 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -893,7 +893,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" card.odue = card.due # if suspended as a leech, nothing to do delay = 0 - if self._checkLeech(card, conf) and card.queue == -1: + if self._checkLeech(card, conf) and card.queue == QUEUE_TYPE_SUSPENDED: return delay # if no relearning steps, nothing to do if not conf["delays"]: @@ -1152,7 +1152,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?""" if card.odid: card.did = card.odid card.odue = card.odid = 0 - card.queue = -1 + card.queue = QUEUE_TYPE_SUSPENDED # notify UI hooks.card_did_leech(card) return True @@ -1391,7 +1391,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" self.remFromDyn(ids) self.removeLrn(ids) self.col.db.execute( - "update cards set queue=-1,mod=?,usn=? where id in " + ids2str(ids), + f"update cards set queue={QUEUE_TYPE_SUSPENDED},mod=?,usn=? where id in " + ids2str(ids), intTime(), self.col.usn(), ) @@ -1401,7 +1401,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" self.col.log(ids) self.col.db.execute( "update cards set queue=type,mod=?,usn=? " - "where queue = -1 and id in " + ids2str(ids), + f"where queue = {QUEUE_TYPE_SUSPENDED} and id in " + ids2str(ids), intTime(), self.col.usn(), ) diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 9dc4a4c5d..613e44d1c 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -976,7 +976,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" card.lapses += 1 card.factor = max(1300, card.factor - 200) - suspended = self._checkLeech(card, conf) and card.queue == -1 + suspended = self._checkLeech(card, conf) and card.queue == QUEUE_TYPE_SUSPENDED if conf["delays"] and not suspended: card.type = CARD_TYPE_RELEARNING @@ -987,7 +987,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" self._rescheduleAsRev(card, conf, early=False) # need to reset the queue after rescheduling if suspended: - card.queue = -1 + card.queue = QUEUE_TYPE_SUSPENDED delay = 0 return delay @@ -1285,7 +1285,7 @@ where id = ? # handle a = conf["leechAction"] if a == LEECH_SUSPEND: - card.queue = -1 + card.queue = QUEUE_TYPE_SUSPENDED # notify UI hooks.card_did_leech(card) return True @@ -1616,7 +1616,7 @@ end) "Suspend cards." self.col.log(ids) self.col.db.execute( - "update cards set queue=-1,mod=?,usn=? where id in " + ids2str(ids), + f"update cards set queue={QUEUE_TYPE_SUSPENDED},mod=?,usn=? where id in " + ids2str(ids), intTime(), self.col.usn(), ) @@ -1625,7 +1625,7 @@ end) "Unsuspend cards." self.col.log(ids) self.col.db.execute( - ("update cards set %s,mod=?,usn=? " "where queue = -1 and id in %s") + (f"update cards set %s,mod=?,usn=? where queue = {QUEUE_TYPE_SUSPENDED} and id in %s") % (self._restoreQueueSnippet, ids2str(ids)), intTime(), self.col.usn(), diff --git a/pylib/tests/test_schedv1.py b/pylib/tests/test_schedv1.py index 9e69873c7..7b75a710e 100644 --- a/pylib/tests/test_schedv1.py +++ b/pylib/tests/test_schedv1.py @@ -376,9 +376,9 @@ def test_reviews(): hooks.card_did_leech.append(onLeech) d.sched.answerCard(c, 1) assert hooked - assert c.queue == -1 + assert c.queue == QUEUE_TYPE_SUSPENDED c.load() - assert c.queue == -1 + assert c.queue == QUEUE_TYPE_SUSPENDED def test_button_spacing(): diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index 88181b100..db76ad460 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -398,9 +398,9 @@ def test_reviews(): hooks.card_did_leech.append(onLeech) d.sched.answerCard(c, 1) assert hooked - assert c.queue == -1 + assert c.queue == QUEUE_TYPE_SUSPENDED c.load() - assert c.queue == -1 + assert c.queue == QUEUE_TYPE_SUSPENDED def test_review_limits(): From 45bf763238f1cc2f3c538c3f4913ce0cd0b39aff Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 2 Feb 2020 01:40:30 -0800 Subject: [PATCH 35/38] QUEUE_TYPE_REV and CARD_TYPE_REV --- pylib/anki/cards.py | 4 +- pylib/anki/consts.py | 2 + pylib/anki/find.py | 4 +- pylib/anki/importing/anki2.py | 2 +- pylib/anki/sched.py | 64 ++++++++++++++-------------- pylib/anki/schedv2.py | 68 ++++++++++++++--------------- pylib/anki/stats.py | 32 +++++++------- pylib/tests/test_find.py | 5 ++- pylib/tests/test_schedv1.py | 80 ++++++++++++++++++----------------- pylib/tests/test_schedv2.py | 76 +++++++++++++++++---------------- qt/aqt/browser.py | 2 +- 11 files changed, 174 insertions(+), 165 deletions(-) diff --git a/pylib/anki/cards.py b/pylib/anki/cards.py index 19845566a..145d2b275 100644 --- a/pylib/anki/cards.py +++ b/pylib/anki/cards.py @@ -88,7 +88,7 @@ class Card: self.mod = intTime() self.usn = self.col.usn() # bug check - if self.queue == 2 and self.odue and not self.col.decks.isDyn(self.did): + if self.queue == QUEUE_TYPE_REV and self.odue and not self.col.decks.isDyn(self.did): hooks.card_odue_was_invalid() assert self.due < 4294967296 self.col.db.execute( @@ -120,7 +120,7 @@ insert or replace into cards values self.mod = intTime() self.usn = self.col.usn() # bug checks - if self.queue == 2 and self.odue and not self.col.decks.isDyn(self.did): + if self.queue == QUEUE_TYPE_REV and self.odue and not self.col.decks.isDyn(self.did): hooks.card_odue_was_invalid() assert self.due < 4294967296 self.col.db.execute( diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index c512f091d..f49bcbf99 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -20,10 +20,12 @@ QUEUE_TYPE_SIBLING_BURIED = -2 QUEUE_TYPE_SUSPENDED = -1 QUEUE_TYPE_NEW = 0 QUEUE_TYPE_LRN = 1 +QUEUE_TYPE_REV = 2 # Card types CARD_TYPE_NEW = 0 CARD_TYPE_LRN = 1 +CARD_TYPE_REV = 2 # removal types REM_CARD = 0 diff --git a/pylib/anki/find.py b/pylib/anki/find.py index 4fbb209b2..026307c70 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -281,7 +281,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ return f"c.queue in ({QUEUE_TYPE_SIBLING_BURIED}, {QUEUE_TYPE_MANUALLY_BURIED})" elif val == "due": return f""" -(c.queue in (2,3) and c.due <= %d) or +(c.queue in ({QUEUE_TYPE_REV},3) and c.due <= %d) or (c.queue = {QUEUE_TYPE_LRN} and c.due <= %d)""" % ( self.col.sched.today, self.col.sched.dayCutoff, @@ -349,7 +349,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ if prop == "due": val += self.col.sched.today # only valid for review/daily learning - q.append("(c.queue in (2,3))") + q.append(f"(c.queue in ({QUEUE_TYPE_REV},3))") elif prop == "ease": prop = "factor" val = int(val * 1000) diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index 35a56309e..e7f952614 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -344,7 +344,7 @@ class Anki2Importer(Importer): card[4] = intTime() card[5] = usn # review cards have a due date relative to collection - if card[7] in (2, 3) or card[6] == 2: + if card[7] in (QUEUE_TYPE_REV, 3) or card[6] == CARD_TYPE_REV: card[8] -= aheadBy # odue needs updating too if card[14]: diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 26e065635..f30dedbe6 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -78,7 +78,7 @@ class Scheduler: # init reps to graduation card.left = self._startingLeft(card) # dynamic? - if card.odid and card.type == 2: + if card.odid and card.type == CARD_TYPE_REV: if self._resched(card): # reviews get their ivl boosted on first sight card.ivl = self._dynIvlBoost(card) @@ -88,7 +88,7 @@ class Scheduler: self._answerLrnCard(card, ease) if not wasNewQ: self._updateStats(card, "lrn") - elif card.queue == 2: + elif card.queue == QUEUE_TYPE_REV: self._answerRevCard(card, ease) self._updateStats(card, "rev") else: @@ -112,9 +112,9 @@ class Scheduler: "Return counts over next DAYS. Includes today." daysd = dict( self.col.db.all( - """ + f""" select due, count() from cards -where did in %s and queue = 2 +where did in %s and queue = {QUEUE_TYPE_REV} and due between ? and ? group by due order by due""" @@ -139,13 +139,13 @@ order by due""" def answerButtons(self, card): if card.odue: # normal review in dyn deck? - if card.odid and card.queue == 2: + if card.odid and card.queue == QUEUE_TYPE_REV: return 4 conf = self._lrnConf(card) if card.type in (CARD_TYPE_NEW, CARD_TYPE_LRN) or len(conf["delays"]) > 1: return 3 return 2 - elif card.queue == 2: + elif card.queue == QUEUE_TYPE_REV: return 4 else: return 3 @@ -557,7 +557,7 @@ did = ? and queue = 3 and due <= ? limit ?""", conf = self._lrnConf(card) if card.odid and not card.wasNew: type = REVLOG_CRAM - elif card.type == 2: + elif card.type == CARD_TYPE_REV: type = REVLOG_RELRN else: type = REVLOG_LRN @@ -627,13 +627,13 @@ did = ? and queue = 3 and due <= ? limit ?""", return delay * 60 def _lrnConf(self, card): - if card.type == 2: + if card.type == CARD_TYPE_REV: return self._lapseConf(card) else: return self._newConf(card) def _rescheduleAsRev(self, card, conf, early): - lapse = card.type == 2 + lapse = card.type == CARD_TYPE_REV if lapse: if self._resched(card): card.due = max(self.today + 1, card.odue) @@ -642,8 +642,8 @@ did = ? and queue = 3 and due <= ? limit ?""", card.odue = 0 else: self._rescheduleNew(card, conf, early) - card.queue = 2 - card.type = 2 + card.queue = QUEUE_TYPE_REV + card.type = CARD_TYPE_REV # if we were dynamic, graduating means moving back to the old deck resched = self._resched(card) if card.odid: @@ -656,7 +656,7 @@ did = ? and queue = 3 and due <= ? limit ?""", card.due = self.col.nextID("pos") def _startingLeft(self, card): - if card.type == 2: + if card.type == CARD_TYPE_REV: conf = self._lapseConf(card) else: conf = self._lrnConf(card) @@ -678,7 +678,7 @@ did = ? and queue = 3 and due <= ? limit ?""", return ok + 1 def _graduatingIvl(self, card, conf, early, adj=True): - if card.type == 2: + if card.type == CARD_TYPE_REV: # lapsed card being relearnt if card.odid: if conf["resched"]: @@ -738,8 +738,8 @@ did = ? and queue = 3 and due <= ? limit ?""", self.col.db.execute( f""" update cards set -due = odue, queue = 2, mod = %d, usn = %d, odue = 0 -where queue in ({QUEUE_TYPE_LRN},3) and type = 2 +due = odue, queue = {QUEUE_TYPE_REV}, mod = %d, usn = %d, odue = 0 +where queue in ({QUEUE_TYPE_LRN},3) and type = {CARD_TYPE_REV} %s """ % (intTime(), self.col.usn(), extra) @@ -786,9 +786,9 @@ and due <= ? limit ?)""", def _revForDeck(self, did, lim): lim = min(lim, self.reportLimit) return self.col.db.scalar( - """ + f""" select count() from -(select 1 from cards where did = ? and queue = 2 +(select 1 from cards where did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?)""", did, self.today, @@ -798,9 +798,9 @@ and due <= ? limit ?)""", def _resetRevCount(self): def cntFn(did, lim): return self.col.db.scalar( - """ + f""" select count() from (select id from cards where -did = ? and queue = 2 and due <= ? limit %d)""" +did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit %d)""" % lim, did, self.today, @@ -824,9 +824,9 @@ did = ? and queue = 2 and due <= ? limit %d)""" if lim: # fill the queue with the current did self._revQueue = self.col.db.list( - """ + f""" select id from cards where -did = ? and queue = 2 and due <= ? limit ?""", +did = ? and queue = {QUEUE_TYPE_REV} and due <= ? limit ?""", did, self.today, lim, @@ -861,9 +861,9 @@ did = ? and queue = 2 and due <= ? limit ?""", def totalRevForCurrentDeck(self): return self.col.db.scalar( - """ + f""" select count() from cards where id in ( -select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" +select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? limit ?)""" % ids2str(self.col.decks.active()), self.today, self.reportLimit, @@ -1088,7 +1088,7 @@ due = odue, odue = 0, odid = 0, usn = ? where %s""" t = "c.due" elif o == DYN_DUEPRIORITY: t = ( - "(case when queue=2 and due <= %d then (ivl / cast(%d-due+0.001 as real)) else 100000+due end)" + f"(case when queue={QUEUE_TYPE_REV} and due <= %d then (ivl / cast(%d-due+0.001 as real)) else 100000+due end)" % (self.today, self.today) ) else: @@ -1107,8 +1107,8 @@ due = odue, odue = 0, odid = 0, usn = ? where %s""" # due reviews stay in the review queue. careful: can't use # "odid or did", as sqlite converts to boolean queue = f""" -(case when type=2 and (case when odue then odue <= %d else due <= %d end) - then 2 else {QUEUE_TYPE_NEW} end)""" +(case when type={CARD_TYPE_REV} and (case when odue then odue <= %d else due <= %d end) + then {QUEUE_TYPE_REV} else {QUEUE_TYPE_NEW} end)""" queue %= (self.today, self.today) self.col.db.executemany( """ @@ -1121,7 +1121,7 @@ did = ?, queue = %s, due = ?, usn = ? where id = ?""" ) def _dynIvlBoost(self, card): - assert card.odid and card.type == 2 + assert card.odid and card.type == CARD_TYPE_REV assert card.factor elapsed = card.ivl - (card.odue - self.today) factor = ((card.factor / 1000) + 1.2) / 2 @@ -1311,7 +1311,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" "True if there are any rev cards due." return self.col.db.scalar( ( - "select 1 from cards where did in %s and queue = 2 " + f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_REV} " "and due <= ? limit 1" ) % self._deckLimit(), @@ -1438,12 +1438,12 @@ update cards set queue={QUEUE_TYPE_SIBLING_BURIED},mod=?,usn=? where id in """ for cid, queue in self.col.db.execute( f""" select id, queue from cards where nid=? and id!=? -and (queue={QUEUE_TYPE_NEW} or (queue=2 and due<=?))""", +and (queue={QUEUE_TYPE_NEW} or (queue={QUEUE_TYPE_REV} and due<=?))""", card.nid, card.id, self.today, ): - if queue == 2: + if queue == QUEUE_TYPE_REV: if buryRev: toBury.append(cid) # if bury disabled, we still discard to give same-day spacing @@ -1503,8 +1503,8 @@ and (queue={QUEUE_TYPE_NEW} or (queue=2 and due<=?))""", ) self.remFromDyn(ids) self.col.db.executemany( - """ -update cards set type=2,queue=2,ivl=:ivl,due=:due,odue=0, + f""" +update cards set type={CARD_TYPE_REV},queue={QUEUE_TYPE_REV},ivl=:ivl,due=:due,odue=0, usn=:usn,mod=:mod,factor=:fact where id=:id""", d, ) diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 613e44d1c..bec433512 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -105,7 +105,7 @@ class Scheduler: if card.queue in (QUEUE_TYPE_LRN, QUEUE_TYPE_DAY_LEARN_RELEARN): self._answerLrnCard(card, ease) - elif card.queue == 2: + elif card.queue == QUEUE_TYPE_REV: self._answerRevCard(card, ease) # update daily limit self._updateStats(card, "rev") @@ -142,9 +142,9 @@ class Scheduler: "Return counts over next DAYS. Includes today." daysd = dict( self.col.db.all( - """ + f""" select due, count() from cards -where did in %s and queue = 2 +where did in %s and queue = {QUEUE_TYPE_REV} and due between ? and ? group by due order by due""" @@ -606,7 +606,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", def _answerLrnCard(self, card: Card, ease: int) -> None: conf = self._lrnConf(card) - if card.type in (2, CARD_TYPE_RELEARNING): + if card.type in (CARD_TYPE_REV, CARD_TYPE_RELEARNING): type = REVLOG_RELRN else: type = REVLOG_LRN @@ -714,13 +714,13 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", return avg def _lrnConf(self, card: Card) -> Any: - if card.type in (2, CARD_TYPE_RELEARNING): + if card.type in (CARD_TYPE_REV, CARD_TYPE_RELEARNING): return self._lapseConf(card) else: return self._newConf(card) def _rescheduleAsRev(self, card: Card, conf: Dict[str, Any], early: bool) -> None: - lapse = card.type in (2, CARD_TYPE_RELEARNING) + lapse = card.type in (CARD_TYPE_REV, CARD_TYPE_RELEARNING) if lapse: self._rescheduleGraduatingLapse(card, early) @@ -735,8 +735,8 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", if early: card.ivl += 1 card.due = self.today + card.ivl - card.queue = 2 - card.type = 2 + card.queue = QUEUE_TYPE_REV + card.type = CARD_TYPE_REV def _startingLeft(self, card: Card) -> int: if card.type == CARD_TYPE_RELEARNING: @@ -768,7 +768,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", def _graduatingIvl( self, card: Card, conf: Dict[str, Any], early: bool, fuzz: bool = True ) -> Any: - if card.type in (2, CARD_TYPE_RELEARNING): + if card.type in (CARD_TYPE_REV, CARD_TYPE_RELEARNING): bonus = early and 1 or 0 return card.ivl + bonus if not early: @@ -786,7 +786,7 @@ did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", card.ivl = self._graduatingIvl(card, conf, early) card.due = self.today + card.ivl card.factor = conf["initialFactor"] - card.type = card.queue = 2 + card.type = card.queue = QUEUE_TYPE_REV def _logLrn( self, @@ -883,9 +883,9 @@ and due <= ? limit ?)""", dids = [did] + self.col.decks.childDids(did, childMap) lim = min(lim, self.reportLimit) return self.col.db.scalar( - """ + f""" select count() from -(select 1 from cards where did in %s and queue = 2 +(select 1 from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? limit ?)""" % ids2str(dids), self.today, @@ -895,9 +895,9 @@ and due <= ? limit ?)""" def _resetRevCount(self) -> None: lim = self._currentRevLimit() self.revCount = self.col.db.scalar( - """ + f""" select count() from (select id from cards where -did in %s and queue = 2 and due <= ? limit ?)""" +did in %s and queue = {QUEUE_TYPE_REV} and due <= ? limit ?)""" % self._deckLimit(), self.today, lim, @@ -916,9 +916,9 @@ did in %s and queue = 2 and due <= ? limit ?)""" lim = min(self.queueLimit, self._currentRevLimit()) if lim: self._revQueue = self.col.db.list( - """ + f""" select id from cards where -did in %s and queue = 2 and due <= ? +did in %s and queue = {QUEUE_TYPE_REV} and due <= ? order by due, random() limit ?""" % self._deckLimit(), @@ -946,9 +946,9 @@ limit ?""" def totalRevForCurrentDeck(self) -> int: return self.col.db.scalar( - """ + f""" select count() from cards where id in ( -select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" +select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? limit ?)""" % self._deckLimit(), self.today, self.reportLimit, @@ -1101,7 +1101,7 @@ select id from cards where did in %s and queue = 2 and due <= ? limit ?)""" # next interval for card when answered early+correctly def _earlyReviewIvl(self, card: Card, ease: int) -> int: - assert card.odid and card.type == 2 + assert card.odid and card.type == CARD_TYPE_REV assert card.factor assert ease > 1 @@ -1213,7 +1213,7 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe t = "n.id desc" elif o == DYN_DUEPRIORITY: t = ( - "(case when queue=2 and due <= %d then (ivl / cast(%d-due+0.001 as real)) else 100000+due end)" + f"(case when queue={QUEUE_TYPE_REV} and due <= %d then (ivl / cast(%d-due+0.001 as real)) else 100000+due end)" % (self.today, self.today) ) else: # DYN_DUE or unknown @@ -1231,7 +1231,7 @@ due = (case when odue>0 then odue else due end), odue = 0, odid = 0, usn = ? whe queue = "" if not deck["resched"]: - queue = ",queue=2" + queue = f",queue={QUEUE_TYPE_REV}" query = ( """ @@ -1509,7 +1509,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" "True if there are any rev cards due." return self.col.db.scalar( ( - "select 1 from cards where did in %s and queue = 2 " + f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_REV} " "and due <= ? limit 1" ) % self._deckLimit(), @@ -1700,12 +1700,12 @@ update cards set queue=?,mod=?,usn=? where id in """ for cid, queue in self.col.db.execute( f""" select id, queue from cards where nid=? and id!=? -and (queue={QUEUE_TYPE_NEW} or (queue=2 and due<=?))""", +and (queue={QUEUE_TYPE_NEW} or (queue={QUEUE_TYPE_REV} and due<=?))""", card.nid, card.id, self.today, ): - if queue == 2: + if queue == QUEUE_TYPE_REV: if buryRev: toBury.append(cid) # if bury disabled, we still discard to give same-day spacing @@ -1760,8 +1760,8 @@ and (queue={QUEUE_TYPE_NEW} or (queue=2 and due<=?))""", ) self.remFromDyn(ids) self.col.db.executemany( - """ -update cards set type=2,queue=2,ivl=:ivl,due=:due,odue=0, + f""" +update cards set type={CARD_TYPE_REV},queue={QUEUE_TYPE_REV},ivl=:ivl,due=:due,odue=0, usn=:usn,mod=:mod,factor=:fact where id=:id""", d, ) @@ -1875,10 +1875,10 @@ and due >= ? and queue = {QUEUE_TYPE_NEW}""" f""" update cards set did = odid, queue = (case when type = {CARD_TYPE_LRN} then {QUEUE_TYPE_NEW} -when type = {CARD_TYPE_RELEARNING} then 2 +when type = {CARD_TYPE_RELEARNING} then {QUEUE_TYPE_REV} else type end), type = (case when type = {CARD_TYPE_LRN} then {CARD_TYPE_NEW} -when type = {CARD_TYPE_RELEARNING} then 2 +when type = {CARD_TYPE_RELEARNING} then {CARD_TYPE_REV} else type end), due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", self.col.usn(), @@ -1890,8 +1890,8 @@ due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", self.col.db.execute( f""" update cards set - due = odue, queue = 2, type = 2, mod = %d, usn = %d, odue = 0 - where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in (2, {CARD_TYPE_RELEARNING}) + due = odue, queue = {QUEUE_TYPE_REV}, type = {CARD_TYPE_REV}, mod = %d, usn = %d, odue = 0 + where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in ({CARD_TYPE_REV}, {CARD_TYPE_RELEARNING}) """ % (intTime(), self.col.usn()) ) @@ -1899,8 +1899,8 @@ due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", self.col.db.execute( f""" update cards set - due = %d+ivl, queue = 2, type = 2, mod = %d, usn = %d, odue = 0 - where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in (2, {CARD_TYPE_RELEARNING}) + due = %d+ivl, queue = {QUEUE_TYPE_REV}, type = {CARD_TYPE_REV}, mod = %d, usn = %d, odue = 0 + where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type in ({CARD_TYPE_REV}, {CARD_TYPE_RELEARNING}) """ % (self.today, intTime(), self.col.usn()) ) @@ -1917,7 +1917,7 @@ due = odue, odue = 0, odid = 0, usn = ? where odid != 0""", f""" update cards set type = (case when type = {CARD_TYPE_LRN} then {CARD_TYPE_NEW} -when type in (2, {CARD_TYPE_RELEARNING}) then 2 +when type in ({CARD_TYPE_REV}, {CARD_TYPE_RELEARNING}) then {CARD_TYPE_REV} else type end), due = (case when odue then odue else due end), odue = 0, @@ -1936,7 +1936,7 @@ where queue < {QUEUE_TYPE_NEW}""" # adding 'hard' in v2 scheduler means old ease entries need shifting # up or down def _remapLearningAnswers(self, sql: str) -> None: - self.col.db.execute(f"update revlog set %s and type in ({CARD_TYPE_NEW},2)" % sql) + self.col.db.execute(f"update revlog set %s and type in ({CARD_TYPE_NEW},{CARD_TYPE_REV})" % sql) def moveToV1(self) -> None: self._emptyAllFiltered() diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index ed8c318eb..5fad0dd30 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -35,18 +35,18 @@ class CardStats: if first: self.addLine(_("First Review"), self.date(first / 1000)) self.addLine(_("Latest Review"), self.date(last / 1000)) - if c.type in (CARD_TYPE_LRN, 2): + if c.type in (CARD_TYPE_LRN, CARD_TYPE_REV): if c.odid or c.queue < QUEUE_TYPE_NEW: next = None else: - if c.queue in (2, 3): + if c.queue in (QUEUE_TYPE_REV, 3): next = time.time() + ((c.due - self.col.sched.today) * 86400) else: next = c.due next = self.date(next) if next: self.addLine(_("Due"), next) - if c.queue == 2: + if c.queue == QUEUE_TYPE_REV: self.addLine(_("Interval"), fmt(c.ivl * 86400)) self.addLine(_("Ease"), "%d%%" % (c.factor / 10.0)) self.addLine(_("Reviews"), "%d" % c.reps) @@ -284,8 +284,8 @@ from revlog where id > ? """ self._line(i, _("Total"), ngettext("%d review", "%d reviews", tot) % tot) self._line(i, _("Average"), self._avgDay(tot, num, _("reviews"))) tomorrow = self.col.db.scalar( - """ -select count() from cards where did in %s and queue in (2,3) + f""" +select count() from cards where did in %s and queue in ({QUEUE_TYPE_REV},3) and due = ?""" % self._limit(), self.col.sched.today + 1, @@ -301,12 +301,12 @@ and due = ?""" if end is not None: lim += " and day < %d" % end return self.col.db.all( - """ + f""" select (due-:today)/:chunk as day, sum(case when ivl < 21 then 1 else 0 end), -- yng sum(case when ivl >= 21 then 1 else 0 end) -- mtr from cards -where did in %s and queue in (2,3) +where did in %s and queue in ({QUEUE_TYPE_REV},3) %s group by day order by day""" % (self._limit(), lim), @@ -644,9 +644,9 @@ group by day order by day)""" lim = "and grp <= %d" % end if end else "" data = [ self.col.db.all( - """ + f""" select ivl / :chunk as grp, count() from cards -where did in %s and queue = 2 %s +where did in %s and queue = {QUEUE_TYPE_REV} %s group by grp order by grp""" % (self._limit(), lim), @@ -657,8 +657,8 @@ order by grp""" data + list( self.col.db.first( - """ -select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" + f""" +select count(), avg(ivl), max(ivl) from cards where did in %s and queue = {QUEUE_TYPE_REV}""" % self._limit() ) ), @@ -678,7 +678,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" for (type, ease, cnt) in eases: if type == CARD_TYPE_LRN: ease += 5 - elif type == 2: + elif type == CARD_TYPE_REV: ease += 10 n = types[type] d[n].append((ease, cnt)) @@ -930,12 +930,12 @@ when you answer "good" on a review.""" def _factors(self) -> Any: return self.col.db.first( - """ + f""" select min(factor) / 10.0, avg(factor) / 10.0, max(factor) / 10.0 -from cards where did in %s and queue = 2""" +from cards where did in %s and queue = {QUEUE_TYPE_REV}""" % self._limit() ) @@ -943,8 +943,8 @@ from cards where did in %s and queue = 2""" return self.col.db.first( f""" select -sum(case when queue=2 and ivl >= 21 then 1 else 0 end), -- mtr -sum(case when queue in ({QUEUE_TYPE_LRN},3) or (queue=2 and ivl < 21) then 1 else 0 end), -- yng/lrn +sum(case when queue={QUEUE_TYPE_REV} and ivl >= 21 then 1 else 0 end), -- mtr +sum(case when queue in ({QUEUE_TYPE_LRN},3) or (queue={QUEUE_TYPE_REV} and ivl < 21) then 1 else 0 end), -- yng/lrn sum(case when queue={QUEUE_TYPE_NEW} then 1 else 0 end), -- new sum(case when queue<{QUEUE_TYPE_NEW} then 1 else 0 end) -- susp from cards where did in %s""" diff --git a/pylib/tests/test_find.py b/pylib/tests/test_find.py index e7dc215de..98ccc20a4 100644 --- a/pylib/tests/test_find.py +++ b/pylib/tests/test_find.py @@ -1,6 +1,7 @@ # coding: utf-8 import pytest +from anki.consts import * from anki.find import Finder from tests.shared import getEmptyCol @@ -91,13 +92,13 @@ def test_findCards(): assert len(deck.findCards('"goats are"')) == 1 # card states c = f.cards()[0] - c.queue = c.type = 2 + c.queue = c.type = CARD_TYPE_REV assert deck.findCards("is:review") == [] c.flush() assert deck.findCards("is:review") == [c.id] assert deck.findCards("is:due") == [] c.due = 0 - c.queue = 2 + c.queue = QUEUE_TYPE_REV c.flush() assert deck.findCards("is:due") == [c.id] assert len(deck.findCards("-is:due")) == 4 diff --git a/pylib/tests/test_schedv1.py b/pylib/tests/test_schedv1.py index 7b75a710e..392e3ad1d 100644 --- a/pylib/tests/test_schedv1.py +++ b/pylib/tests/test_schedv1.py @@ -166,8 +166,8 @@ def test_learn(): assert c.queue == QUEUE_TYPE_LRN assert c.type == CARD_TYPE_LRN d.sched.answerCard(c, 2) - assert c.queue == 2 - assert c.type == 2 + assert c.queue == QUEUE_TYPE_REV + assert c.type == CARD_TYPE_REV # should be due tomorrow, with an interval of 1 assert c.due == d.sched.today + 1 assert c.ivl == 1 @@ -175,27 +175,27 @@ def test_learn(): c.type = 0 c.queue = 1 d.sched.answerCard(c, 3) - assert c.type == 2 - assert c.queue == 2 + assert c.type == CARD_TYPE_REV + assert c.queue == QUEUE_TYPE_REV assert checkRevIvl(d, c, 4) # revlog should have been updated each time assert d.db.scalar("select count() from revlog where type = 0") == 5 # now failed card handling - c.type = 2 + c.type = CARD_TYPE_REV c.queue = 1 c.odue = 123 d.sched.answerCard(c, 3) assert c.due == 123 - assert c.type == 2 - assert c.queue == 2 + assert c.type == CARD_TYPE_REV + assert c.queue == QUEUE_TYPE_REV # we should be able to remove manually, too - c.type = 2 + c.type = CARD_TYPE_REV c.queue = 1 c.odue = 321 c.flush() d.sched.removeLrn() c.load() - assert c.queue == 2 + assert c.queue == QUEUE_TYPE_REV assert c.due == 321 @@ -271,7 +271,7 @@ def test_learn_day(): # the last pass should graduate it into a review card assert ni(c, 2) == 86400 d.sched.answerCard(c, 2) - assert c.queue == c.type == 2 + assert c.queue == CARD_TYPE_REV and c.type == QUEUE_TYPE_REV # if the lapse step is tomorrow, failing it should handle the counts # correctly c.due = 0 @@ -294,8 +294,8 @@ def test_reviews(): d.addNote(f) # set the card up as a review card, due 8 days ago c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = d.sched.today - 8 c.factor = STARTING_FACTOR c.reps = 3 @@ -333,7 +333,7 @@ def test_reviews(): c = copy.copy(cardcopy) c.flush() d.sched.answerCard(c, 2) - assert c.queue == 2 + assert c.queue == QUEUE_TYPE_REV # the new interval should be (100 + 8/4) * 1.2 = 122 assert checkRevIvl(d, c, 122) assert c.due == d.sched.today + c.ivl @@ -388,8 +388,8 @@ def test_button_spacing(): d.addNote(f) # 1 day ivl review card due now c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = d.sched.today c.reps = 1 c.ivl = 1 @@ -412,7 +412,7 @@ def test_overdue_lapse(): d.addNote(f) # simulate a review that was lapsed and is now due for its normal review c = f.cards()[0] - c.type = 2 + c.type = CARD_TYPE_REV c.queue = 1 c.due = -1 c.odue = -1 @@ -492,7 +492,7 @@ def test_nextIvl(): assert ni(c, 3) == 4 * 86400 # lapsed cards ################################################## - c.type = 2 + c.type = CARD_TYPE_REV c.ivl = 100 c.factor = STARTING_FACTOR assert ni(c, 1) == 60 @@ -500,7 +500,7 @@ def test_nextIvl(): assert ni(c, 3) == 100 * 86400 # review cards ################################################## - c.queue = 2 + c.queue = QUEUE_TYPE_REV c.ivl = 100 c.factor = STARTING_FACTOR # failing it should put it at 60s @@ -551,20 +551,20 @@ def test_suspend(): # should cope with rev cards being relearnt c.due = 0 c.ivl = 100 - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.flush() d.reset() c = d.sched.getCard() d.sched.answerCard(c, 1) assert c.due >= time.time() assert c.queue == QUEUE_TYPE_LRN - assert c.type == 2 + assert c.type == CARD_TYPE_REV d.sched.suspendCards([c.id]) d.sched.unsuspendCards([c.id]) c.load() - assert c.queue == 2 - assert c.type == 2 + assert c.queue == QUEUE_TYPE_REV + assert c.type == CARD_TYPE_REV assert c.due == 1 # should cope with cards in cram decks c.due = 1 @@ -587,7 +587,8 @@ def test_cram(): d.addNote(f) c = f.cards()[0] c.ivl = 100 - c.type = c.queue = 2 + c.queue = CARD_TYPE_REV + c.type = QUEUE_TYPE_REV # due in 25 days, so it's been waiting 75 days c.due = d.sched.today + 25 c.mod = 1 @@ -634,7 +635,7 @@ def test_cram(): d.sched.answerCard(c, 2) assert c.ivl == 138 assert c.due == 138 - assert c.queue == 2 + assert c.queue == QUEUE_TYPE_REV # and it will have moved back to the previous deck assert c.did == 1 # cram the deck again @@ -734,7 +735,8 @@ def test_cram_resched(): assert c.type == CARD_TYPE_NEW and c.queue == QUEUE_TYPE_NEW # undue reviews should also be unaffected c.ivl = 100 - c.type = c.queue = 2 + c.queue = CARD_TYPE_REV + c.type = QUEUE_TYPE_REV c.due = d.sched.today + 25 c.factor = STARTING_FACTOR c.flush() @@ -911,8 +913,8 @@ def test_repCounts(): f["Front"] = "three" d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = d.sched.today c.flush() d.reset() @@ -929,8 +931,8 @@ def test_timing(): f["Front"] = "num" + str(i) d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = 0 c.flush() # fail the first one @@ -941,7 +943,7 @@ def test_timing(): d.sched.answerCard(c, 1) # the next card should be another review c = d.sched.getCard() - assert c.queue == 2 + assert c.queue == QUEUE_TYPE_REV # but if we wait for a second, the failed card should come back orig_time = time.time @@ -982,7 +984,7 @@ def test_deckDue(): d.addNote(f) # make it a review card c = f.cards()[0] - c.queue = 2 + c.queue = QUEUE_TYPE_REV c.due = 0 c.flush() # add one more with a new deck @@ -1100,8 +1102,8 @@ def test_forget(): f["Front"] = "one" d.addNote(f) c = f.cards()[0] - c.queue = 2 - c.type = 2 + c.queue = QUEUE_TYPE_REV + c.type = CARD_TYPE_REV c.ivl = 100 c.due = 0 c.flush() @@ -1122,7 +1124,7 @@ def test_resched(): c.load() assert c.due == d.sched.today assert c.ivl == 1 - assert c.queue == c.type == 2 + assert c.queue == CARD_TYPE_REV and c.type == QUEUE_TYPE_REV d.sched.reschedCards([c.id], 1, 1) c.load() assert c.due == d.sched.today + 1 @@ -1136,8 +1138,8 @@ def test_norelearn(): f["Front"] = "one" d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = 0 c.factor = STARTING_FACTOR c.reps = 3 @@ -1158,8 +1160,8 @@ def test_failmult(): f["Back"] = "two" d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.ivl = 100 c.due = d.sched.today - c.ivl c.factor = STARTING_FACTOR diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index db76ad460..0503b0a98 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -179,8 +179,8 @@ def test_learn(): assert c.queue == QUEUE_TYPE_LRN assert c.type == CARD_TYPE_LRN d.sched.answerCard(c, 3) - assert c.queue == 2 - assert c.type == 2 + assert c.queue == QUEUE_TYPE_REV + assert c.type == CARD_TYPE_REV # should be due tomorrow, with an interval of 1 assert c.due == d.sched.today + 1 assert c.ivl == 1 @@ -188,8 +188,8 @@ def test_learn(): c.type = 0 c.queue = 1 d.sched.answerCard(c, 4) - assert c.type == 2 - assert c.queue == 2 + assert c.type == CARD_TYPE_REV + assert c.queue == QUEUE_TYPE_REV assert checkRevIvl(d, c, 4) # revlog should have been updated each time assert d.db.scalar("select count() from revlog where type = 0") == 5 @@ -203,7 +203,8 @@ def test_relearn(): c = f.cards()[0] c.ivl = 100 c.due = d.sched.today - c.type = c.queue = 2 + c.queue = CARD_TYPE_REV + c.type = QUEUE_TYPE_REV c.flush() # fail the card @@ -216,7 +217,7 @@ def test_relearn(): # immediately graduate it d.sched.answerCard(c, 4) - assert c.queue == c.type == 2 + assert c.queue == CARD_TYPE_REV and c.type == QUEUE_TYPE_REV assert c.ivl == 2 assert c.due == d.sched.today + c.ivl @@ -229,7 +230,8 @@ def test_relearn_no_steps(): c = f.cards()[0] c.ivl = 100 c.due = d.sched.today - c.type = c.queue = 2 + c.queue = CARD_TYPE_REV + c.type = QUEUE_TYPE_REV c.flush() conf = d.decks.confForDid(1) @@ -240,7 +242,7 @@ def test_relearn_no_steps(): d.reset() c = d.sched.getCard() d.sched.answerCard(c, 1) - assert c.type == c.queue == 2 + assert c.queue == CARD_TYPE_REV and c.type == QUEUE_TYPE_REV def test_learn_collapsed(): @@ -315,7 +317,7 @@ def test_learn_day(): # the last pass should graduate it into a review card assert ni(c, 3) == 86400 d.sched.answerCard(c, 3) - assert c.queue == c.type == 2 + assert c.queue == CARD_TYPE_REV and c.type == QUEUE_TYPE_REV # if the lapse step is tomorrow, failing it should handle the counts # correctly c.due = 0 @@ -338,8 +340,8 @@ def test_reviews(): d.addNote(f) # set the card up as a review card, due 8 days ago c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = d.sched.today - 8 c.factor = STARTING_FACTOR c.reps = 3 @@ -355,7 +357,7 @@ def test_reviews(): c.flush() d.reset() d.sched.answerCard(c, 2) - assert c.queue == 2 + assert c.queue == QUEUE_TYPE_REV # the new interval should be (100) * 1.2 = 120 assert checkRevIvl(d, c, 120) assert c.due == d.sched.today + c.ivl @@ -432,7 +434,8 @@ def test_review_limits(): # make them reviews c = f.cards()[0] - c.queue = c.type = 2 + c.queue = CARD_TYPE_REV + c.type = QUEUE_TYPE_REV c.due = 0 c.flush() @@ -474,8 +477,8 @@ def test_button_spacing(): d.addNote(f) # 1 day ivl review card due now c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = d.sched.today c.reps = 1 c.ivl = 1 @@ -503,7 +506,7 @@ def test_overdue_lapse(): d.addNote(f) # simulate a review that was lapsed and is now due for its normal review c = f.cards()[0] - c.type = 2 + c.type = CARD_TYPE_REV c.queue = 1 c.due = -1 c.odue = -1 @@ -586,7 +589,7 @@ def test_nextIvl(): assert ni(c, 4) == 4 * 86400 # lapsed cards ################################################## - c.type = 2 + c.type = CARD_TYPE_REV c.ivl = 100 c.factor = STARTING_FACTOR assert ni(c, 1) == 60 @@ -594,7 +597,7 @@ def test_nextIvl(): assert ni(c, 4) == 101 * 86400 # review cards ################################################## - c.queue = 2 + c.queue = QUEUE_TYPE_REV c.ivl = 100 c.factor = STARTING_FACTOR # failing it should put it at 60s @@ -671,8 +674,8 @@ def test_suspend(): # should cope with rev cards being relearnt c.due = 0 c.ivl = 100 - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.flush() d.reset() c = d.sched.getCard() @@ -709,7 +712,8 @@ def test_filt_reviewing_early_normal(): d.addNote(f) c = f.cards()[0] c.ivl = 100 - c.type = c.queue = 2 + c.queue = CARD_TYPE_REV + c.type = QUEUE_TYPE_REV # due in 25 days, so it's been waiting 75 days c.due = d.sched.today + 25 c.mod = 1 @@ -740,7 +744,7 @@ def test_filt_reviewing_early_normal(): assert c.due == d.sched.today + c.ivl assert not c.odue # should not be in learning - assert c.queue == 2 + assert c.queue == QUEUE_TYPE_REV # should be logged as a cram rep assert d.db.scalar("select type from revlog order by id desc limit 1") == 3 @@ -943,8 +947,8 @@ def test_repCounts(): f["Front"] = "three" d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = d.sched.today c.flush() d.reset() @@ -961,8 +965,8 @@ def test_timing(): f["Front"] = "num" + str(i) d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = 0 c.flush() # fail the first one @@ -971,7 +975,7 @@ def test_timing(): d.sched.answerCard(c, 1) # the next card should be another review c2 = d.sched.getCard() - assert c2.queue == 2 + assert c2.queue == QUEUE_TYPE_REV # if the failed card becomes due, it should show first c.due = time.time() - 1 c.flush() @@ -1008,7 +1012,7 @@ def test_deckDue(): d.addNote(f) # make it a review card c = f.cards()[0] - c.queue = 2 + c.queue = QUEUE_TYPE_REV c.due = 0 c.flush() # add one more with a new deck @@ -1126,8 +1130,8 @@ def test_forget(): f["Front"] = "one" d.addNote(f) c = f.cards()[0] - c.queue = 2 - c.type = 2 + c.queue = QUEUE_TYPE_REV + c.type = CARD_TYPE_REV c.ivl = 100 c.due = 0 c.flush() @@ -1148,7 +1152,7 @@ def test_resched(): c.load() assert c.due == d.sched.today assert c.ivl == 1 - assert c.queue == c.type == 2 + assert c.queue == QUEUE_TYPE_REV and c.type == CARD_TYPE_REV d.sched.reschedCards([c.id], 1, 1) c.load() assert c.due == d.sched.today + 1 @@ -1162,8 +1166,8 @@ def test_norelearn(): f["Front"] = "one" d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.due = 0 c.factor = STARTING_FACTOR c.reps = 3 @@ -1184,8 +1188,8 @@ def test_failmult(): f["Back"] = "two" d.addNote(f) c = f.cards()[0] - c.type = 2 - c.queue = 2 + c.type = CARD_TYPE_REV + c.queue = QUEUE_TYPE_REV c.ivl = 100 c.due = d.sched.today - c.ivl c.factor = STARTING_FACTOR @@ -1269,7 +1273,7 @@ def test_negativeDueFilter(): d.addNote(f) c = f.cards()[0] c.due = -5 - c.queue = 2 + c.queue = QUEUE_TYPE_REV c.ivl = 5 c.flush() diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index 57af170eb..5ebd10bcf 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -337,7 +337,7 @@ class DataModel(QAbstractTableModel): date = c.due elif c.queue == QUEUE_TYPE_NEW or c.type == CARD_TYPE_NEW: return str(c.due) - elif c.queue in (2, 3) or (c.type == 2 and c.queue < 0): + elif c.queue in (QUEUE_TYPE_REV, 3) or (c.type == CARD_TYPE_REV and c.queue < 0): date = time.time() + ((c.due - self.col.sched.today) * 86400) else: return "" From 7b7b71c0e1a0d3b646b92b5da15c6a7b0c29ea93 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 20:11:03 -0800 Subject: [PATCH 36/38] QUEUE_TYPE_PREVIEW --- pylib/anki/consts.py | 1 + pylib/anki/schedv2.py | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index f49bcbf99..d0eba1499 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -21,6 +21,7 @@ QUEUE_TYPE_SUSPENDED = -1 QUEUE_TYPE_NEW = 0 QUEUE_TYPE_LRN = 1 QUEUE_TYPE_REV = 2 +QUEUE_TYPE_PREVIEW = 4 # Card types CARD_TYPE_NEW = 0 diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index bec433512..725259bab 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -25,7 +25,6 @@ from anki.utils import fmtTimeSpan, ids2str, intTime CARD_TYPE_RELEARNING = 3 # queue types: 0=new, 1=(re)lrn, 2=rev, 3=day (re)lrn, # 4=preview, -1=suspended, -2=sibling buried, -3=manually buried -QUEUE_TYPE_PREVIEW = 4 QUEUE_TYPE_DAY_LEARN_RELEARN = 3 # revlog types: 0=lrn, 1=rev, 2=relrn, 3=early review From 957f0c8e8b76cb413fb9fdeca4a76c7038008185 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Thu, 30 Jan 2020 20:38:39 -0800 Subject: [PATCH 37/38] QUEUE and TYPE day learn, relearn --- pylib/anki/consts.py | 2 ++ pylib/anki/find.py | 6 +++--- pylib/anki/importing/anki2.py | 2 +- pylib/anki/sched.py | 26 +++++++++++++------------- pylib/anki/schedv2.py | 2 -- pylib/anki/stats.py | 8 ++++---- pylib/tests/test_schedv1.py | 4 ++-- pylib/tests/test_schedv2.py | 10 +++++----- qt/aqt/browser.py | 2 +- 9 files changed, 31 insertions(+), 31 deletions(-) diff --git a/pylib/anki/consts.py b/pylib/anki/consts.py index d0eba1499..1d2b35910 100644 --- a/pylib/anki/consts.py +++ b/pylib/anki/consts.py @@ -21,12 +21,14 @@ QUEUE_TYPE_SUSPENDED = -1 QUEUE_TYPE_NEW = 0 QUEUE_TYPE_LRN = 1 QUEUE_TYPE_REV = 2 +QUEUE_TYPE_DAY_LEARN_RELEARN = 3 QUEUE_TYPE_PREVIEW = 4 # Card types CARD_TYPE_NEW = 0 CARD_TYPE_LRN = 1 CARD_TYPE_REV = 2 +CARD_TYPE_RELEARNING = 3 # removal types REM_CARD = 0 diff --git a/pylib/anki/find.py b/pylib/anki/find.py index 026307c70..847d4e05f 100644 --- a/pylib/anki/find.py +++ b/pylib/anki/find.py @@ -273,7 +273,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ elif val == "new": n = CARD_TYPE_NEW else: - return f"queue in ({QUEUE_TYPE_LRN}, 3)" + return f"queue in ({QUEUE_TYPE_LRN}, {QUEUE_TYPE_DAY_LEARN_RELEARN})" return "type = %d" % n elif val == "suspended": return "c.queue = -1" @@ -281,7 +281,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ return f"c.queue in ({QUEUE_TYPE_SIBLING_BURIED}, {QUEUE_TYPE_MANUALLY_BURIED})" elif val == "due": return f""" -(c.queue in ({QUEUE_TYPE_REV},3) and c.due <= %d) or +(c.queue in ({QUEUE_TYPE_REV},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and c.due <= %d) or (c.queue = {QUEUE_TYPE_LRN} and c.due <= %d)""" % ( self.col.sched.today, self.col.sched.dayCutoff, @@ -349,7 +349,7 @@ select distinct(n.id) from cards c, notes n where c.nid=n.id and """ if prop == "due": val += self.col.sched.today # only valid for review/daily learning - q.append(f"(c.queue in ({QUEUE_TYPE_REV},3))") + q.append(f"(c.queue in ({QUEUE_TYPE_REV},{QUEUE_TYPE_DAY_LEARN_RELEARN}))") elif prop == "ease": prop = "factor" val = int(val * 1000) diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index e7f952614..77818e426 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -344,7 +344,7 @@ class Anki2Importer(Importer): card[4] = intTime() card[5] = usn # review cards have a due date relative to collection - if card[7] in (QUEUE_TYPE_REV, 3) or card[6] == CARD_TYPE_REV: + if card[7] in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN) or card[6] == CARD_TYPE_REV: card[8] -= aheadBy # odue needs updating too if card[14]: diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index f30dedbe6..0542d303d 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -84,7 +84,7 @@ class Scheduler: card.ivl = self._dynIvlBoost(card) card.odue = self.today + card.ivl self._updateStats(card, "new") - if card.queue in (QUEUE_TYPE_LRN, 3): + if card.queue in (QUEUE_TYPE_LRN, QUEUE_TYPE_DAY_LEARN_RELEARN): self._answerLrnCard(card, ease) if not wasNewQ: self._updateStats(card, "lrn") @@ -132,7 +132,7 @@ order by due""" return ret def countIdx(self, card): - if card.queue == 3: + if card.queue == QUEUE_TYPE_DAY_LEARN_RELEARN: return 1 return card.queue @@ -476,8 +476,8 @@ did in %s and queue = {QUEUE_TYPE_LRN} and due < ? limit %d)""" ) # day self.lrnCount += self.col.db.scalar( - """ -select count() from cards where did in %s and queue = 3 + f""" +select count() from cards where did in %s and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit %d""" % (self._deckLimit(), self.reportLimit), self.today, @@ -528,9 +528,9 @@ limit %d""" did = self._lrnDids[0] # fill the queue with the current did self._lrnDayQueue = self.col.db.list( - """ + f""" select id from cards where -did = ? and queue = 3 and due <= ? limit ?""", +did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?""", did, self.today, self.queueLimit, @@ -611,7 +611,7 @@ did = ? and queue = 3 and due <= ? limit ?""", # day learn queue ahead = ((card.due - self.dayCutoff) // 86400) + 1 card.due = self.today + ahead - card.queue = 3 + card.queue = QUEUE_TYPE_DAY_LEARN_RELEARN self._logLrn(card, ease, conf, leaving, type, lastLeft) def _delayForGrade(self, conf, left): @@ -739,14 +739,14 @@ did = ? and queue = 3 and due <= ? limit ?""", f""" update cards set due = odue, queue = {QUEUE_TYPE_REV}, mod = %d, usn = %d, odue = 0 -where queue in ({QUEUE_TYPE_LRN},3) and type = {CARD_TYPE_REV} +where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type = {CARD_TYPE_REV} %s """ % (intTime(), self.col.usn(), extra) ) # new cards in learning self.forgetCards( - self.col.db.list(f"select id from cards where queue in ({QUEUE_TYPE_LRN},3) %s" % extra) + self.col.db.list(f"select id from cards where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) %s" % extra) ) def _lrnForDeck(self, did): @@ -762,9 +762,9 @@ select sum(left/1000) from or 0 ) return cnt + self.col.db.scalar( - """ + f""" select count() from -(select 1 from cards where did = ? and queue = 3 +(select 1 from cards where did = ? and queue = {QUEUE_TYPE_DAY_LEARN_RELEARN} and due <= ? limit ?)""", did, self.today, @@ -913,7 +913,7 @@ select id from cards where did in %s and queue = {QUEUE_TYPE_REV} and due <= ? l # day learn queue ahead = ((card.due - self.dayCutoff) // 86400) + 1 card.due = self.today + ahead - card.queue = 3 + card.queue = QUEUE_TYPE_DAY_LEARN_RELEARN return delay def _nextLapseIvl(self, card, conf): @@ -1347,7 +1347,7 @@ To study outside of the normal schedule, click the Custom Study button below.""" def nextIvl(self, card, ease): "Return the next interval for CARD, in seconds." - if card.queue in (QUEUE_TYPE_NEW, QUEUE_TYPE_LRN, 3): + if card.queue in (QUEUE_TYPE_NEW, QUEUE_TYPE_LRN, QUEUE_TYPE_DAY_LEARN_RELEARN): return self._nextLrnIvl(card, ease) elif ease == BUTTON_ONE: # lapsed diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 725259bab..498644d20 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -22,10 +22,8 @@ from anki.rsbackend import SchedTimingToday from anki.utils import fmtTimeSpan, ids2str, intTime # card types: 0=new, 1=lrn, 2=rev, 3=relrn -CARD_TYPE_RELEARNING = 3 # queue types: 0=new, 1=(re)lrn, 2=rev, 3=day (re)lrn, # 4=preview, -1=suspended, -2=sibling buried, -3=manually buried -QUEUE_TYPE_DAY_LEARN_RELEARN = 3 # revlog types: 0=lrn, 1=rev, 2=relrn, 3=early review # positive revlog intervals are in days (rev), negative in seconds (lrn) diff --git a/pylib/anki/stats.py b/pylib/anki/stats.py index 5fad0dd30..e1cc18922 100644 --- a/pylib/anki/stats.py +++ b/pylib/anki/stats.py @@ -39,7 +39,7 @@ class CardStats: if c.odid or c.queue < QUEUE_TYPE_NEW: next = None else: - if c.queue in (QUEUE_TYPE_REV, 3): + if c.queue in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN): next = time.time() + ((c.due - self.col.sched.today) * 86400) else: next = c.due @@ -285,7 +285,7 @@ from revlog where id > ? """ self._line(i, _("Average"), self._avgDay(tot, num, _("reviews"))) tomorrow = self.col.db.scalar( f""" -select count() from cards where did in %s and queue in ({QUEUE_TYPE_REV},3) +select count() from cards where did in %s and queue in ({QUEUE_TYPE_REV},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and due = ?""" % self._limit(), self.col.sched.today + 1, @@ -306,7 +306,7 @@ select (due-:today)/:chunk as day, sum(case when ivl < 21 then 1 else 0 end), -- yng sum(case when ivl >= 21 then 1 else 0 end) -- mtr from cards -where did in %s and queue in ({QUEUE_TYPE_REV},3) +where did in %s and queue in ({QUEUE_TYPE_REV},{QUEUE_TYPE_DAY_LEARN_RELEARN}) %s group by day order by day""" % (self._limit(), lim), @@ -944,7 +944,7 @@ from cards where did in %s and queue = {QUEUE_TYPE_REV}""" f""" select sum(case when queue={QUEUE_TYPE_REV} and ivl >= 21 then 1 else 0 end), -- mtr -sum(case when queue in ({QUEUE_TYPE_LRN},3) or (queue={QUEUE_TYPE_REV} and ivl < 21) then 1 else 0 end), -- yng/lrn +sum(case when queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) or (queue={QUEUE_TYPE_REV} and ivl < 21) then 1 else 0 end), -- yng/lrn sum(case when queue={QUEUE_TYPE_NEW} then 1 else 0 end), -- new sum(case when queue<{QUEUE_TYPE_NEW} then 1 else 0 end) -- susp from cards where did in %s""" diff --git a/pylib/tests/test_schedv1.py b/pylib/tests/test_schedv1.py index 392e3ad1d..5613badf2 100644 --- a/pylib/tests/test_schedv1.py +++ b/pylib/tests/test_schedv1.py @@ -247,7 +247,7 @@ def test_learn_day(): # answering it will place it in queue 3 d.sched.answerCard(c, 2) assert c.due == d.sched.today + 1 - assert c.queue == 3 + assert c.queue == CARD_TYPE_RELEARNING assert not d.sched.getCard() # for testing, move it back a day c.due -= 1 @@ -281,7 +281,7 @@ def test_learn_day(): d.sched._cardConf(c)["lapse"]["delays"] = [1440] c = d.sched.getCard() d.sched.answerCard(c, 1) - assert c.queue == 3 + assert c.queue == CARD_TYPE_RELEARNING assert d.sched.counts() == (0, 0, 0) diff --git a/pylib/tests/test_schedv2.py b/pylib/tests/test_schedv2.py index 0503b0a98..cbee96c2a 100644 --- a/pylib/tests/test_schedv2.py +++ b/pylib/tests/test_schedv2.py @@ -212,7 +212,7 @@ def test_relearn(): c = d.sched.getCard() d.sched.answerCard(c, 1) assert c.queue == QUEUE_TYPE_LRN - assert c.type == 3 + assert c.type == CARD_TYPE_RELEARNING assert c.ivl == 1 # immediately graduate it @@ -293,7 +293,7 @@ def test_learn_day(): # answering it will place it in queue 3 d.sched.answerCard(c, 3) assert c.due == d.sched.today + 1 - assert c.queue == 3 + assert c.queue == QUEUE_TYPE_DAY_LEARN_RELEARN assert not d.sched.getCard() # for testing, move it back a day c.due -= 1 @@ -327,7 +327,7 @@ def test_learn_day(): d.sched._cardConf(c)["lapse"]["delays"] = [1440] c = d.sched.getCard() d.sched.answerCard(c, 1) - assert c.queue == 3 + assert c.queue == QUEUE_TYPE_DAY_LEARN_RELEARN assert d.sched.counts() == (0, 0, 0) @@ -683,12 +683,12 @@ def test_suspend(): assert c.due >= time.time() due = c.due assert c.queue == QUEUE_TYPE_LRN - assert c.type == 3 + assert c.type == CARD_TYPE_RELEARNING d.sched.suspendCards([c.id]) d.sched.unsuspendCards([c.id]) c.load() assert c.queue == QUEUE_TYPE_LRN - assert c.type == 3 + assert c.type == CARD_TYPE_RELEARNING assert c.due == due # should cope with cards in cram decks c.due = 1 diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index 5ebd10bcf..d2e1bc951 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -337,7 +337,7 @@ class DataModel(QAbstractTableModel): date = c.due elif c.queue == QUEUE_TYPE_NEW or c.type == CARD_TYPE_NEW: return str(c.due) - elif c.queue in (QUEUE_TYPE_REV, 3) or (c.type == CARD_TYPE_REV and c.queue < 0): + elif c.queue in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN) or (c.type == CARD_TYPE_REV and c.queue < 0): date = time.time() + ((c.due - self.col.sched.today) * 86400) else: return "" From 35c8f21eb6dfb1b9774264c856efe0defc02ab28 Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Fri, 31 Jan 2020 00:58:03 -0800 Subject: [PATCH 38/38] Reformatting through black --- pylib/anki/cards.py | 12 +++++++++-- pylib/anki/importing/anki2.py | 5 ++++- pylib/anki/sched.py | 40 ++++++++++++++++++++++++++--------- pylib/anki/schedv2.py | 24 +++++++++++++++------ qt/aqt/browser.py | 7 ++++-- 5 files changed, 67 insertions(+), 21 deletions(-) diff --git a/pylib/anki/cards.py b/pylib/anki/cards.py index 145d2b275..2de6960e5 100644 --- a/pylib/anki/cards.py +++ b/pylib/anki/cards.py @@ -88,7 +88,11 @@ class Card: self.mod = intTime() self.usn = self.col.usn() # bug check - if self.queue == QUEUE_TYPE_REV and self.odue and not self.col.decks.isDyn(self.did): + if ( + self.queue == QUEUE_TYPE_REV + and self.odue + and not self.col.decks.isDyn(self.did) + ): hooks.card_odue_was_invalid() assert self.due < 4294967296 self.col.db.execute( @@ -120,7 +124,11 @@ insert or replace into cards values self.mod = intTime() self.usn = self.col.usn() # bug checks - if self.queue == QUEUE_TYPE_REV and self.odue and not self.col.decks.isDyn(self.did): + if ( + self.queue == QUEUE_TYPE_REV + and self.odue + and not self.col.decks.isDyn(self.did) + ): hooks.card_odue_was_invalid() assert self.due < 4294967296 self.col.db.execute( diff --git a/pylib/anki/importing/anki2.py b/pylib/anki/importing/anki2.py index 77818e426..50ba9cfab 100644 --- a/pylib/anki/importing/anki2.py +++ b/pylib/anki/importing/anki2.py @@ -344,7 +344,10 @@ class Anki2Importer(Importer): card[4] = intTime() card[5] = usn # review cards have a due date relative to collection - if card[7] in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN) or card[6] == CARD_TYPE_REV: + if ( + card[7] in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN) + or card[6] == CARD_TYPE_REV + ): card[8] -= aheadBy # odue needs updating too if card[14]: diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 0542d303d..3bc82972b 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -153,14 +153,21 @@ order by due""" def unburyCards(self): "Unbury cards." self.col.conf["lastUnburied"] = self.today - self.col.log(self.col.db.list(f"select id from cards where queue = {QUEUE_TYPE_SIBLING_BURIED}")) - self.col.db.execute(f"update cards set queue=type where queue = {QUEUE_TYPE_SIBLING_BURIED}") + self.col.log( + self.col.db.list( + f"select id from cards where queue = {QUEUE_TYPE_SIBLING_BURIED}" + ) + ) + self.col.db.execute( + f"update cards set queue=type where queue = {QUEUE_TYPE_SIBLING_BURIED}" + ) def unburyCardsForDeck(self): sids = ids2str(self.col.decks.active()) self.col.log( self.col.db.list( - f"select id from cards where queue = {QUEUE_TYPE_SIBLING_BURIED} and did in %s" % sids + f"select id from cards where queue = {QUEUE_TYPE_SIBLING_BURIED} and did in %s" + % sids ) ) self.col.db.execute( @@ -746,7 +753,10 @@ where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) and type = {CAR ) # new cards in learning self.forgetCards( - self.col.db.list(f"select id from cards where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) %s" % extra) + self.col.db.list( + f"select id from cards where queue in ({QUEUE_TYPE_LRN},{QUEUE_TYPE_DAY_LEARN_RELEARN}) %s" + % extra + ) ) def _lrnForDeck(self, did): @@ -1321,14 +1331,18 @@ To study outside of the normal schedule, click the Custom Study button below.""" def newDue(self): "True if there are any new cards due." return self.col.db.scalar( - (f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_NEW} " "limit 1") + ( + f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_NEW} " + "limit 1" + ) % self._deckLimit() ) def haveBuried(self): sdids = ids2str(self.col.decks.active()) cnt = self.col.db.scalar( - f"select 1 from cards where queue = {QUEUE_TYPE_SIBLING_BURIED} and did in %s limit 1" % sdids + f"select 1 from cards where queue = {QUEUE_TYPE_SIBLING_BURIED} and did in %s limit 1" + % sdids ) return not not cnt @@ -1391,7 +1405,8 @@ To study outside of the normal schedule, click the Custom Study button below.""" self.remFromDyn(ids) self.removeLrn(ids) self.col.db.execute( - f"update cards set queue={QUEUE_TYPE_SUSPENDED},mod=?,usn=? where id in " + ids2str(ids), + f"update cards set queue={QUEUE_TYPE_SUSPENDED},mod=?,usn=? where id in " + + ids2str(ids), intTime(), self.col.usn(), ) @@ -1462,7 +1477,8 @@ and (queue={QUEUE_TYPE_NEW} or (queue={QUEUE_TYPE_REV} and due<=?))""", # then bury if toBury: self.col.db.execute( - f"update cards set queue={QUEUE_TYPE_SIBLING_BURIED},mod=?,usn=? where id in " + ids2str(toBury), + f"update cards set queue={QUEUE_TYPE_SIBLING_BURIED},mod=?,usn=? where id in " + + ids2str(toBury), intTime(), self.col.usn(), ) @@ -1479,7 +1495,10 @@ and (queue={QUEUE_TYPE_NEW} or (queue={QUEUE_TYPE_REV} and due<=?))""", " where id in " + ids2str(ids), STARTING_FACTOR, ) - pmax = self.col.db.scalar(f"select max(due) from cards where type={CARD_TYPE_NEW}") or 0 + pmax = ( + self.col.db.scalar(f"select max(due) from cards where type={CARD_TYPE_NEW}") + or 0 + ) # takes care of mod + usn self.sortCards(ids, start=pmax + 1) self.col.log(ids) @@ -1515,7 +1534,8 @@ usn=:usn,mod=:mod,factor=:fact where id=:id""", sids = ids2str(ids) # we want to avoid resetting due number of existing new cards on export nonNew = self.col.db.list( - f"select id from cards where id in %s and (queue != {QUEUE_TYPE_NEW} or type != {CARD_TYPE_NEW})" % sids + f"select id from cards where id in %s and (queue != {QUEUE_TYPE_NEW} or type != {CARD_TYPE_NEW})" + % sids ) # reset all cards self.col.db.execute( diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 498644d20..3a3e88846 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -1516,7 +1516,10 @@ To study outside of the normal schedule, click the Custom Study button below.""" def newDue(self) -> Any: "True if there are any new cards due." return self.col.db.scalar( - (f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_NEW} " "limit 1") + ( + f"select 1 from cards where did in %s and queue = {QUEUE_TYPE_NEW} " + "limit 1" + ) % self._deckLimit() ) @@ -1613,7 +1616,8 @@ end) "Suspend cards." self.col.log(ids) self.col.db.execute( - f"update cards set queue={QUEUE_TYPE_SUSPENDED},mod=?,usn=? where id in " + ids2str(ids), + f"update cards set queue={QUEUE_TYPE_SUSPENDED},mod=?,usn=? where id in " + + ids2str(ids), intTime(), self.col.usn(), ) @@ -1622,7 +1626,9 @@ end) "Unsuspend cards." self.col.log(ids) self.col.db.execute( - (f"update cards set %s,mod=?,usn=? where queue = {QUEUE_TYPE_SUSPENDED} and id in %s") + ( + f"update cards set %s,mod=?,usn=? where queue = {QUEUE_TYPE_SUSPENDED} and id in %s" + ) % (self._restoreQueueSnippet, ids2str(ids)), intTime(), self.col.usn(), @@ -1733,7 +1739,10 @@ and (queue={QUEUE_TYPE_NEW} or (queue={QUEUE_TYPE_REV} and due<=?))""", " where id in " + ids2str(ids), STARTING_FACTOR, ) - pmax = self.col.db.scalar(f"select max(due) from cards where type={CARD_TYPE_NEW}") or 0 + pmax = ( + self.col.db.scalar(f"select max(due) from cards where type={CARD_TYPE_NEW}") + or 0 + ) # takes care of mod + usn self.sortCards(ids, start=pmax + 1) self.col.log(ids) @@ -1769,7 +1778,8 @@ usn=:usn,mod=:mod,factor=:fact where id=:id""", sids = ids2str(ids) # we want to avoid resetting due number of existing new cards on export nonNew = self.col.db.list( - f"select id from cards where id in %s and (queue != {QUEUE_TYPE_NEW} or type != {CARD_TYPE_NEW})" % sids + f"select id from cards where id in %s and (queue != {QUEUE_TYPE_NEW} or type != {CARD_TYPE_NEW})" + % sids ) # reset all cards self.col.db.execute( @@ -1933,7 +1943,9 @@ where queue < {QUEUE_TYPE_NEW}""" # adding 'hard' in v2 scheduler means old ease entries need shifting # up or down def _remapLearningAnswers(self, sql: str) -> None: - self.col.db.execute(f"update revlog set %s and type in ({CARD_TYPE_NEW},{CARD_TYPE_REV})" % sql) + self.col.db.execute( + f"update revlog set %s and type in ({CARD_TYPE_NEW},{CARD_TYPE_REV})" % sql + ) def moveToV1(self) -> None: self._emptyAllFiltered() diff --git a/qt/aqt/browser.py b/qt/aqt/browser.py index d2e1bc951..a586bca9b 100644 --- a/qt/aqt/browser.py +++ b/qt/aqt/browser.py @@ -337,7 +337,9 @@ class DataModel(QAbstractTableModel): date = c.due elif c.queue == QUEUE_TYPE_NEW or c.type == CARD_TYPE_NEW: return str(c.due) - elif c.queue in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN) or (c.type == CARD_TYPE_REV and c.queue < 0): + elif c.queue in (QUEUE_TYPE_REV, QUEUE_TYPE_DAY_LEARN_RELEARN) or ( + c.type == CARD_TYPE_REV and c.queue < 0 + ): date = time.time() + ((c.due - self.col.sched.today) * 86400) else: return "" @@ -1936,7 +1938,8 @@ update cards set usn=?, mod=?, did=? where id in """ def _reposition(self): cids = self.selectedCards() cids2 = self.col.db.list( - f"select id from cards where type = {CARD_TYPE_NEW} and id in " + ids2str(cids) + f"select id from cards where type = {CARD_TYPE_NEW} and id in " + + ids2str(cids) ) if not cids2: return showInfo(_("Only new cards can be repositioned."))