mirror of
https://github.com/ankitects/anki.git
synced 2025-09-20 23:12:21 -04:00
Merge branch 'master' of https://github.com/sobjornstad/anki
This commit is contained in:
commit
c4fffdda92
2 changed files with 87 additions and 12 deletions
|
@ -117,6 +117,7 @@ class CollectionStats(object):
|
||||||
txt += self.todayStats()
|
txt += self.todayStats()
|
||||||
txt += self.dueGraph()
|
txt += self.dueGraph()
|
||||||
txt += self.repsGraph()
|
txt += self.repsGraph()
|
||||||
|
txt += self.introductionGraph()
|
||||||
txt += self.ivlGraph()
|
txt += self.ivlGraph()
|
||||||
txt += self.hourGraph()
|
txt += self.hourGraph()
|
||||||
txt += self.easeGraph()
|
txt += self.easeGraph()
|
||||||
|
@ -254,9 +255,49 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
today=self.col.sched.today,
|
today=self.col.sched.today,
|
||||||
chunk=chunk)
|
chunk=chunk)
|
||||||
|
|
||||||
# Reps and time spent
|
# Added, reps and time spent
|
||||||
######################################################################
|
######################################################################
|
||||||
|
|
||||||
|
def introductionGraph(self):
|
||||||
|
if self.type == 0:
|
||||||
|
days = 30; chunk = 1
|
||||||
|
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:
|
||||||
|
return ""
|
||||||
|
d = data
|
||||||
|
conf = dict(
|
||||||
|
xaxis=dict(tickDecimals=0, max=0.5),
|
||||||
|
yaxes=[dict(min=0), dict(position="right",min=0)])
|
||||||
|
if days is not None:
|
||||||
|
conf['xaxis']['min'] = -days+0.5
|
||||||
|
def plot(id, data, ylabel, ylabel2):
|
||||||
|
return self._graph(
|
||||||
|
id, data=data, conf=conf, ylabel=ylabel, ylabel2=ylabel2)
|
||||||
|
# graph
|
||||||
|
(repdata, repsum) = self._splitRepData(d, ((1, colLearn, ""),))
|
||||||
|
txt = self._title(
|
||||||
|
title, _("The number of new cards you have added."))
|
||||||
|
txt += plot("intro", repdata, ylabel=_("Cards"), ylabel2=_("Cumulative Cards"))
|
||||||
|
# total and per day average
|
||||||
|
tot = sum([i[1] for i in d])
|
||||||
|
period = self._periodDays()
|
||||||
|
if not period:
|
||||||
|
# base off date of earliest added card
|
||||||
|
period = self._deckAge('add')
|
||||||
|
i = []
|
||||||
|
self._line(i, _("Total"), _("%i cards") % tot)
|
||||||
|
self._line(i, _("Average"), _("%.01f cards/day") % (float(tot) / period))
|
||||||
|
txt += self._lineTbl(i)
|
||||||
|
|
||||||
|
return txt
|
||||||
|
|
||||||
def repsGraph(self):
|
def repsGraph(self):
|
||||||
if self.type == 0:
|
if self.type == 0:
|
||||||
days = 30; chunk = 1
|
days = 30; chunk = 1
|
||||||
|
@ -322,15 +363,7 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
period = self._periodDays()
|
period = self._periodDays()
|
||||||
if not period:
|
if not period:
|
||||||
# base off earliest repetition date
|
# base off earliest repetition date
|
||||||
lim = self._revlogLimit()
|
period = self._deckAge('review')
|
||||||
if lim:
|
|
||||||
lim = " where " + lim
|
|
||||||
t = self.col.db.scalar("select id from revlog %s order by id limit 1" % lim)
|
|
||||||
if not t:
|
|
||||||
period = 1
|
|
||||||
else:
|
|
||||||
period = max(
|
|
||||||
1, int(1+((self.col.sched.dayCutoff - (t/1000)) / 86400)))
|
|
||||||
i = []
|
i = []
|
||||||
self._line(i, _("Days studied"),
|
self._line(i, _("Days studied"),
|
||||||
_("<b>%(pct)d%%</b> (%(x)s of %(y)s)") % dict(
|
_("<b>%(pct)d%%</b> (%(x)s of %(y)s)") % dict(
|
||||||
|
@ -394,6 +427,27 @@ group by day order by day""" % (self._limit(), lim),
|
||||||
bars={'show': False}, lines=dict(show=True), stack=-n))
|
bars={'show': False}, lines=dict(show=True), stack=-n))
|
||||||
return (ret, alltot)
|
return (ret, alltot)
|
||||||
|
|
||||||
|
def _added(self, num=7, chunk=1):
|
||||||
|
lims = []
|
||||||
|
if num is not None:
|
||||||
|
lims.append("id > %d" % (
|
||||||
|
(self.col.sched.dayCutoff-(num*chunk*86400))*1000))
|
||||||
|
lims.append("did in %s" % self._limit())
|
||||||
|
if lims:
|
||||||
|
lim = "where " + " and ".join(lims)
|
||||||
|
else:
|
||||||
|
lim = ""
|
||||||
|
if self.type == 0:
|
||||||
|
tf = 60.0 # minutes
|
||||||
|
else:
|
||||||
|
tf = 3600.0 # hours
|
||||||
|
return self.col.db.all("""
|
||||||
|
select
|
||||||
|
(cast((id/1000.0 - :cut) / 86400.0 as int))/:chunk as day,
|
||||||
|
count(id)
|
||||||
|
from cards %s
|
||||||
|
group by day order by day""" % lim, cut=self.col.sched.dayCutoff,tf=tf, chunk=chunk)
|
||||||
|
|
||||||
def _done(self, num=7, chunk=1):
|
def _done(self, num=7, chunk=1):
|
||||||
lims = []
|
lims = []
|
||||||
if num is not None:
|
if num is not None:
|
||||||
|
@ -839,6 +893,22 @@ $(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 _deckAge(self, by):
|
||||||
|
lim = self._revlogLimit()
|
||||||
|
if lim:
|
||||||
|
lim = " where " + lim
|
||||||
|
if by == 'review':
|
||||||
|
t = self.col.db.scalar("select id from revlog %s order by id limit 1" % lim)
|
||||||
|
elif by == 'add':
|
||||||
|
lim = "where did in %s" % ids2str(self.col.decks.active())
|
||||||
|
t = self.col.db.scalar("select id from cards %s order by id limit 1" % lim)
|
||||||
|
if not t:
|
||||||
|
period = 1
|
||||||
|
else:
|
||||||
|
period = max(
|
||||||
|
1, int(1+((self.col.sched.dayCutoff - (t/1000)) / 86400)))
|
||||||
|
return period
|
||||||
|
|
||||||
def _periodDays(self):
|
def _periodDays(self):
|
||||||
if self.type == 0:
|
if self.type == 0:
|
||||||
return 30
|
return 30
|
||||||
|
|
|
@ -41,6 +41,7 @@ class ExportDialog(QDialog):
|
||||||
def exporterChanged(self, idx):
|
def exporterChanged(self, idx):
|
||||||
self.exporter = exporters()[idx][1](self.col)
|
self.exporter = exporters()[idx][1](self.col)
|
||||||
self.isApkg = hasattr(self.exporter, "includeSched")
|
self.isApkg = hasattr(self.exporter, "includeSched")
|
||||||
|
self.isTextNote = hasattr(self.exporter, "includeTags")
|
||||||
self.hideTags = hasattr(self.exporter, "hideTags")
|
self.hideTags = hasattr(self.exporter, "hideTags")
|
||||||
self.frm.includeSched.setVisible(self.isApkg)
|
self.frm.includeSched.setVisible(self.isApkg)
|
||||||
self.frm.includeMedia.setVisible(self.isApkg)
|
self.frm.includeMedia.setVisible(self.isApkg)
|
||||||
|
@ -103,7 +104,11 @@ class ExportDialog(QDialog):
|
||||||
period = 5000
|
period = 5000
|
||||||
else:
|
else:
|
||||||
period = 3000
|
period = 3000
|
||||||
msg = ngettext("%d card exported.", "%d cards exported.", \
|
if self.isTextNote:
|
||||||
|
msg = ngettext("%d note exported.", "%d notes exported.",
|
||||||
|
self.exporter.count) % self.exporter.count
|
||||||
|
else:
|
||||||
|
msg = ngettext("%d card exported.", "%d cards exported.",
|
||||||
self.exporter.count) % self.exporter.count
|
self.exporter.count) % self.exporter.count
|
||||||
tooltip(msg, period=period)
|
tooltip(msg, period=period)
|
||||||
finally:
|
finally:
|
||||||
|
|
Loading…
Reference in a new issue