-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmds_time_left.py
183 lines (164 loc) · 8.37 KB
/
mds_time_left.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
# -*- coding: utf-8 -*-
#Copyright(C) | Carlos Duarte
#Based 1 on | Dmitry Mikheev code, in add-on "More decks overview stats"
#Based 2 on | calumkscode, in add-on https://github.com/calumks/anki-deck-stats
#License | GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
#Source in | https://github.com/cjdduarte/MDS_Time_Left
import anki
from anki.lang import _, ngettext
import aqt
from aqt import mw, theme
from aqt.utils import tooltip
from aqt.overview import Overview, OverviewContent, OverviewBottomBar
import math
from datetime import datetime, timezone, timedelta, date
import time
#-------------Configuration------------------
config = mw.addonManager.getConfig(__name__)
# The default steps for "New" Anki cards are 1min and 10min meaning that you see New cards actually a minimum of *TWO* times that day
# You can now configure how many times new cards will be counted.
# CountTimesNew = 1 (old version)
# Quantify '1' time the "new card" time | Example: Steps (10 1440)
# CountTimesNew = 2 (default)
# Quantify '2' times the "new card" time | Example: Steps (1 10)
# CountTimesNew = n
# Quantify 'n' times the "new card" time | Example: Steps (1 10 10 20 30...)
CountTimesNew = config['CountTimesNew']
lrnSteps = 3
showDebug = 0
#-------------Configuration------------------
def renderStats(self, _old):
x = (mw.col.sched.day_cutoff - 86400*7)*1000
"""Calculate progress using weights and card counts from the sched."""
# Get studdied cards and true retention stats
xcards, xfailed, xdistinct, xflunked, xpassed = mw.col.db.first("""
select
sum(case when ease >=1 then 1 else 0 end), /* xcards */
sum(case when ease = 1 then 1 else 0 end), /* xfailed */
count(distinct cid), /* xdistinct */
sum(case when ease = 1 and type == 1 then 1 else 0 end), /* xflunked */
sum(case when ease > 1 and type == 1 then 1 else 0 end) /* xpassed */
from revlog where id > ?""",x)
xcards = xcards or 0
xfailed = xfailed or 0
xdistinct = xdistinct or 0
xflunked = xflunked or 0
xpassed = xpassed or 0
TR = 1-float(xpassed/(float(max(1,xpassed+xflunked))))
xagain = float((xfailed)/max(1,(xcards-xpassed)))
lrnWeight = float((1+(1*xagain*lrnSteps))/1)
newWeight = float((1+(1*xagain*lrnSteps))/1)
revWeight = float((1+(1*TR*lrnSteps))/1)
# Get due and new cards
new = 0
lrn = 0
due = 0
for tree in self.mw.col.sched.deckDueTree():
new += tree[4]
lrn += tree[3]
due += tree[2]
#if CountTimesNew == 0: CountTimesNew = 2
total = (newWeight*new) + (lrnWeight*lrn) + (revWeight*due)
totalDisplay = int((newWeight*new) + (lrnWeight*lrn) + (revWeight*due))
#total = new + lrn + due
# Get studdied cards
cards, thetime = self.mw.col.db.first(
"""select count(), sum(time)/1000 from revlog where id > ?""",
(self.mw.col.sched.dayCutoff - 86400) * 1000)
cards = cards or 0
thetime = thetime or 0
speed = thetime / max(1, cards)
minutes = (total*speed)/3600
thetimerounded = round(thetime/60,2)
hrhr = math.floor(minutes)
hrmin = math.floor(60*(minutes-hrhr))
hrsec = ((minutes-hrhr)*60-hrmin)*60
dt=datetime.today()
tz = 8 #GMT+ <CHANGE THIS TO YOUR GMT+_ (negative number if you're GMT-)>
tzsec = tz*3600
t = timedelta(hours = hrhr, minutes = hrmin, seconds = hrsec)
left = dt.timestamp()+tzsec+t.total_seconds()
date_time = datetime.utcfromtimestamp(left).strftime('%Y-%m-%d %H:%M:%S')
date_time_24H = datetime.strptime(date_time, "%Y-%m-%d %H:%M:%S")
ETA = date_time_24H.strftime("%I:%M %p")
if theme.theme_manager.night_mode:
NewColor = config['NewColorDark']
ReviewColor = config['ReviewColorDark']
LearnColor = config['LearnColorDark']
TotalDueColor = config['TotalDueColorDark']
TotalColor = config['TotalColorDark']
else:
NewColor = config['NewColorLight']
ReviewColor = config['ReviewColorLight']
LearnColor = config['LearnColorLight']
TotalDueColor = config['TotalDueColorLight']
TotalColor = config['TotalColorLight']
insert_style = "<style type=\"text/css\">" \
+ ".new-color { color:" + NewColor + ";}" \
+ ".review-color { color:" + ReviewColor + ";}" \
+ ".learn-color { color:" + LearnColor + ";}" \
+ ".totaldue-color { color:" + TotalDueColor + ";}" \
+ ".total-color { color:" + TotalColor + ";}" \
+ "</style>"
if showDebug:
buf = insert_style \
+ "<div style='display:table;padding-top:1.5em;'>" \
+ "<div style='display:table-cell;background-color:black'> " \
+ "Studied " + _("%d") % (cards)+ " cards in " + _("%.02f") % (thetimerounded) + " minutes today" + "<hr>" \
+ _("New Cards") \
+ ": <span class='new-color'> %(d)s</span>" % dict(d=new) \
+ " " + _("Learn") \
+ ": <span class='learn-color'>%(c)s</span>" % dict(c=lrn) \
+ " <span style='white-space:nowrap;'>" + _("To Review") \
+ ": <span class='review-color'>%(c)s</span>" % dict(c=due) \
+ "</span>" \
+ " <br><span style='white-space:nowrap;'>" + _("Due") \
+ ": <b class='totaldue-color'>%(c)s</b> " % dict(c=(lrn+due)) \
+ "</span> " \
+ " <span style='white-space:nowrap;'>" + _("Total") \
+ ": <b class='total-color'>%(c)s</b>" % dict(c=(totalDisplay)) \
+ "</span></div>" \
+ "<div style='display:table-cell;vertical-align:middle;" \
+ "padding-left:2em;'>" \
+ "<span style='white-space:nowrap;'>" + _("Statistics") \
+ ":<br> " + _("%.02f") % (speed) + " " + (_("s") + "/" + _("card").replace("s", "")).lower() \
+ "</span><br>" \
+ str(ngettext("%02d", "%02d", hrhr) % (hrhr)) + ":" + str(ngettext("%02d", "%02d", hrmin) % (hrmin)) + _(" More").lower() \
+ "</span><br>" \
+ str(ngettext("ETA %s","ETA %s",ETA) % (ETA)).replace(".",".")+ " " \
+ "</span><br>" \
+ str(ngettext("New/Lrn: %.02f","New/Lrn: %.02f",lrnWeight) % (lrnWeight)).replace(".",".")+ " " \
+ str(ngettext("Rev: %.02f","Rev: %.02f",revWeight) % (revWeight)).replace(".",".")+ " " \
+ "</div></div>"
else:
buf = insert_style \
+ "<div style='display:table;padding-top:1.5em;'>" \
+ "<div style='display:table-cell;background-color:black'> " \
+ "Studied " + _("%d") % (cards)+ " cards in " + _("%.02f") % (thetimerounded) + " minutes today" + "<hr>" \
+ _("New Cards") \
+ ": <span class='new-color'> %(d)s</span>" % dict(d=new) \
+ " " + _("Learn") \
+ ": <span class='learn-color'>%(c)s</span>" % dict(c=lrn) \
+ " <span style='white-space:nowrap;'>" + _("To Review") \
+ ": <span class='review-color'>%(c)s</span>" % dict(c=due) \
+ "</span>" \
+ " <br><span style='white-space:nowrap;'>" + _("Due") \
+ ": <b class='totaldue-color'>%(c)s</b> " % dict(c=(lrn+due)) \
+ "</span> " \
+ " <span style='white-space:nowrap;'>" + _("Total") \
+ ": <b class='total-color'>%(c)s</b>" % dict(c=(totalDisplay)) \
+ "</span></div>" \
+ "<div style='display:table-cell;vertical-align:middle;" \
+ "padding-left:2em;'>" \
+ "<span style='white-space:nowrap;'>" + _("Statistics") \
+ ":<br> " + _("%.02f") % (speed) + " " + (_("s") + "/" + _("card").replace("s", "")).lower() \
+ "</span><br>" \
+ str(ngettext("%02d", "%02d", hrhr) % (hrhr)) + ":" + str(ngettext("%02d", "%02d", hrmin) % (hrmin)) + _(" More").lower() \
+ "</span><br>" \
+ str(ngettext("ETA %s","ETA %s",ETA) % (ETA)).replace(".",".")+ " " \
+ "</div></div>"
return buf
#+ ":<br> " + _("%.01f cards/minute") % (speed) \
#+ _("More") + " " + ngettext("%s minute.", "%s minutes.", minutes) % (minutes) \
aqt.deckbrowser.DeckBrowser._renderStats = anki.hooks.wrap(
aqt.deckbrowser.DeckBrowser._renderStats, renderStats, 'around')