From 4ddb7273098bee179bb77e0937e560fc0100960c Mon Sep 17 00:00:00 2001 From: Thanos Apollo Date: Thu, 4 Aug 2022 09:50:48 +0300 Subject: Add anki addons --- .../addons21/advanced_review/Deck_Overview.py | 646 +++++++++++++++++++++ 1 file changed, 646 insertions(+) create mode 100644 .local/share/Anki2/addons21/advanced_review/Deck_Overview.py (limited to '.local/share/Anki2/addons21/advanced_review/Deck_Overview.py') diff --git a/.local/share/Anki2/addons21/advanced_review/Deck_Overview.py b/.local/share/Anki2/addons21/advanced_review/Deck_Overview.py new file mode 100644 index 0000000..9b53121 --- /dev/null +++ b/.local/share/Anki2/addons21/advanced_review/Deck_Overview.py @@ -0,0 +1,646 @@ + + +import time +from datetime import date, timedelta +from aqt import mw +from copy import deepcopy +from aqt.utils import shortcut, showInfo, tr +from anki import version +anki_version = int(version.replace('.', '')) +if anki_version > 2119: + from aqt.deckbrowser import DeckBrowserBottomBar + from aqt.overview import OverviewBottomBar +from aqt.deckbrowser import DeckBrowser +from aqt.overview import Overview +from . import styles + +config = mw.addonManager.getConfig(__name__) +studyNow_label = config['Button Label_ Study Now'] +more_overviewStats = config[' More Overview Stats'] +bottombarButtons_style = config[' Review_ Bottombar Buttons Style'] +style_mainScreenButtons = config[' Style Main Screen Buttons'] + +bottombar_neon1 = styles.bottombar_neon1 +bottombar_neon2 = styles.bottombar_neon2 +bottombar_fill1 = styles.bottombar_fill1 +bottombar_fill2 = styles.bottombar_fill2 + +#// Chosing stylinhg for review other buttons in reviewer bottombar based on chosen style +if bottombarButtons_style == 0: + bottomHTML_style = "" +elif bottombarButtons_style == 1: + bottomHTML_style = bottombar_neon1 +elif bottombarButtons_style == 2: + bottomHTML_style = bottombar_neon2 +elif bottombarButtons_style == 3: + bottomHTML_style = bottombar_fill1 +elif bottombarButtons_style == 4: + bottomHTML_style = bottombar_fill2 + +#// Main Screen Bottombar Buttons +def _drawButtons(self): + buf = "{}".format(bottomHTML_style) + if style_mainScreenButtons: + #// style='height: px' -> to prevent changing main screen buttons heights + # based on height defined in #main {} + mainScreen_style = """id=main style='height: px' """ + else: + mainScreen_style = "" + drawLinks = deepcopy(self.drawLinks) + for b in drawLinks: + b.insert(0, "{}".format(mainScreen_style)) + if b[0]: + b[0] = ("Shortcut key: %s") % shortcut(b[0]) + buf += """ +""" % (tuple(b)) + if anki_version > 2121: + self.bottom.draw( + buf=buf, + link_handler=self._linkHandler, + web_context=DeckBrowserBottomBar(self), + ) + else: + self.bottom.draw(buf) + self.bottom.web.onBridgeCmd = self._linkHandler + +#// Deck Overview Bottombar Buttons +def _renderBottom(self): + links = [ + ["O", "opts", tr.actions_options()], + ] + if self.mw.col.decks.current()["dyn"]: + links.append(["R", "refresh", tr.actions_rebuild()]) + links.append(["E", "empty", tr.studying_empty()]) + else: + links.append(["C", "studymore", tr.actions_custom_study()]) + # links.append(["F", "cram", ("Filter/Cram")]) + if self.mw.col.sched.haveBuried(): + links.append(["U", "unbury", tr.studying_unbury()]) + links.append(["", "description", tr.scheduling_description()]) + buf = "{}".format(bottomHTML_style) + if style_mainScreenButtons: + #// style='height: px' -> to prevent changing main screen buttons heights + # based on height defined in #main {} + mainScreen_style = """id=main style='height: px' """ + else: + mainScreen_style = "" + for b in links: + b.insert(0, "{}".format(mainScreen_style)) + if b[0]: + b[0] = ("Shortcut key: %s") % shortcut(b[0]) + buf += """ +""" % tuple(b) + if anki_version > 2121: + self.bottom.draw( + buf=buf, + link_handler=self._linkHandler, + web_context=OverviewBottomBar(self) + ) + else: + self.bottom.draw(buf) + self.bottom.web.onBridgeCmd = self._linkHandler + + +#// Deck Overview Study Now Button | code from more overview stats to add more overview stats, OBVIOUSLY +if more_overviewStats == 1: + def _table(self): + """Returns html table with more statistics than before.""" + sched = self.mw.col.sched + deck = self.mw.col.decks.current() + dconf = self.mw.col.decks.confForDid(deck.get('id')) + but = self.mw.button + + # Get default counts + # 0 = new, 1 = learn, 2 = review + counts = list(sched.counts()) + finished = not sum(counts) + counts = _limit(counts) + + totals = [ + #new + sched.col.db.scalar(""" + select count() from (select id from cards where did = %s + and queue = 0)""" % deck.get('id')), + # learn + sched.col.db.scalar(""" + select count() from (select id from cards where did = %s + and queue in (1,3))""" % deck.get('id')), + # review + sched.col.db.scalar(""" + select count() from (select id from cards where did = %s + and queue = 2)""" % deck.get('id')), + # suspended + sched.col.db.scalar(""" + select count() from (select id from cards where did = %s + and queue = -1)""" % deck.get('id')), + # buried + sched.col.db.scalar(""" + select count() from (select id from cards where did = %s + and queue = -2)""" % deck.get('id')), + ] + + if (dconf.get('new')): + dueTomorrow = _limit([ + # new + min(dconf.get('new').get('perDay'), totals[0]), + # review + sched.col.db.scalar(""" + select count() from cards where did = %s and queue = 3 + and due = ?""" % deck.get('id'), sched.today + 1), + sched.col.db.scalar(""" + select count() from cards where did = %s and queue = 2 + and due = ?""" % deck.get('id'), sched.today + 1) + ]) + + html = '' + + # Style if less than 2.1.20 + if (int(version.replace('.', '')) < 2120): + html += ''' + ''' + + # No need to show due if we have finished collection today + if finished: + mssg = sched.finishedMsg() + html += ''' +
%s
+ ''' % mssg + else: + html +='''%s +
+ + +
+ + ''' % (bottomHTML_style, tr.browsing_sidebar_due_today(), counts[0], counts[1], counts[2]) + + if (dconf.get('new')): + html += ''' + ''' % (tr.statistics_due_tomorrow(), dueTomorrow[0], + dueTomorrow[1], dueTomorrow[2]) + + html += ''' + + + + +
%s: + %s + %s + %s +
%s: + %s + %s + %s +
%s: + %s + %s + %s + %s + %s +
''' % (tr.statistics_counts_total_cards(), totals[0], totals[1], totals[2], totals[4], + totals[3]) + + if not finished: + if style_mainScreenButtons: + #// style='height: px' -> to prevent changing main screen buttons heights + # based on height defined in #main {} + mainScreen_style = """id=main style='height: px' """ + else: + mainScreen_style = "" + if style_mainScreenButtons: + studyButton_id = "main" + else: + studyButton_id = "study" + html += '''
%s
''' % (but("study", ("{}".format(studyNow_label)), id="{}".format(studyButton_id), extra="autofocus")) + + return html + +elif more_overviewStats == 2: + def _table(self): + stat_colors = { + "New" : "#00a", + "Learning" : "#a00", + "Review" : "#080", + "Percent" : "#888", + "Mature" : "#0051ff", + "Young" : "#0051ff", + "Learned" : "#080", + "Unseen" : "#a00", + "Suspended" : "#e7a100", + "Done on Date" : "#ddd", + "Days until done" : "#ddd", + "Total" : "#ddd", + } + date_format = "%d.%m.%Y" + correction_for_notes = 1 + last_match_length = 0 + current_deck_name = self.mw.col.decks.current()['name'] + date_format = "%m/%d/%Y" + + try: + learn_per_day = self.mw.col.decks.confForDid(self.mw.col.decks.current()['id'])['new']['perDay'] + except: + learn_per_day = 0 + + total, mature, young, unseen, suspended, due = self.mw.col.db.first( + u''' + select + -- total + count(id), + -- mature + sum(case when queue = 2 and ivl >= 21 + then 1 else 0 end), + -- young / learning + sum(case when queue in (1, 3) or (queue = 2 and ivl < 21) + then 1 else 0 end), + -- unseen + sum(case when queue = 0 + then 1 else 0 end), + -- suspended + sum(case when queue < 0 + then 1 else 0 end), + -- due + sum(case when queue = 1 and due <= ? + then 1 else 0 end) + from cards where did in {:s} + '''.format(self.mw.col.sched._deckLimit()), round(time.time()) + ) + if not total: + return u'

No Cards Found.

' + + scheduled_counts = list(self.mw.col.sched.counts()) + deck_is_finished = not sum(scheduled_counts) + + cards = {} + + cards['mature'] = mature // int(correction_for_notes) + cards['young'] = young // int(correction_for_notes) + cards['unseen'] = unseen // int(correction_for_notes) + cards['suspended'] = suspended // int(correction_for_notes) + + cards['total'] = total // int(correction_for_notes) + cards['learned'] = cards['mature'] + cards['young'] + cards['unlearned'] = cards['total'] - cards['learned'] + + cards['new'] = scheduled_counts[0] + cards['learning'] = scheduled_counts[1] + cards['review'] = scheduled_counts[2] + # cards['due'] = due + cards['review'] + + cards['total_without_suspended'] = cards['total'] - cards['suspended'] + + try: + daysUntilDone = math.ceil(cards['unseen'] / learn_per_day) + except: + daysUntilDone = 0 + + try: + cards['doneDate'] = (date.today()+timedelta(days=daysUntilDone)).strftime(date_format) + except: + showInfo("Unsupported date format. Defaulting to Day.Month.Year instead. Use one of the shorthands: \"us\", \"asia\" or \"eu\", or specify the date like \"\%d.\%m.\%Y\", \"\%m/\%d/\%Y\" etc.\n For more information check the table at: https://docs.python.org/2/library/datetime.html#strftime-and-strptime-behavior", type="warning", title="More Overview Stats 2.1 Warning") + print(date_format) + cards['doneDate'] = (date.today()+timedelta(days=daysUntilDone)).strftime("%d.%m.%Y") + + cards['daysLeft'] = daysUntilDone + + if(daysUntilDone == 1): + cards['daysLeft'] = '{} day'.format(daysUntilDone) + else: + cards['daysLeft'] = '{} days'.format(daysUntilDone) + + cards_percent = {} + + cards_percent['mature'] = cards['mature'] * 1.0 / cards['total'] + cards_percent['young'] = cards['young'] * 1.0 / cards['total'] + cards_percent['unseen'] = cards['unseen'] * 1.0 / cards['total'] + cards_percent['suspended'] = cards['suspended'] * 1.0 / cards['total'] + + cards_percent['total'] = 1.0 + cards_percent['learned'] = cards['learned'] * 1.0 / cards['total'] + cards_percent['unlearned'] = cards['unlearned'] * 1.0 / cards['total'] + + cards_percent['new'] = cards['new'] * 1.0 / cards['total'] + cards_percent['learning'] = cards['learning'] * 1.0 / cards['total'] + cards_percent['review'] = cards['review'] * 1.0 / cards['total'] + # cards_percent['due'] = cards['due'] * 1.0 / cards['total'] + + cards_percent_without_suspended = {} + + if(cards['total_without_suspended'] != 0): + cards_percent_without_suspended['mature'] = cards['mature'] * 1.0 / cards['total_without_suspended'] + cards_percent_without_suspended['young'] = cards['young'] * 1.0 / cards['total_without_suspended'] + cards_percent_without_suspended['unseen'] = cards['unseen'] * 1.0 / cards['total_without_suspended'] + cards_percent_without_suspended['suspended'] = cards['suspended'] * 1.0 / cards['total_without_suspended'] + + cards_percent_without_suspended['total'] = 1.0 + cards_percent_without_suspended['learned'] = cards['learned'] * 1.0 / cards['total_without_suspended'] + cards_percent_without_suspended['unlearned'] = cards['unlearned'] * 1.0 / cards['total_without_suspended'] + + cards_percent_without_suspended['new'] = cards['new'] * 1.0 / cards['total_without_suspended'] + cards_percent_without_suspended['learning'] = cards['learning'] * 1.0 / cards['total_without_suspended'] + cards_percent_without_suspended['review'] = cards['review'] * 1.0 / cards['total_without_suspended'] + else: + cards_percent_without_suspended['mature'] = 0 + cards_percent_without_suspended['young'] = 0 + cards_percent_without_suspended['unseen'] = 0 + cards_percent_without_suspended['suspended'] = 0 + + cards_percent_without_suspended['total'] = 1.0 + cards_percent_without_suspended['learned'] = 0 + cards_percent_without_suspended['unlearned'] = 0 + + cards_percent_without_suspended['new'] = 0 + cards_percent_without_suspended['learning'] = 0 + cards_percent_without_suspended['review'] = 0 + + labels = {} + + labels['mature'] = tr.statistics_counts_mature_cards() + labels['young'] = tr.statistics_counts_young_cards() + labels['unseen'] = ('Unseen') + labels['suspended'] = tr.statistics_counts_suspended_cards() + + labels['total'] = tr.statistics_counts_total_cards() + labels['learned'] = ('Learned') + labels['unlearned'] = ('Unlearned') + + labels['new'] = tr.statistics_counts_new_cards() + labels['learning'] = tr.statistics_counts_learning_cards() + labels['review'] = ('Review') + # labels['due'] = ('Due') + + labels['doneDate'] = ('Done in') + + for key in labels: + labels[key] = u'{:s}:'.format(labels[key]) + + button = self.mw.button + + output_table = u''' + + + + ''' + + if not deck_is_finished: + output_table += u''' + + + + + + + + + + + + + + + + + + + + + + '''.format(label=labels, cards=cards, percent=cards_percent, percent2=cards_percent_without_suspended) + output_table += u''' + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + '''.format(label=labels, cards=cards, percent=cards_percent, percent2=cards_percent_without_suspended) + + output = '' + + if deck_is_finished: + if (config == None or not 'options' in config) or (config['options'].get('Show table for finished decks', True)): + output += output_table + output += u''' +
{label[new]:s}{cards[new]:d}{percent[new]:.0%}{percent2[new]:.0%}
{label[learning]:s}{cards[learning]:d}{percent[learning]:.0%}{percent2[learning]:.0%}
{label[review]:s}{cards[review]:d}{percent[review]:.0%}{percent2[review]:.0%}

{label[mature]:s}{cards[mature]:d}{percent[mature]:.0%}{percent2[mature]:.0%}
{label[young]:s}{cards[young]:d}{percent[young]:.0%}{percent2[young]:.0%}

{label[learned]:s}{cards[learned]:d}{percent[learned]:.0%}{percent2[learned]:.0%}
{label[unseen]:s}{cards[unseen]:d}{percent[unseen]:.0%}{percent2[unseen]:.0%}
{label[suspended]:s}{cards[suspended]:d}{percent[suspended]:.0%}ignored

{label[total]:s}{cards[total]:d}{percent[total]:.0%}{percent2[total]:.0%}

{label[doneDate]:s}{cards[daysLeft]:s}on:{cards[doneDate]:s}
+
+ ''' + output += u''' +
{:s}
+ '''.format(self.mw.col.sched.finishedMsg()) + else: + if style_mainScreenButtons: + #// style='height: px' -> to prevent changing main screen buttons heights + # based on height defined in #main {} + mainScreen_style = """id=main style='height: px' """ + else: + mainScreen_style = "" + if style_mainScreenButtons: + studyButton_id = "main" + else: + studyButton_id = "study" + + output += output_table + output += bottomHTML_style + output += u''' + + {button:s} + + + '''.format(button=button('study', tr.studying_study_now(), id='{}'.format(studyButton_id), extra="autofocus")) + + return output + +else: + def _table(self): + counts = list(self.mw.col.sched.counts()) + finished = not sum(counts) + if self.mw.col.sched_ver() == 1: + for n in range(len(counts)): + if counts[n] >= 1000: + counts[n] = "1000+" + but = self.mw.button + if finished: + return '
%s
' % ( + self.mw.col.sched.finishedMsg() + ) + else: + if style_mainScreenButtons: + #// style='height: px' -> to prevent changing main screen buttons heights + # based on height defined in #main {} + mainScreen_style = """id=main style='height: px' """ + else: + mainScreen_style = "" + if style_mainScreenButtons: + studyButton_id = "main" + else: + studyButton_id = "study" + return """%s + +
+ + + + +
%s:%s
%s:%s
%s:%s
+
+ %s
""" % ( + bottomHTML_style, + tr.actions_new(), + counts[0], + tr.scheduling_learning(), + counts[1], + tr.studying_to_review(), + counts[2], + but("study", tr.studying_study_now(), id="{}".format(studyButton_id), extra="autofocus"), + ) + +def _limit(counts): + for i, count in enumerate(counts): + if count >= 1000: + counts[i] = "1000+" + return counts + + +Overview._renderBottom = _renderBottom +DeckBrowser._drawButtons = _drawButtons +Overview._table = _table -- cgit v1.2.3