mirror of
https://github.com/ankitects/anki.git
synced 2025-09-24 16:56:36 -04:00
add descriptions and xaxis relabeling
This commit is contained in:
parent
674d2b2b30
commit
b52a2eed6d
1 changed files with 62 additions and 40 deletions
102
anki/graphs.py
102
anki/graphs.py
|
@ -24,31 +24,30 @@ class Graphs(object):
|
||||||
self.deck = deck
|
self.deck = deck
|
||||||
self._stats = None
|
self._stats = None
|
||||||
self.selective = selective
|
self.selective = selective
|
||||||
|
self.type = 0
|
||||||
|
|
||||||
def report(self, type=0):
|
def report(self, type=0):
|
||||||
# 0=days, 1=weeks, 2=months
|
# 0=days, 1=weeks, 2=months
|
||||||
# period-dependent graphs
|
# period-dependent graphs
|
||||||
txt = self.dueGraph(type)
|
self.type = type
|
||||||
txt += self.repsGraph(type)
|
txt = self.dueGraph()
|
||||||
txt += self.ivlGraph(type)
|
txt += self.repsGraph()
|
||||||
|
txt += self.ivlGraph()
|
||||||
# other graphs
|
# other graphs
|
||||||
txt += self.easeGraph()
|
txt += self.easeGraph()
|
||||||
return "<script>%s</script><center>%s</center>" % (anki.js.all, txt)
|
return "<script>%s\n</script><center>%s</center>" % (anki.js.all, txt)
|
||||||
|
|
||||||
# Due and cumulative due
|
# Due and cumulative due
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def dueGraph(self, type):
|
def dueGraph(self):
|
||||||
if type == 0:
|
if self.type == 0:
|
||||||
start = 0; end = 30; chunk = 1
|
start = 0; end = 30; chunk = 1;
|
||||||
elif type == 1:
|
elif self.type == 1:
|
||||||
start = 0; end = 52; chunk = 7
|
start = 0; end = 52; chunk = 7
|
||||||
elif type == 2:
|
elif self.type == 2:
|
||||||
start = 0; end = None; chunk = 30
|
start = 0; end = None; chunk = 30
|
||||||
return self._dueGraph(self._due(start, end, chunk), _("Forecast"))
|
d = self._due(start, end, chunk)
|
||||||
|
|
||||||
def _dueGraph(self, data, title):
|
|
||||||
d = data
|
|
||||||
yng = []
|
yng = []
|
||||||
mtr = []
|
mtr = []
|
||||||
tot = 0
|
tot = 0
|
||||||
|
@ -58,12 +57,12 @@ class Graphs(object):
|
||||||
mtr.append((day[0], day[2]))
|
mtr.append((day[0], day[2]))
|
||||||
tot += day[1]+day[2]
|
tot += day[1]+day[2]
|
||||||
totd.append((day[0], tot))
|
totd.append((day[0], tot))
|
||||||
txt = self._graph(id="due", title=title, data=[
|
txt = self._graph(id="due", title=_("Forecast"), data=[
|
||||||
dict(data=mtr, color=colMature, label=_("Mature")),
|
dict(data=mtr, color=colMature, label=_("Mature")),
|
||||||
dict(data=yng, color=colYoung, label=_("Young")),
|
dict(data=yng, color=colYoung, label=_("Young")),
|
||||||
dict(data=totd, color=colCum, label=_("Cumulative"), yaxis=2,
|
dict(data=totd, color=colCum, label=_("Cumulative"), yaxis=2,
|
||||||
bars={'show': False}, lines=dict(show=True), stack=False)
|
bars={'show': False}, lines=dict(show=True), stack=False)
|
||||||
], conf=dict(
|
], info=_("The number of reviews due in the future."), conf=dict(
|
||||||
xaxis=dict(tickDecimals=0),
|
xaxis=dict(tickDecimals=0),
|
||||||
yaxes=[dict(), dict(position="right")]))
|
yaxes=[dict(), dict(position="right")]))
|
||||||
return txt
|
return txt
|
||||||
|
@ -75,7 +74,7 @@ class Graphs(object):
|
||||||
if end is not None:
|
if end is not None:
|
||||||
lim += " and day < %d" % end
|
lim += " and day < %d" % end
|
||||||
return self.deck.db.all("""
|
return self.deck.db.all("""
|
||||||
select (due-:today+1)/:chunk as day,
|
select (due-:today)/:chunk as day,
|
||||||
sum(case when ivl < 21 then 1 else 0 end), -- yng
|
sum(case when ivl < 21 then 1 else 0 end), -- yng
|
||||||
sum(case when ivl >= 21 then 1 else 0 end) -- mtr
|
sum(case when ivl >= 21 then 1 else 0 end) -- mtr
|
||||||
from cards
|
from cards
|
||||||
|
@ -88,10 +87,10 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
# Reps and time spent
|
# Reps and time spent
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def repsGraph(self, type):
|
def repsGraph(self):
|
||||||
if type == 0:
|
if self.type == 0:
|
||||||
days = 30; chunk = 1
|
days = 30; chunk = 1
|
||||||
elif type == 1:
|
elif self.type == 1:
|
||||||
days = 52; chunk = 7
|
days = 52; chunk = 7
|
||||||
else:
|
else:
|
||||||
days = None; chunk = 30
|
days = None; chunk = 30
|
||||||
|
@ -107,9 +106,9 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
yaxes=[dict(), dict(position="right")])
|
yaxes=[dict(), dict(position="right")])
|
||||||
if days is not None:
|
if days is not None:
|
||||||
conf['xaxis']['min'] = -days
|
conf['xaxis']['min'] = -days
|
||||||
def plot(id, title, data, ylabel):
|
def plot(id, title, data, ylabel, info):
|
||||||
return self._graph(id, title=title,
|
return self._graph(id, title=title,
|
||||||
data=data, conf=conf, ylabel=ylabel)
|
data=data, conf=conf, ylabel=ylabel, info=info)
|
||||||
# reps
|
# reps
|
||||||
(repdata, repsum) = self._splitRepData(d, (
|
(repdata, repsum) = self._splitRepData(d, (
|
||||||
(3, colMature, _("Mature")),
|
(3, colMature, _("Mature")),
|
||||||
|
@ -117,7 +116,10 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
(4, colRelearn, _("Relearn")),
|
(4, colRelearn, _("Relearn")),
|
||||||
(1, colLearn, _("Learn")),
|
(1, colLearn, _("Learn")),
|
||||||
(5, colCram, _("Cram"))))
|
(5, colCram, _("Cram"))))
|
||||||
txt = plot("reps", reptitle, repdata, ylabel=_("Answers"))
|
txt = plot("reps", reptitle, repdata, ylabel=_("Answers"),
|
||||||
|
info=_("""\
|
||||||
|
The number of cards you have answered. Answering the same card twice \
|
||||||
|
counts as two answers."""))
|
||||||
# time
|
# time
|
||||||
(timdata, timsum) = self._splitRepData(d, (
|
(timdata, timsum) = self._splitRepData(d, (
|
||||||
(8, colMature, _("Mature")),
|
(8, colMature, _("Mature")),
|
||||||
|
@ -125,7 +127,8 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
(9, colRelearn, _("Relearn")),
|
(9, colRelearn, _("Relearn")),
|
||||||
(6, colLearn, _("Learn")),
|
(6, colLearn, _("Learn")),
|
||||||
(10, colCram, _("Cram"))))
|
(10, colCram, _("Cram"))))
|
||||||
txt += plot("time", timetitle, timdata, ylabel=_("Hours"))
|
txt += plot("time", timetitle, timdata, ylabel=_("Hours"), info=_("""\
|
||||||
|
Time spent answering cards."""))
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
def _splitRepData(self, data, spec):
|
def _splitRepData(self, data, spec):
|
||||||
|
@ -179,11 +182,11 @@ group by day order by day""" % lim,
|
||||||
# Intervals
|
# Intervals
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def ivlGraph(self, type):
|
def ivlGraph(self):
|
||||||
(ivls, all) = self._ivls(type)
|
(ivls, all) = self._ivls()
|
||||||
tot = 0
|
tot = 0
|
||||||
totd = []
|
totd = []
|
||||||
if not all:
|
if not ivls or not all:
|
||||||
return ""
|
return ""
|
||||||
for (grp, cnt) in ivls:
|
for (grp, cnt) in ivls:
|
||||||
tot += cnt
|
tot += cnt
|
||||||
|
@ -193,13 +196,16 @@ group by day order by day""" % lim,
|
||||||
dict(data=totd, color=colCum, label=_("% Total"), yaxis=2,
|
dict(data=totd, color=colCum, label=_("% Total"), yaxis=2,
|
||||||
bars={'show': False}, lines=dict(show=True), stack=False)
|
bars={'show': False}, lines=dict(show=True), stack=False)
|
||||||
], conf=dict(
|
], conf=dict(
|
||||||
yaxes=[dict(), dict(position="right", max=105)]))
|
yaxes=[dict(), dict(position="right", max=105)]),
|
||||||
|
info=_("""\
|
||||||
|
Intervals in the review queue. New cards and cards in (re)learning \
|
||||||
|
are not included."""))
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
def _ivls(self, type):
|
def _ivls(self):
|
||||||
if type == 0:
|
if self.type == 0:
|
||||||
chunk = 1; lim = " and grp <= 30"
|
chunk = 1; lim = " and grp <= 30"
|
||||||
elif type == 1:
|
elif self.type == 1:
|
||||||
chunk = 7; lim = " and grp <= 52"
|
chunk = 7; lim = " and grp <= 52"
|
||||||
else:
|
else:
|
||||||
chunk = 30; lim = ""
|
chunk = 30; lim = ""
|
||||||
|
@ -230,11 +236,12 @@ select count() from cards where queue = 2 %s""" % self._limit()))
|
||||||
ticks = [[1,1],[2,2],[3,3],
|
ticks = [[1,1],[2,2],[3,3],
|
||||||
[6,1],[7,2],[8,3],[9,4],
|
[6,1],[7,2],[8,3],[9,4],
|
||||||
[11, 1],[12,2],[13,3],[14,4]]
|
[11, 1],[12,2],[13,3],[14,4]]
|
||||||
txt = self._graph(id="ease", title=_("Eases"), data=[
|
txt = self._graph(id="ease", title=_("Answer Buttons"), data=[
|
||||||
dict(data=d['lrn'], color=easesNewC, label=_("Learning")),
|
dict(data=d['lrn'], color=colLearn, label=_("Learning")),
|
||||||
dict(data=d['yng'], color=easesYoungC, label=_("Young")),
|
dict(data=d['yng'], color=colYoung, label=_("Young")),
|
||||||
dict(data=d['mtr'], color=easesMatureC, label=_("Mature")),
|
dict(data=d['mtr'], color=colMature, label=_("Mature")),
|
||||||
], type="barsLine", conf=dict(
|
], type="barsLine", info=_("""\
|
||||||
|
The number of times you have pressed each answer button."""), conf=dict(
|
||||||
xaxis=dict(ticks=ticks, min=0, max=15)),
|
xaxis=dict(ticks=ticks, min=0, max=15)),
|
||||||
ylabel=_("Answers"))
|
ylabel=_("Answers"))
|
||||||
return txt
|
return txt
|
||||||
|
@ -254,13 +261,17 @@ order by thetype, ease""")
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def _graph(self, id, title, data, conf={}, width=600, height=200,
|
def _graph(self, id, title, data, conf={}, width=600, height=200,
|
||||||
type="bars", ylabel=_("Cards")):
|
type="bars", ylabel=_("Cards"), timeTicks=True, info=""):
|
||||||
# display settings
|
# display settings
|
||||||
conf['legend'] = {'container': "#%sLegend" % id}
|
conf['legend'] = {'container': "#%sLegend" % id}
|
||||||
conf['series'] = dict(stack=True)
|
conf['series'] = dict(stack=True)
|
||||||
if not 'yaxis' in conf:
|
if not 'yaxis' in conf:
|
||||||
conf['yaxis'] = {}
|
conf['yaxis'] = {}
|
||||||
conf['yaxis']['labelWidth'] = 40
|
conf['yaxis']['labelWidth'] = 40
|
||||||
|
if 'xaxis' not in conf:
|
||||||
|
conf['xaxis'] = {}
|
||||||
|
if timeTicks:
|
||||||
|
conf['timeTicks'] = (_("d"), _("w"), _("m"))[self.type]
|
||||||
if type == "bars":
|
if type == "bars":
|
||||||
conf['series']['bars'] = dict(
|
conf['series']['bars'] = dict(
|
||||||
show=True, barWidth=0.8, align="center", fill=0.7, lineWidth=0)
|
show=True, barWidth=0.8, align="center", fill=0.7, lineWidth=0)
|
||||||
|
@ -276,16 +287,27 @@ order by thetype, ease""")
|
||||||
<tr>
|
<tr>
|
||||||
<td><div style="width: 10px; -webkit-transform: rotate(-90deg);
|
<td><div style="width: 10px; -webkit-transform: rotate(-90deg);
|
||||||
-moz-transform: rotate(-90deg);">%(ylab)s</div></td>
|
-moz-transform: rotate(-90deg);">%(ylab)s</div></td>
|
||||||
|
|
||||||
<td><div id="%(id)s" style="width:%(w)s; height:%(h)s;"></div></td>
|
<td><div id="%(id)s" style="width:%(w)s; height:%(h)s;"></div></td>
|
||||||
<td width=100 valign=top><br><div id=%(id)sLegend></div></td></tr></table>
|
|
||||||
|
<td width=100 valign=top><br>
|
||||||
|
<div id=%(id)sLegend></div>
|
||||||
|
<br><small>%(info)s</small>
|
||||||
|
</td></tr></table>
|
||||||
<script>
|
<script>
|
||||||
$(function () {
|
$(function () {
|
||||||
$.plot($("#%(id)s"), %(data)s, %(conf)s);
|
var conf = %(conf)s;
|
||||||
|
if (conf.timeTicks) {
|
||||||
|
conf.xaxis.tickFormatter = function (val, axis) {
|
||||||
|
return val.toFixed(0)+conf.timeTicks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$.plot($("#%(id)s"), %(data)s, conf);
|
||||||
});
|
});
|
||||||
</script>""" % dict(
|
</script>""" % dict(
|
||||||
id=id, title=title, w=width, h=height, tw=width+100, ylab=ylabel,
|
id=id, title=title, w=width, h=height, tw=width+100, ylab=ylabel,
|
||||||
data=simplejson.dumps(data),
|
info=info,
|
||||||
conf=simplejson.dumps(conf)))
|
data=simplejson.dumps(data), conf=simplejson.dumps(conf)))
|
||||||
|
|
||||||
def _limit(self):
|
def _limit(self):
|
||||||
if self.selective:
|
if self.selective:
|
||||||
|
|
Loading…
Reference in a new issue