mirror of
https://github.com/ankitects/anki.git
synced 2025-09-25 09:16:38 -04:00
improve review time data; make sure graph bounds include end points
This commit is contained in:
parent
4c8eec5659
commit
02b1494a10
2 changed files with 80 additions and 24 deletions
|
@ -447,6 +447,7 @@ queue = 2 %s and due <= :lim order by %s limit %d""" % (
|
||||||
self._updateRevIvl(card, ease)
|
self._updateRevIvl(card, ease)
|
||||||
# then the rest
|
# then the rest
|
||||||
card.factor = max(1300, card.factor+[-150, 0, 150][ease-2])
|
card.factor = max(1300, card.factor+[-150, 0, 150][ease-2])
|
||||||
|
print "fixme: ensure ivl is 1+ current"
|
||||||
card.due = self.today + card.ivl
|
card.due = self.today + card.ivl
|
||||||
|
|
||||||
def _logRev(self, card, ease):
|
def _logRev(self, card, ease):
|
||||||
|
|
103
anki/stats.py
103
anki/stats.py
|
@ -137,9 +137,9 @@ table * { font-size: 14px; }
|
||||||
txt = self._title(
|
txt = self._title(
|
||||||
_("Forecast"),
|
_("Forecast"),
|
||||||
_("The number of reviews due in the future."))
|
_("The number of reviews due in the future."))
|
||||||
xaxis = dict(tickDecimals=0, min=0)
|
xaxis = dict(tickDecimals=0, min=-0.5)
|
||||||
if end is not None:
|
if end is not None:
|
||||||
xaxis['max'] = end
|
xaxis['max'] = end+0.5
|
||||||
txt += self._graph(id="due", data=data, conf=dict(
|
txt += self._graph(id="due", data=data, conf=dict(
|
||||||
xaxis=xaxis,
|
xaxis=xaxis,
|
||||||
yaxes=[dict(), dict(tickDecimals=0, position="right")]))
|
yaxes=[dict(), dict(tickDecimals=0, position="right")]))
|
||||||
|
@ -147,22 +147,8 @@ table * { font-size: 14px; }
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
def _dueInfo(self, tot, num):
|
def _dueInfo(self, tot, num):
|
||||||
if self.type == 0:
|
txt = _("Average: <b>%s</b>") % self._dayWeekMonth(
|
||||||
days = num
|
tot, num, _("reviews"))
|
||||||
elif self.type == 1:
|
|
||||||
days = num*7
|
|
||||||
else:
|
|
||||||
days = num*30
|
|
||||||
vals = []
|
|
||||||
try:
|
|
||||||
vals.append(_("%d/day") % (tot/days))
|
|
||||||
if self.type > 0:
|
|
||||||
vals.append(_("%d/week") % (tot/(days/7)))
|
|
||||||
if self.type > 1:
|
|
||||||
vals.append(_("%d/month") % (tot/(days/30)))
|
|
||||||
txt = _("Average reviews: <b>%s</b>") % ", ".join(vals)
|
|
||||||
except ZeroDivisionError:
|
|
||||||
return ""
|
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
def _due(self, start=None, end=None, chunk=1):
|
def _due(self, start=None, end=None, chunk=1):
|
||||||
|
@ -202,10 +188,10 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
return ""
|
return ""
|
||||||
d = data
|
d = data
|
||||||
conf = dict(
|
conf = dict(
|
||||||
xaxis=dict(tickDecimals=0),
|
xaxis=dict(tickDecimals=0, max=0.5),
|
||||||
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-0.5
|
||||||
def plot(id, data, ylabel):
|
def plot(id, data, ylabel):
|
||||||
return self._graph(
|
return self._graph(
|
||||||
id, data=data, conf=conf, ylabel=ylabel)
|
id, data=data, conf=conf, ylabel=ylabel)
|
||||||
|
@ -219,6 +205,9 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
txt = self._title(
|
txt = self._title(
|
||||||
reptitle, _("The number of questions you have answered."))
|
reptitle, _("The number of questions you have answered."))
|
||||||
txt += plot("reps", repdata, ylabel=_("Answers"))
|
txt += plot("reps", repdata, ylabel=_("Answers"))
|
||||||
|
(daysStud, fstDay) = self._daysStudied()
|
||||||
|
txt += self._ansInfo(repsum, daysStud, fstDay, _("reviews"))
|
||||||
|
|
||||||
# time
|
# time
|
||||||
(timdata, timsum) = self._splitRepData(d, (
|
(timdata, timsum) = self._splitRepData(d, (
|
||||||
(8, colMature, _("Mature")),
|
(8, colMature, _("Mature")),
|
||||||
|
@ -228,14 +217,39 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
(10, colCram, _("Cram"))))
|
(10, colCram, _("Cram"))))
|
||||||
if self.type == 0:
|
if self.type == 0:
|
||||||
t = _("Minutes")
|
t = _("Minutes")
|
||||||
|
convHours = False
|
||||||
else:
|
else:
|
||||||
t = _("Hours")
|
t = _("Hours")
|
||||||
|
convHours = True
|
||||||
txt += self._title(timetitle, _("The time taken to answer the questions."))
|
txt += self._title(timetitle, _("The time taken to answer the questions."))
|
||||||
txt += plot("time", timdata, ylabel=t)
|
txt += plot("time", timdata, ylabel=t)
|
||||||
|
txt += self._ansInfo(timsum, daysStud, fstDay, _("minutes"), convHours)
|
||||||
return txt
|
return txt
|
||||||
|
|
||||||
def _ansInfo(self, data):
|
def _ansInfo(self, totd, studied, first, unit, convHours=False):
|
||||||
return ""
|
if not totd:
|
||||||
|
return
|
||||||
|
tot = totd[-1][1]
|
||||||
|
period = self._periodDays()
|
||||||
|
if not period:
|
||||||
|
period = first
|
||||||
|
print period, first
|
||||||
|
txt = _("Days studied: <b>%(pct)d%%</b> (%(x)s of %(y)s)") % dict(
|
||||||
|
x=studied, y=period, pct=studied/float(period)*100)
|
||||||
|
if convHours:
|
||||||
|
tunit = _("hours")
|
||||||
|
else:
|
||||||
|
tunit = unit
|
||||||
|
txt += "<br>"+_("Total: <b>%(tot)s %(unit)s</b>") % dict(
|
||||||
|
unit=tunit, tot=int(tot))
|
||||||
|
if convHours:
|
||||||
|
# convert to minutes
|
||||||
|
tot *= 60
|
||||||
|
txt += "<br>"+_("Average over studied: <b>%s</b>") % self._dayWeekMonth(
|
||||||
|
tot, studied, unit)
|
||||||
|
txt += "<br>"+_("If you studied every day: <b>%s</b>") % self._dayWeekMonth(
|
||||||
|
tot, period, unit)
|
||||||
|
return txt
|
||||||
|
|
||||||
def _splitRepData(self, data, spec):
|
def _splitRepData(self, data, spec):
|
||||||
sep = {}
|
sep = {}
|
||||||
|
@ -259,7 +273,7 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
ret.append(dict(
|
ret.append(dict(
|
||||||
data=totd, color=colCum, label=_("Cumulative"), yaxis=2,
|
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))
|
||||||
return (ret, sum)
|
return (ret, totd)
|
||||||
|
|
||||||
def _done(self, num=7, chunk=1):
|
def _done(self, num=7, chunk=1):
|
||||||
lims = []
|
lims = []
|
||||||
|
@ -279,7 +293,7 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
tf = 3600.0 # hours
|
tf = 3600.0 # hours
|
||||||
return self.deck.db.all("""
|
return self.deck.db.all("""
|
||||||
select
|
select
|
||||||
(cast((time/1000 - :cut) / 86400.0 as int)+1)/:chunk as day,
|
(cast((time/1000 - :cut) / 86400.0 as int))/:chunk as day,
|
||||||
sum(case when type = 0 then 1 else 0 end), -- lrn count
|
sum(case when type = 0 then 1 else 0 end), -- lrn count
|
||||||
sum(case when type = 1 and lastIvl < 21 then 1 else 0 end), -- yng count
|
sum(case when type = 1 and lastIvl < 21 then 1 else 0 end), -- yng count
|
||||||
sum(case when type = 1 and lastIvl >= 21 then 1 else 0 end), -- mtr count
|
sum(case when type = 1 and lastIvl >= 21 then 1 else 0 end), -- mtr count
|
||||||
|
@ -297,6 +311,31 @@ group by day order by day""" % lim,
|
||||||
tf=tf,
|
tf=tf,
|
||||||
chunk=chunk)
|
chunk=chunk)
|
||||||
|
|
||||||
|
def _daysStudied(self):
|
||||||
|
lims = []
|
||||||
|
num = None
|
||||||
|
if self.type == 0:
|
||||||
|
num = 30
|
||||||
|
elif self.type == 1:
|
||||||
|
num = 7*52
|
||||||
|
if num:
|
||||||
|
lims.append(
|
||||||
|
"time > %d" %
|
||||||
|
((self.deck.sched.dayCutoff-(num*86400))*1000))
|
||||||
|
rlim = self._revlogLimit()
|
||||||
|
if rlim:
|
||||||
|
lims.append(rlim)
|
||||||
|
if lims:
|
||||||
|
lim = "where " + " and ".join(lims)
|
||||||
|
else:
|
||||||
|
lim = ""
|
||||||
|
return self.deck.db.first("""
|
||||||
|
select count(), abs(min(day)) from (select
|
||||||
|
(cast((time/1000 - :cut) / 86400.0 as int)+1) as day
|
||||||
|
from revlog %s
|
||||||
|
group by day order by day)""" % lim,
|
||||||
|
cut=self.deck.sched.dayCutoff)
|
||||||
|
|
||||||
# Intervals
|
# Intervals
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
@ -560,3 +599,19 @@ $(function () {
|
||||||
|
|
||||||
def _title(self, title, subtitle=""):
|
def _title(self, title, subtitle=""):
|
||||||
return '<h1>%s</h1>%s' % (title, subtitle)
|
return '<h1>%s</h1>%s' % (title, subtitle)
|
||||||
|
|
||||||
|
def _periodDays(self):
|
||||||
|
if self.type == 0:
|
||||||
|
return 30
|
||||||
|
elif self.type == 1:
|
||||||
|
return 365
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _dayWeekMonth(self, tot, num, unit):
|
||||||
|
vals = []
|
||||||
|
try:
|
||||||
|
vals.append(_("%d %s/day") % (tot/float(num), unit))
|
||||||
|
return ", ".join(vals)
|
||||||
|
except ZeroDivisionError:
|
||||||
|
return ""
|
||||||
|
|
Loading…
Reference in a new issue