From c4b2ab96a6fcf4d954e2004c04834a2abc3764eb Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 1 Mar 2020 13:38:42 +0100 Subject: [PATCH 1/2] single return in sched2 _deckRevLimitSingle --- pylib/anki/schedv2.py | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 9c00e46ca..019bd1074 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -867,14 +867,12 @@ and due <= ? limit ?)""", lim = max(0, c["rev"]["perDay"] - d["revToday"][1]) if parentLimit is not None: - return min(parentLimit, lim) - elif "::" not in d["name"]: - return lim - else: + lim = min(parentLimit, lim) + elif "::" in d["name"]: for parent in self.col.decks.parents(d["id"]): # pass in dummy parentLimit so we don't do parent lookup again lim = min(lim, self._deckRevLimitSingle(parent, parentLimit=lim)) - return lim + return lim def _revForDeck(self, did: int, lim: int, childMap: Dict[int, Any]) -> Any: dids = [did] + self.col.decks.childDids(did, childMap) From 0c9de3b19c5bba63e4005e3d76222eb3b06eb9ca Mon Sep 17 00:00:00 2001 From: Arthur Milchior Date: Sun, 1 Mar 2020 13:52:32 +0100 Subject: [PATCH 2/2] hooks for limit new/rev for a single deck --- pylib/anki/hooks.py | 56 +++++++++++++++++++++++++++++++++++++++++ pylib/anki/sched.py | 3 ++- pylib/anki/schedv2.py | 5 ++-- pylib/tools/genhooks.py | 14 +++++++++++ 4 files changed, 75 insertions(+), 3 deletions(-) diff --git a/pylib/anki/hooks.py b/pylib/anki/hooks.py index 2d91ac74d..912d42fb3 100644 --- a/pylib/anki/hooks.py +++ b/pylib/anki/hooks.py @@ -387,6 +387,62 @@ class _NotesWillBeDeletedHook: notes_will_be_deleted = _NotesWillBeDeletedHook() +class _SchedulerNewLimitForSingleDeckFilter: + """Allows changing the number of new card for this deck (without + considering descendants).""" + + _hooks: List[Callable[[int, Dict[str, Any]], int]] = [] + + def append(self, cb: Callable[[int, Dict[str, Any]], int]) -> None: + """(count: int, deck: Dict[str, Any])""" + self._hooks.append(cb) + + def remove(self, cb: Callable[[int, Dict[str, Any]], int]) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__(self, count: int, deck: Dict[str, Any]) -> int: + for filter in self._hooks: + try: + count = filter(count, deck) + except: + # if the hook fails, remove it + self._hooks.remove(filter) + raise + return count + + +scheduler_new_limit_for_single_deck = _SchedulerNewLimitForSingleDeckFilter() + + +class _SchedulerReviewLimitForSingleDeckFilter: + """Allows changing the number of rev card for this deck (without + considering descendants).""" + + _hooks: List[Callable[[int, Dict[str, Any]], int]] = [] + + def append(self, cb: Callable[[int, Dict[str, Any]], int]) -> None: + """(count: int, deck: Dict[str, Any])""" + self._hooks.append(cb) + + def remove(self, cb: Callable[[int, Dict[str, Any]], int]) -> None: + if cb in self._hooks: + self._hooks.remove(cb) + + def __call__(self, count: int, deck: Dict[str, Any]) -> int: + for filter in self._hooks: + try: + count = filter(count, deck) + except: + # if the hook fails, remove it + self._hooks.remove(filter) + raise + return count + + +scheduler_review_limit_for_single_deck = _SchedulerReviewLimitForSingleDeckFilter() + + class _Schedv2DidAnswerReviewCardHook: _hooks: List[Callable[["anki.cards.Card", int, bool], None]] = [] diff --git a/pylib/anki/sched.py b/pylib/anki/sched.py index 0c7862782..258c48994 100644 --- a/pylib/anki/sched.py +++ b/pylib/anki/sched.py @@ -525,7 +525,8 @@ and due <= ? limit ?)""", if d["dyn"]: return self.reportLimit c = self.col.decks.confForDid(d["id"]) - return max(0, c["rev"]["perDay"] - d["revToday"][1]) + limit = max(0, c["rev"]["perDay"] - d["revToday"][1]) + return hooks.scheduler_review_limit_for_single_deck(limit, d) def _revForDeck(self, did: int, lim: int) -> int: # type: ignore[override] lim = min(lim, self.reportLimit) diff --git a/pylib/anki/schedv2.py b/pylib/anki/schedv2.py index 019bd1074..6a7a3c4cb 100644 --- a/pylib/anki/schedv2.py +++ b/pylib/anki/schedv2.py @@ -474,7 +474,8 @@ select count() from if g["dyn"]: return self.dynReportLimit c = self.col.decks.confForDid(g["id"]) - return max(0, c["new"]["perDay"] - g["newToday"][1]) + limit = max(0, c["new"]["perDay"] - g["newToday"][1]) + return hooks.scheduler_new_limit_for_single_deck(limit, g) def totalNewForCurrentDeck(self) -> int: return self.col.db.scalar( @@ -872,7 +873,7 @@ and due <= ? limit ?)""", for parent in self.col.decks.parents(d["id"]): # pass in dummy parentLimit so we don't do parent lookup again lim = min(lim, self._deckRevLimitSingle(parent, parentLimit=lim)) - return lim + return hooks.scheduler_review_limit_for_single_deck(lim, d) def _revForDeck(self, did: int, lim: int, childMap: Dict[int, Any]) -> Any: dids = [did] + self.col.decks.childDids(did, childMap) diff --git a/pylib/tools/genhooks.py b/pylib/tools/genhooks.py index 6cbe922dd..465a064cc 100644 --- a/pylib/tools/genhooks.py +++ b/pylib/tools/genhooks.py @@ -95,6 +95,20 @@ hooks = [ name="schedv2_did_answer_review_card", args=["card: anki.cards.Card", "ease: int", "early: bool"], ), + Hook( + name="scheduler_new_limit_for_single_deck", + args=["count: int", "deck: Dict[str, Any]"], + return_type="int", + doc="""Allows changing the number of new card for this deck (without + considering descendants).""", + ), + Hook( + name="scheduler_review_limit_for_single_deck", + args=["count: int", "deck: Dict[str, Any]"], + return_type="int", + doc="""Allows changing the number of rev card for this deck (without + considering descendants).""", + ), ] if __name__ == "__main__":