mirror of
https://github.com/ankitects/anki.git
synced 2025-09-19 22:42:25 -04:00
Merge pull request #290 from jianli/change-chunk-by-deck-age
Fix chunk size for newer decks
This commit is contained in:
commit
039f6bb382
1 changed files with 50 additions and 69 deletions
115
anki/stats.py
115
anki/stats.py
|
@ -198,13 +198,24 @@ from revlog where id > ? """+lim, (self.col.sched.dayCutoff-86400)*1000)
|
||||||
# Due and cumulative due
|
# Due and cumulative due
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def dueGraph(self):
|
def get_start_end_chunk(self, by='review'):
|
||||||
|
start = 0
|
||||||
if self.type == 0:
|
if self.type == 0:
|
||||||
start, end, chunk = 0, 31, 1
|
end, chunk = 31, 1
|
||||||
elif self.type == 1:
|
elif self.type == 1:
|
||||||
start, end, chunk = 0, 52, 7
|
end, chunk = 52, 7
|
||||||
elif self.type == 2:
|
elif self.type == 2:
|
||||||
start, end, chunk = 0, None, 30
|
end = None
|
||||||
|
if self._deckAge(by) <= 100:
|
||||||
|
chunk = 1
|
||||||
|
elif self._deckAge(by) <= 700:
|
||||||
|
chunk = 7
|
||||||
|
else:
|
||||||
|
chunk = 31
|
||||||
|
return start, end, chunk
|
||||||
|
|
||||||
|
def dueGraph(self):
|
||||||
|
start, end, chunk = self.get_start_end_chunk()
|
||||||
d = self._due(start, end, chunk)
|
d = self._due(start, end, chunk)
|
||||||
yng = []
|
yng = []
|
||||||
mtr = []
|
mtr = []
|
||||||
|
@ -229,10 +240,13 @@ from revlog where id > ? """+lim, (self.col.sched.dayCutoff-86400)*1000)
|
||||||
xaxis = dict(tickDecimals=0, min=-0.5)
|
xaxis = dict(tickDecimals=0, min=-0.5)
|
||||||
if end is not None:
|
if end is not None:
|
||||||
xaxis['max'] = end-0.5
|
xaxis['max'] = end-0.5
|
||||||
txt += self._graph(id="due", data=data,
|
txt += self._graph(
|
||||||
ylabel2=_("Cumulative Cards"), conf=dict(
|
id="due", data=data, xunit=chunk, ylabel2=_("Cumulative Cards"),
|
||||||
xaxis=xaxis, yaxes=[dict(min=0), dict(
|
conf=dict(
|
||||||
min=0, tickDecimals=0, position="right")]))
|
xaxis=xaxis, yaxes=[
|
||||||
|
dict(min=0), dict(min=0, tickDecimals=0, position="right")]
|
||||||
|
),
|
||||||
|
)
|
||||||
txt += self._dueInfo(tot, len(totd)*chunk)
|
txt += self._dueInfo(tot, len(totd)*chunk)
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
|
@ -269,34 +283,26 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def introductionGraph(self):
|
def introductionGraph(self):
|
||||||
if self.type == 0:
|
start, days, chunk = self.get_start_end_chunk()
|
||||||
days = 30; chunk = 1
|
data = self._added(days, chunk)
|
||||||
elif self.type == 1:
|
|
||||||
days = 52; chunk = 7
|
|
||||||
else:
|
|
||||||
days = None; chunk = 30
|
|
||||||
return self._introductionGraph(self._added(days, chunk),
|
|
||||||
days, _("Added"))
|
|
||||||
|
|
||||||
def _introductionGraph(self, data, days, title):
|
|
||||||
if not data:
|
if not data:
|
||||||
return ""
|
return ""
|
||||||
d = data
|
|
||||||
conf = dict(
|
conf = dict(
|
||||||
xaxis=dict(tickDecimals=0, max=0.5),
|
xaxis=dict(tickDecimals=0, max=0.5),
|
||||||
yaxes=[dict(min=0), dict(position="right", min=0)])
|
yaxes=[dict(min=0), dict(position="right", min=0)])
|
||||||
if days is not None:
|
if days is not None:
|
||||||
|
# pylint: disable=invalid-unary-operand-type
|
||||||
conf['xaxis']['min'] = -days+0.5
|
conf['xaxis']['min'] = -days+0.5
|
||||||
def plot(id, data, ylabel, ylabel2):
|
def plot(id, data, ylabel, ylabel2):
|
||||||
return self._graph(
|
return self._graph(
|
||||||
id, data=data, conf=conf, ylabel=ylabel, ylabel2=ylabel2)
|
id, data=data, conf=conf, xunit=chunk, ylabel=ylabel, ylabel2=ylabel2)
|
||||||
# graph
|
# graph
|
||||||
(repdata, repsum) = self._splitRepData(d, ((1, colLearn, ""),))
|
repdata, repsum = self._splitRepData(data, ((1, colLearn, ""),))
|
||||||
txt = self._title(
|
txt = self._title(
|
||||||
title, _("The number of new cards you have added."))
|
_("Added"), _("The number of new cards you have added."))
|
||||||
txt += plot("intro", repdata, ylabel=_("Cards"), ylabel2=_("Cumulative Cards"))
|
txt += plot("intro", repdata, ylabel=_("Cards"), ylabel2=_("Cumulative Cards"))
|
||||||
# total and per day average
|
# total and per day average
|
||||||
tot = sum([i[1] for i in d])
|
tot = sum([i[1] for i in data])
|
||||||
period = self._periodDays()
|
period = self._periodDays()
|
||||||
if not period:
|
if not period:
|
||||||
# base off date of earliest added card
|
# base off date of earliest added card
|
||||||
|
@ -309,45 +315,35 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
def repsGraphs(self):
|
def repsGraphs(self):
|
||||||
if self.type == 0:
|
start, days, chunk = self.get_start_end_chunk()
|
||||||
days = 30; chunk = 1
|
data = self._done(days, chunk)
|
||||||
elif self.type == 1:
|
|
||||||
days = 52; chunk = 7
|
|
||||||
else:
|
|
||||||
days = None; chunk = 30
|
|
||||||
return self._repsGraphs(self._done(days, chunk),
|
|
||||||
days,
|
|
||||||
_("Review Count"),
|
|
||||||
_("Review Time"))
|
|
||||||
|
|
||||||
def _repsGraphs(self, data, days, reptitle, timetitle):
|
|
||||||
if not data:
|
if not data:
|
||||||
return ""
|
return ""
|
||||||
d = data
|
|
||||||
conf = dict(
|
conf = dict(
|
||||||
xaxis=dict(tickDecimals=0, max=0.5),
|
xaxis=dict(tickDecimals=0, max=0.5),
|
||||||
yaxes=[dict(min=0), dict(position="right", min=0)])
|
yaxes=[dict(min=0), dict(position="right", min=0)])
|
||||||
if days is not None:
|
if days is not None:
|
||||||
|
# pylint: disable=invalid-unary-operand-type
|
||||||
conf['xaxis']['min'] = -days+0.5
|
conf['xaxis']['min'] = -days+0.5
|
||||||
def plot(id, data, ylabel, ylabel2):
|
def plot(id, data, ylabel, ylabel2):
|
||||||
return self._graph(
|
return self._graph(
|
||||||
id, data=data, conf=conf, ylabel=ylabel, ylabel2=ylabel2)
|
id, data=data, conf=conf, xunit=chunk, ylabel=ylabel, ylabel2=ylabel2)
|
||||||
# reps
|
# reps
|
||||||
(repdata, repsum) = self._splitRepData(d, (
|
(repdata, repsum) = self._splitRepData(data, (
|
||||||
(3, colMature, _("Mature")),
|
(3, colMature, _("Mature")),
|
||||||
(2, colYoung, _("Young")),
|
(2, colYoung, _("Young")),
|
||||||
(4, colRelearn, _("Relearn")),
|
(4, colRelearn, _("Relearn")),
|
||||||
(1, colLearn, _("Learn")),
|
(1, colLearn, _("Learn")),
|
||||||
(5, colCram, _("Cram"))))
|
(5, colCram, _("Cram"))))
|
||||||
txt1 = self._title(
|
txt1 = self._title(
|
||||||
reptitle, _("The number of questions you have answered."))
|
_("Review Count"), _("The number of questions you have answered."))
|
||||||
txt1 += plot("reps", repdata, ylabel=_("Answers"), ylabel2=_(
|
txt1 += plot("reps", repdata, ylabel=_("Answers"), ylabel2=_(
|
||||||
"Cumulative Answers"))
|
"Cumulative Answers"))
|
||||||
(daysStud, fstDay) = self._daysStudied()
|
(daysStud, fstDay) = self._daysStudied()
|
||||||
rep, tot = self._ansInfo(repsum, daysStud, fstDay, _("reviews"))
|
rep, tot = self._ansInfo(repsum, daysStud, fstDay, _("reviews"))
|
||||||
txt1 += rep
|
txt1 += rep
|
||||||
# time
|
# time
|
||||||
(timdata, timsum) = self._splitRepData(d, (
|
(timdata, timsum) = self._splitRepData(data, (
|
||||||
(8, colMature, _("Mature")),
|
(8, colMature, _("Mature")),
|
||||||
(7, colYoung, _("Young")),
|
(7, colYoung, _("Young")),
|
||||||
(9, colRelearn, _("Relearn")),
|
(9, colRelearn, _("Relearn")),
|
||||||
|
@ -359,7 +355,7 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
else:
|
else:
|
||||||
t = _("Hours")
|
t = _("Hours")
|
||||||
convHours = True
|
convHours = True
|
||||||
txt2 = self._title(timetitle, _("The time taken to answer the questions."))
|
txt2 = self._title(_("Review Time"), _("The time taken to answer the questions."))
|
||||||
txt2 += plot("time", timdata, ylabel=t, ylabel2=_("Cumulative %s") % t)
|
txt2 += plot("time", timdata, ylabel=t, ylabel2=_("Cumulative %s") % t)
|
||||||
rep, tot2 = self._ansInfo(
|
rep, tot2 = self._ansInfo(
|
||||||
timsum, daysStud, fstDay, _("minutes"), convHours, total=tot)
|
timsum, daysStud, fstDay, _("minutes"), convHours, total=tot)
|
||||||
|
@ -416,7 +412,6 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
for (n, col, lab) in spec:
|
for (n, col, lab) in spec:
|
||||||
totcnt[n] = 0
|
totcnt[n] = 0
|
||||||
totd[n] = []
|
totd[n] = []
|
||||||
sum = []
|
|
||||||
for row in data:
|
for row in data:
|
||||||
for (n, col, lab) in spec:
|
for (n, col, lab) in spec:
|
||||||
if n not in sep:
|
if n not in sep:
|
||||||
|
@ -519,7 +514,7 @@ group by day order by day)""" % lim,
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def ivlGraph(self):
|
def ivlGraph(self):
|
||||||
(ivls, all, avg, max_) = self._ivls()
|
(ivls, all, avg, max_), chunk = self._ivls()
|
||||||
tot = 0
|
tot = 0
|
||||||
totd = []
|
totd = []
|
||||||
if not ivls or not all:
|
if not ivls or not all:
|
||||||
|
@ -535,7 +530,7 @@ group by day order by day)""" % lim,
|
||||||
ivlmax = max(5, ivls[-1][0])
|
ivlmax = max(5, ivls[-1][0])
|
||||||
txt = self._title(_("Intervals"),
|
txt = self._title(_("Intervals"),
|
||||||
_("Delays until reviews are shown again."))
|
_("Delays until reviews are shown again."))
|
||||||
txt += self._graph(id="ivl", ylabel2=_("Percentage"), data=[
|
txt += self._graph(id="ivl", ylabel2=_("Percentage"), xunit=chunk, data=[
|
||||||
dict(data=ivls, color=colIvl),
|
dict(data=ivls, color=colIvl),
|
||||||
dict(data=totd, color=colCum, yaxis=2,
|
dict(data=totd, color=colCum, yaxis=2,
|
||||||
bars={'show': False}, lines=dict(show=True), stack=False)
|
bars={'show': False}, lines=dict(show=True), stack=False)
|
||||||
|
@ -548,12 +543,8 @@ group by day order by day)""" % lim,
|
||||||
return txt + self._lineTbl(i)
|
return txt + self._lineTbl(i)
|
||||||
|
|
||||||
def _ivls(self):
|
def _ivls(self):
|
||||||
if self.type == 0:
|
start, end, chunk = self.get_start_end_chunk()
|
||||||
chunk = 1; lim = " and grp <= 30"
|
lim = "and grp <= %d" % end if end else ""
|
||||||
elif self.type == 1:
|
|
||||||
chunk = 7; lim = " and grp <= 52"
|
|
||||||
else:
|
|
||||||
chunk = 30; lim = ""
|
|
||||||
data = [self.col.db.all("""
|
data = [self.col.db.all("""
|
||||||
select ivl / :chunk as grp, count() from cards
|
select ivl / :chunk as grp, count() from cards
|
||||||
where did in %s and queue = 2 %s
|
where did in %s and queue = 2 %s
|
||||||
|
@ -561,7 +552,7 @@ group by grp
|
||||||
order by grp""" % (self._limit(), lim), chunk=chunk)]
|
order by grp""" % (self._limit(), lim), chunk=chunk)]
|
||||||
return data + list(self.col.db.first("""
|
return data + list(self.col.db.first("""
|
||||||
select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" %
|
select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" %
|
||||||
self._limit()))
|
self._limit())), chunk
|
||||||
|
|
||||||
# Eases
|
# Eases
|
||||||
######################################################################
|
######################################################################
|
||||||
|
@ -625,12 +616,7 @@ select count(), avg(ivl), max(ivl) from cards where did in %s and queue = 2""" %
|
||||||
lim = self._revlogLimit()
|
lim = self._revlogLimit()
|
||||||
if lim:
|
if lim:
|
||||||
lims.append(lim)
|
lims.append(lim)
|
||||||
if self.type == 0:
|
days = self._periodDays()
|
||||||
days = 30
|
|
||||||
elif self.type == 1:
|
|
||||||
days = 365
|
|
||||||
else:
|
|
||||||
days = None
|
|
||||||
if days is not None:
|
if days is not None:
|
||||||
lims.append("id > %d" % (
|
lims.append("id > %d" % (
|
||||||
(self.col.sched.dayCutoff-(days*86400))*1000))
|
(self.col.sched.dayCutoff-(days*86400))*1000))
|
||||||
|
@ -811,7 +797,7 @@ from cards where did in %s""" % self._limit())
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
def _graph(self, id, data, conf=None,
|
def _graph(self, id, data, conf=None,
|
||||||
type="bars", ylabel=_("Cards"), timeTicks=True, ylabel2=""):
|
type="bars", xunit=1, ylabel=_("Cards"), ylabel2=""):
|
||||||
if conf is None:
|
if conf is None:
|
||||||
conf = {}
|
conf = {}
|
||||||
# display settings
|
# display settings
|
||||||
|
@ -825,8 +811,7 @@ from cards where did in %s""" % self._limit())
|
||||||
conf['yaxis']['labelWidth'] = 40
|
conf['yaxis']['labelWidth'] = 40
|
||||||
if 'xaxis' not in conf:
|
if 'xaxis' not in conf:
|
||||||
conf['xaxis'] = {}
|
conf['xaxis'] = {}
|
||||||
if timeTicks:
|
conf['timeTicks'] = {1: _("d"), 7: _("w"), 31: _("mo")}[xunit]
|
||||||
conf['timeTicks'] = (_("d"), _("w"), _("mo"))[self.type]
|
|
||||||
# types
|
# types
|
||||||
width = self.width
|
width = self.width
|
||||||
height = self.height
|
height = self.height
|
||||||
|
@ -855,8 +840,6 @@ from cards where did in %s""" % self._limit())
|
||||||
opacity=0.5,
|
opacity=0.5,
|
||||||
color="#000"
|
color="#000"
|
||||||
)))
|
)))
|
||||||
|
|
||||||
#conf['legend'] = dict(show=False)
|
|
||||||
return (
|
return (
|
||||||
"""
|
"""
|
||||||
<table cellpadding=0 cellspacing=10>
|
<table cellpadding=0 cellspacing=10>
|
||||||
|
@ -937,12 +920,10 @@ $(function () {
|
||||||
return period
|
return period
|
||||||
|
|
||||||
def _periodDays(self):
|
def _periodDays(self):
|
||||||
if self.type == 0:
|
start, end, chunk = self.get_start_end_chunk()
|
||||||
return 30
|
if end is None:
|
||||||
elif self.type == 1:
|
|
||||||
return 365
|
|
||||||
else:
|
|
||||||
return None
|
return None
|
||||||
|
return end * chunk
|
||||||
|
|
||||||
def _avgDay(self, tot, num, unit):
|
def _avgDay(self, tot, num, unit):
|
||||||
vals = []
|
vals = []
|
||||||
|
|
Loading…
Reference in a new issue