Last active
January 19, 2019 04:04
-
-
Save z1lc/e9ef656af95aa88af75af4b1d9841a0f to your computer and use it in GitHub Desktop.
Anki Add-on: Set the number of new cards due in a specified deck based on how much time total you want to spend in review
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import math | |
from aqt import mw | |
from aqt.qt import * | |
DECK_EXACT_NAME = "z" | |
TOTAL_MINUTES = 50 | |
# TODO: I can get this stuff from existing information in DB | |
CARDS_PER_MINUTE = 11.5 | |
REPS_PER_NEW_CARD = 2.5 | |
RETENTION = 0.85 | |
def get_new_card_setting(): | |
due_card_ids = mw.col.findCards('deck:{} -deck:{}::* is:due -is:suspended'.format(DECK_EXACT_NAME, DECK_EXACT_NAME)) | |
total_reps_you_can_do = TOTAL_MINUTES * CARDS_PER_MINUTE | |
estimated_reps_for_review = int(len(due_card_ids) / RETENTION) | |
reps_still_available = total_reps_you_can_do - estimated_reps_for_review | |
new_card_setting = 0 | |
if reps_still_available > 0: | |
new_card_setting = int(reps_still_available / REPS_PER_NEW_CARD) | |
return new_card_setting | |
def set_new_cards_in_deck(deck, new_card_setting): | |
deck_configuration = mw.col.decks.confForDid(deck['id']) | |
deck_configuration['new']['perDay'] = new_card_setting | |
# if we don't save both the deck and deck config, | |
# there will be a mismatch between the two and anki will force a full sync | |
mw.col.decks.save(deck) | |
mw.col.decks.save(deck_configuration) | |
def set_autoadd_deck_totals(total_new_setting): | |
autoadd_decks = [deck for deck in mw.col.decks.all() if '[autoadd]' in deck['name']] | |
autoadd_per_deck = 0 | |
new_actually_available = len(mw.col.findNotes('deck:{} -deck:{}::* is:new -is:suspended' | |
.format(DECK_EXACT_NAME, DECK_EXACT_NAME))) | |
if total_new_setting > new_actually_available: | |
autoadd_total = total_new_setting - new_actually_available | |
non_empty_autoadd_deck_count = sum('EMPTY' not in s['name'] for s in autoadd_decks) | |
autoadd_per_deck = math.ceil(autoadd_total / non_empty_autoadd_deck_count) | |
# since all autoadd decks share the same options group, we only have to update one of them. | |
set_new_cards_in_deck(autoadd_decks[0], autoadd_per_deck) | |
def recalculate(): | |
total_new_setting = get_new_card_setting() | |
set_new_cards_in_deck(mw.col.decks.byName(DECK_EXACT_NAME), total_new_setting) | |
set_autoadd_deck_totals(total_new_setting) | |
# if we don't reset the view, the configuration change will not be immediately visible in the UI | |
mw.reset() | |
recalculate_action = QAction("Recalculate new card setting", mw) | |
recalculate_action.triggered.connect(recalculate) | |
mw.form.menuTools.addAction(recalculate_action) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment