Guest User

Untitled

a guest
Nov 4th, 2018
133
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 10.43 KB | None | 0 0
  1. import anki
  2. import anki.sched
  3.  
  4. import time
  5. import random
  6. import itertools
  7. from operator import itemgetter
  8. from heapq import *
  9.  
  10. #from anki.cards import Card
  11. from anki.utils import ids2str, intTime, fmtTimeSpan
  12. from anki.lang import _
  13. from anki.consts import *
  14. from anki.hooks import runHook
  15.  
  16. from aqt import mw
  17. addon_config = mw.addonManager.getConfig(__name__)
  18. if not addon_config:
  19.     addon_config = {
  20.         "change_sched_v1": True,
  21.         "disable_again_ease_change": True,
  22.         "override_max_review_cards": True,
  23.         "reset_ease": True,
  24.         "answer_button_overhaul": True,
  25.         "force_minimum_failure_interval_factor": 20,
  26.     }
  27.  
  28. # force_minimum_failure_interval_factor
  29. def v1_lapseConf(self, card):
  30.     conf = self._cardConf(card)
  31.     # normal deck
  32.     if not card.odid:
  33.         return conf['lapse']
  34.     # dynamic deck; override some attributes, use original deck for others
  35.     oconf = self.col.decks.confForDid(card.odid)
  36.     delays = conf['delays'] or oconf['lapse']['delays']
  37.     return dict(
  38.         # original deck
  39.         minInt=oconf['lapse']['minInt'],
  40.         leechFails=oconf['lapse']['leechFails'],
  41.         leechAction=oconf['lapse']['leechAction'],
  42.         mult=max(addon_config['force_minimum_failure_interval_factor'], oconf['lapse']['mult']), #####################
  43.         # overrides
  44.         delays=delays,
  45.         resched=conf['resched'],
  46.     )
  47.  
  48. # reset_ease
  49. def v1_answerRevCard(self, card, ease):
  50.     delay = 0
  51.     if ease == 1:
  52.         delay = self._rescheduleLapse(card)
  53.     else:
  54.         self._rescheduleRev(card, ease)
  55.     if addon_config['reset_ease']: #####################
  56.         conf = self._newConf(card)
  57.         card.factor = conf['initialFactor']
  58.     self._logRev(card, ease, delay)
  59.  
  60. # disable_again_ease_change
  61. def v1_rescheduleLapse(self, card):
  62.     conf = self._lapseConf(card)
  63.     card.lastIvl = card.ivl
  64.     if self._resched(card):
  65.         card.lapses += 1
  66.         card.ivl = self._nextLapseIvl(card, conf)
  67.         if not addon_config['disable_again_ease_change']: #####################
  68.             card.factor = max(1300, card.factor-200)
  69.         card.due = self.today + card.ivl
  70.         # if it's a filtered deck, update odue as well
  71.         if card.odid:
  72.             card.odue = card.due
  73.     # if suspended as a leech, nothing to do
  74.     delay = 0
  75.     if self._checkLeech(card, conf) and card.queue == -1:
  76.         return delay
  77.     # if no relearning steps, nothing to do
  78.     if not conf['delays']:
  79.         return delay
  80.     # record rev due date for later
  81.     if not card.odue:
  82.         card.odue = card.due
  83.     delay = self._delayForGrade(conf, 0)
  84.     card.due = int(delay + time.time())
  85.     card.left = self._startingLeft(card)
  86.     # queue 1
  87.     if card.due < self.dayCutoff:
  88.         self.lrnCount += card.left // 1000
  89.         card.queue = 1
  90.         heappush(self._lrnQueue, (card.due, card.id))
  91.     else:
  92.         # day learn queue
  93.         ahead = ((card.due - self.dayCutoff) // 86400) + 1
  94.         card.due = self.today + ahead
  95.         card.queue = 3
  96.     return delay
  97.  
  98. # override_max_review_cards
  99. def v1_deckRevLimitSingle(self, d):
  100.     if d['dyn']:
  101.         return self.reportLimit
  102.     c = self.col.decks.confForDid(d['id'])
  103.     if addon_config['override_max_review_cards']: ###############
  104.         return max(0, 9999 - d['revToday'][1])
  105.     else:
  106.         return max(0, c['rev']['perDay'] - d['revToday'][1])
  107.  
  108. # override_max_review_cards
  109. def v1_groupChildrenMain(self, grps):
  110.     tree = []
  111.     # group and recurse
  112.     def key(grp):
  113.         return grp[0][0]
  114.     for (head, tail) in itertools.groupby(grps, key=key):
  115.         tail = list(tail)
  116.         did = None
  117.         rev = 0
  118.         new = 0
  119.         lrn = 0
  120.         children = []
  121.         for c in tail:
  122.             if len(c[0]) == 1:
  123.                 # current node
  124.                 did = c[1]
  125.                 rev += c[2]
  126.                 lrn += c[3]
  127.                 new += c[4]
  128.             else:
  129.                 # set new string to tail
  130.                 c[0] = c[0][1:]
  131.                 children.append(c)
  132.         children = self._groupChildrenMain(children)
  133.         # tally up children counts
  134.         for ch in children:
  135.             rev += ch[2]
  136.             lrn += ch[3]
  137.             new += ch[4]
  138.         # limit the counts to the deck's limits
  139.         conf = self.col.decks.confForDid(did)
  140.         deck = self.col.decks.get(did)
  141.         if not conf['dyn']:
  142.             if addon_config['override_max_review_cards']: ###############
  143.                 rev = max(0, min(rev, 9999-deck['revToday'][1]))
  144.             else:
  145.                 rev = max(0, min(rev, conf['rev']['perDay']-deck['revToday'][1]))
  146.            
  147.             new = max(0, min(new, conf['new']['perDay']-deck['newToday'][1]))
  148.         tree.append((head, did, rev, lrn, new, children))
  149.     return tuple(tree)
  150.  
  151. # answer_button_overhaul
  152. def v1_answerButtons(self, card):
  153.     if card.odue:
  154.         # normal review in dyn deck?
  155.         if card.odid and card.queue == 2:
  156.             if addon_config['answer_button_overhaul']: ###############
  157.                 return 2
  158.             else:
  159.                 return 4
  160.         conf = self._lrnConf(card)
  161.         if card.type in (0,1) or len(conf['delays']) > 1:
  162.             return 3
  163.         return 2
  164.     elif card.queue == 2:
  165.         if addon_config['answer_button_overhaul']: ###############
  166.             return 2
  167.         else:
  168.             return 4
  169.     else:
  170.         return 3
  171.  
  172. # answer_button_overhaul
  173. def v1_answerLrnCard(self, card, ease):
  174.     ##############
  175.     if addon_config['answer_button_overhaul'] and card.left == self._startingLeft(card) and ease == 1:
  176.         ease = 2
  177.     ##############
  178.     # ease 1=no, 2=yes, 3=remove
  179.     conf = self._lrnConf(card)
  180.     if card.odid and not card.wasNew:
  181.         type = 3
  182.     elif card.type == 2:
  183.         type = 2
  184.     else:
  185.         type = 0
  186.     leaving = False
  187.     # lrnCount was decremented once when card was fetched
  188.     lastLeft = card.left
  189.     # immediate graduate?
  190.     if ease == 3:
  191.         self._rescheduleAsRev(card, conf, True)
  192.         leaving = True
  193.     # graduation time?
  194.     elif ease == 2 and (card.left%1000)-1 <= 0:
  195.         self._rescheduleAsRev(card, conf, False)
  196.         leaving = True
  197.     else:
  198.         # one step towards graduation
  199.         if ease == 2:
  200.             # decrement real left count and recalculate left today
  201.             left = (card.left % 1000) - 1
  202.             card.left = self._leftToday(conf['delays'], left)*1000 + left
  203.         # failed
  204.         else:
  205.             card.left = self._startingLeft(card)
  206.             resched = self._resched(card)
  207.             if 'mult' in conf and resched:
  208.                 # review that's lapsed
  209.                 card.ivl = max(1, conf['minInt'], card.ivl*conf['mult'])
  210.             else:
  211.                 # new card; no ivl adjustment
  212.                 pass
  213.             if resched and card.odid:
  214.                 card.odue = self.today + 1
  215.         delay = self._delayForGrade(conf, card.left)
  216.         if card.due < time.time():
  217.             # not collapsed; add some randomness
  218.             delay *= random.uniform(1, 1.25)
  219.         card.due = int(time.time() + delay)
  220.         # due today?
  221.         if card.due < self.dayCutoff:
  222.             self.lrnCount += card.left // 1000
  223.             # if the queue is not empty and there's nothing else to do, make
  224.             # sure we don't put it at the head of the queue and end up showing
  225.             # it twice in a row
  226.             card.queue = 1
  227.             if self._lrnQueue and not self.revCount and not self.newCount:
  228.                 smallestDue = self._lrnQueue[0][0]
  229.                 card.due = max(card.due, smallestDue+1)
  230.             heappush(self._lrnQueue, (card.due, card.id))
  231.         else:
  232.             # the card is due in one or more days, so we need to use the
  233.             # day learn queue
  234.             ahead = ((card.due - self.dayCutoff) // 86400) + 1
  235.             card.due = self.today + ahead
  236.             card.queue = 3
  237.     self._logLrn(card, ease, conf, leaving, type, lastLeft)
  238.  
  239. # answer_button_overhaul
  240. def v1_nextLrnIvl(self, card, ease):
  241.     if card.queue == 0:
  242.         card.left = self._startingLeft(card)
  243.     ##############
  244.     if addon_config['answer_button_overhaul'] and card.left == self._startingLeft(card) and ease == 1:
  245.         ease = 2
  246.     ##############
  247.     conf = self._lrnConf(card)
  248.     if ease == 1:
  249.         # fail
  250.         return self._delayForGrade(conf, len(conf['delays']))
  251.     elif ease == 3:
  252.         # early removal
  253.         if not self._resched(card):
  254.             return 0
  255.         return self._graduatingIvl(card, conf, True, adj=False) * 86400
  256.     else:
  257.         left = card.left%1000 - 1
  258.         if left <= 0:
  259.             # graduate
  260.             if not self._resched(card):
  261.                 return 0
  262.             return self._graduatingIvl(card, conf, False, adj=False) * 86400
  263.         else:
  264.             return self._delayForGrade(conf, left)
  265.  
  266. # answer_button_overhaul
  267. def v1_nextRevIvl(self, card, ease):
  268.     "Ideal next interval for CARD, given EASE."
  269.     delay = self._daysLate(card)
  270.     conf = self._revConf(card)
  271.     fct = card.factor / 1000
  272.     if addon_config['answer_button_overhaul']: ################
  273.         interval = self._constrainedIvl((card.ivl + delay // 2) * fct, conf, card.ivl)
  274.     else:
  275.         ivl2 = self._constrainedIvl((card.ivl + delay // 4) * 1.2, conf, card.ivl)
  276.         ivl3 = self._constrainedIvl((card.ivl + delay // 2) * fct, conf, ivl2)
  277.         ivl4 = self._constrainedIvl(
  278.             (card.ivl + delay) * fct * conf['ease4'], conf, ivl3)
  279.         if ease == 2:
  280.             interval = ivl2
  281.         elif ease == 3:
  282.             interval = ivl3
  283.         elif ease == 4:
  284.             interval = ivl4
  285.     return min(interval, conf['maxIvl'])
  286.  
  287. if addon_config['change_sched_v1']:
  288.     # override_max_review_cards
  289.     anki.sched.Scheduler._deckRevLimitSingle = v1_deckRevLimitSingle
  290.     anki.sched.Scheduler._groupChildrenMain = v1_groupChildrenMain
  291.     # disable_again_ease_change
  292.     anki.sched.Scheduler._rescheduleLapse = v1_rescheduleLapse
  293.     # reset_ease
  294.     anki.sched.Scheduler._answerRevCard = v1_answerRevCard
  295.     # force_minimum_failure_interval_factor
  296.     anki.sched.Scheduler._lapseConf = v1_lapseConf
  297.     # answer_button_overhaul
  298.     anki.sched.Scheduler.answerButtons = v1_answerButtons
  299.     anki.sched.Scheduler._answerLrnCard = v1_answerLrnCard
  300.     anki.sched.Scheduler._nextLrnIvl = v1_nextLrnIvl
  301.     anki.sched.Scheduler._nextRevIvl = v1_nextRevIvl
Advertisement
Add Comment
Please, Sign In to add comment