Commit graph

55 commits

Author SHA1 Message Date
Damien Elmes
2f27133705 drop sqlalchemy; massive refactor
SQLAlchemy is a great tool, but it wasn't a great fit for Anki:
- We often had to drop down to raw SQL for performance reasons.
- The DB cursors and results were wrapped, which incurred a
  sizable performance hit due to introspection. Operations like fetching 50k
  records from a hot cache were taking more than twice as long to complete.
- We take advantage of sqlite-specific features, so SQL language abstraction
  is useless to us.
- The anki schema is quite small, so manually saving and loading objects is
  not a big burden.

In the process of porting to DBAPI, I've refactored the database schema:
- App configuration data that we don't need in joins or bulk updates has been
  moved into JSON objects. This simplifies serializing, and means we won't
  need DB schema changes to store extra options in the future. This change
  obsoletes the deckVars table.
- Renamed tables:
-- fieldModels -> fields
-- cardModels -> templates
-- fields -> fdata
- a number of attribute names have been shortened

Classes like Card, Fact & Model remain. They maintain a reference to the deck.
To write their state to the DB, call .flush().

Objects no longer have their modification time manually updated. Instead, the
modification time is updated when they are flushed. This also applies to the
deck.

Decks will now save on close, because various operations that were done at
deck load will be moved into deck close instead. Operations like undoing
buried card are cheap on a hot cache, but expensive on startup.
Programmatically you can call .close(save=False) to avoid a save and a
modification bump. This will be useful for generating due counts.

Because of the new saving behaviour, the save and save as options will be
removed from the GUI in the future.

The q/a cache and field cache generating has been centralized. Facts will
automatically rebuild the cache on flush; models can do so with
model.updateCache().

Media handling has also been reworked. It has moved into a MediaRegistry
object, which the deck holds. Refcounting has been dropped - it meant we had
to compare old and new value every time facts or models were changed, and
existed for the sole purpose of not showing errors on a missing media
download. Instead we just media.registerText(q+a) when it's updated. The
download function will be expanded to ask the user if they want to continue
after a certain number of files have failed to download, which should be an
adequate alternative. And we now add the file into the media DB when it's
copied to th emedia directory, not when the card is commited. This fixes
duplicates a user would get if they added the same media to a card twice
without adding the card.

The old DeckStorage object had its upgrade code split in a previous commit;
the opening and upgrading code has been merged back together, and put in a
separate storage.py file. The correct way to open a deck now is import anki; d
= anki.Deck(path).

deck.getCard() -> deck.sched.getCard()
same with answerCard
deck.getCard(id) returns a Card object now.

And the DB wrapper has had a few changes:
- sql statements are a more standard DBAPI:
 - statement() -> execute()
 - statements() -> executemany()
- called like execute(sql, 1, 2, 3) or execute(sql, a=1, b=2, c=3)
- column0 -> list
2011-04-28 09:23:53 +09:00
Damien Elmes
7547b395ea store revlog time in integer MS
using floats for the primary key causes sqlite to generate an extra index,
which is expensive for large histories
2011-04-28 09:23:28 +09:00
Damien Elmes
9aa2f8dc40 refactor cards
Cards had developed quite a lot of cruft from incremental changes, and a
number of important attributes were stored in names that had no bearing to
their actual use.

Added:

- position, which new cards will be sorted on in the future
- flags, which is reserved for future use

Renamed:

- type to queue
- relativeDelay to type
- noCount to lapses

Removed:

- all new/young/matureEase counts; the information is in the revlog
- firstAnswered, lastDue, lastFactor, averageTime and totalTime for the same
  reason
- isDue, spaceUntil and combinedDue, because they are no longer used. Spaced
  cards will be implemented differently in a coming commit.
- priority
- yesCount, because it can be inferred from reps & lapses
- tags; they've been stored in facts for a long time now

Also compatibility with deck versions less than 65 has been dropped, so decks
will need to be upgraded to 1.2 before they can be upgraded by the dev code.
All shared decks are on 1.2, so this should hopefully not be a problem.
2011-04-28 09:23:27 +09:00
Damien Elmes
f828393de3 rename deck.s to a more understable deck.db; keep s for compat 2011-04-28 09:21:07 +09:00
Damien Elmes
b6bb03025f new history table
- rename to revlog
- change the pk to time, as we want an index on time, and the old multi-column
  index was expensive and not useful
- remove yes/no count; they can be inferred from the ease
- remove lastFactor, as it's in the previous entry
- remove delay, it can be inferred from last entry
- remove 'next' from nextInterval and nextFactor
- rename 'thinkingTime' to 'userTime'
- rename reps to rep
- migrate old data to new table, and fix some problems in the process: ease0
  -> ease1, and limit thinking time to 60 seconds as it should have been
  previously
2011-04-28 09:21:07 +09:00
Damien Elmes
855de47ffe remove the stats table
The stats table was how the early non-SQL versions of Anki kept track of
statistics, before there was a revision log. It is being removed because:

- it's not possible to show the statistics for a subset of the deck
- it can't meaningfully be copied on import/export
- it makes it harder to implement sync merging

Implications:

- graphs and deck stats roughly 1.5-3x longer than before, but we'll have the
  ability to generate stats for subsections of the deck, and it's not time
  critical code
- people who've been using anki since the very early days may notice a drop in
  statistics, as early repetitions were recorded in the stats table but the
  revlog didn't exist at that point.
- due bugs in old syncs and imports/exports, the stats and revlog may not
  match numbers exactly

To remove it, the following changes have been made:

- the graphs and deck stats now generate their data entirely from the revlog
- there are no stats to keep track of how many cards we've answered, so we
  pull that information from the revlog in reset()
- we remove _globalStats and _dailyStats from the deck
- we check if a day rollover has occurred using failedCutoff instead
- we remove the getStats() routine
- the ETA code is currently disabled
- timeboxing routines use repsToday instead of stats
- remove stats delete from export
- remove stats table and index in upgrade
- remove stats syncing and globalStats refresh pre-sync
- remove stats count check in fullSync check, which was redundant anyway
- update unit tests

Also:

- newCountToday -> newCount, to bring it in line with revCount&failedCount
  which also reflect the currently due count
- newCount -> newAvail
- timeboxing routines renamed since the old names were confusingly similar to
  refreshSession() which does something different

Todo:

- update newSeenToday & repsToday when answering a card
- reimplement eta
2011-04-28 09:21:07 +09:00
Damien Elmes
9ce60d5e3a remove stats from graphs; use revlog 2011-04-28 09:21:07 +09:00
Damien Elmes
9421a037f6 remove self explanatory module docstrings; strip trailing whitespace 2011-04-28 09:21:07 +09:00
Damien Elmes
b45f071581 option to limit graphs to selective study 2011-01-02 17:36:11 +09:00
Damien Elmes
386de21f87 don't fudge matplotlib path on win32 2010-11-26 21:59:09 +09:00
Damien Elmes
45dfc97e9f add axis labels to graphs
note that due to limitations in the graphing library, these can't be
translated at the moment.
2010-11-24 05:09:00 +09:00
Damien Elmes
33567edb3e numerous graph changes
- use bar graphs instead of line graphs for 3 months or less
- easier to read shades of blue for reps graph
- simplify day cutoff calculation
- fix off by one bug in work done data
- add missing entries when calculating cumulative due
2010-11-24 04:30:55 +09:00
Damien Elmes
aa753d35a5 don't include suspended cards in graphs 2010-11-14 07:37:51 +09:00
Damien Elmes
b69fd48768 more type handling updates; don't munge counts on sync
In various parts of the code we need to get all cards of a given category
(new, failed, etc) regardless of whether they're suspended, buried, etc. So we
store the true type in the obsolete relativeDelay column and add in index for
it, because it's cheaper than putting indices on reps & successive.
2010-11-13 18:39:24 +09:00
Damien Elmes
be4dea39b1 more scheduler updates
- reimplement reviewEarly and newEarly by replacing parts of the scheduler,
  instead of adding special conditions
- remove references to isDue and priority (1,2,3,4) which is not necessary
  anymore
- add option to switch between per-day scheduling and due now scheduling
- newCardsToday() -> newCardsDoneToday()
- don't decrement counts for suspended cards
- make sure to update type when suspending/unsuspending
- fix findCards()
- set hardInterval = 1-1.1 on upgrade, or the default per day scheduling doesn't
  make sense
2010-10-18 18:01:19 +09:00
Damien Elmes
04ba9c9a4e strip elements out of range in review time graph 2010-02-01 07:16:40 +09:00
Damien Elmes
3106ecd80d change location of matplotlibrc file in frozen distrib 2010-02-01 04:44:39 +09:00
Damien Elmes
ebac830248 don't define MATPLOTLIBDATA on osx 2009-09-26 20:54:08 +09:00
Damien Elmes
e687b1d033 don't translate graphs, as agg can't cope 2009-09-26 05:14:16 +09:00
Damien Elmes
a6b4252428 fix graph dividing, make sure to display 'x cards waiting' msg 2009-01-22 23:47:31 +09:00
Damien Elmes
5d2356804e graph review time in hours, not minutes 2009-01-10 13:53:14 +09:00
Damien Elmes
8c6647f1d5 fix graph translations, update polish translations 2009-01-09 12:11:45 +09:00
Damien Elmes
86e3c19ad6 add review time graph 2009-01-05 14:57:28 +09:00
Damien Elmes
8bb063c226 strip some trailing whitespace in graphs 2009-01-05 14:40:22 +09:00
Timo Paulssen
3a2fd8b5ad fixed "unsubscriptable object" when disabling all the graphs before workDone. 2009-01-04 01:26:46 +01:00
Damien Elmes
9e47063940 change graph colours 2008-12-21 00:37:20 +09:00
rageon
dd10c38f78 extracted colour definition and new colour scheme 2008-12-19 00:43:35 +01:00
Timo Paulssen
b665595c0c new, less "urgent" due graph colors. 2008-12-17 12:44:29 +01:00
Timo Paulssen
dabe170bed don't display the "reviews over the lifetime of the deck" 2008-12-16 00:23:10 +01:00
Timo Paulssen
84f953c754 colorscheme v3 (again by rageon, complaints by Damien) 2008-12-14 14:15:35 +01:00
Timo Paulssen
61600f58ed revised colorscheme (thanks again, rageon) 2008-12-14 13:56:19 +01:00
Timo Paulssen
b71aecf626 new colorscheme (thanks, rageon!) 2008-12-14 13:16:30 +01:00
Timo Paulssen
ccfab29fb8 reversed new/young/mature in graphs, this made the graphs so much nicer! 2008-12-14 13:06:41 +01:00
Timo Paulssen
cc08fd402c fixed a silly mistake in the reviews code. 2008-12-13 18:50:05 +01:00
Timo Paulssen
ec401210fd added a legend to the reviews graph. 2008-12-13 18:39:36 +01:00
Timo Paulssen
9c1f76cf57 split "reviews" graph into new, young and mature layers.
next step: add a legend, too.
2008-12-13 18:30:49 +01:00
Damien Elmes
af28484154 various graph fixes
- remove bars, as they are the main cause of slowdowns
- limit cumulative and due only in the future (fixes late decks)
- don't use outlines for periods over 1 year
2008-12-13 18:04:43 +09:00
Timo Paulssen
e7be3e080c sped up graph generation when switching from long intervals to short intervals 2008-12-13 04:11:52 +01:00
Timo Paulssen
d2e23af5e6 making the Figures lazy introduced a bug. fixed it here.
whenever the recently added or first answered graph was the first one to be calculated, it wouldn't have generated the stats yet.
2008-12-13 03:22:42 +01:00
Timo Paulssen
c810ed7254 added necessary import. moved code. made stuff nicer. 2008-12-13 02:32:01 +01:00
Timo Paulssen
7645483fc7 added first code for the work done graph. needs refactoring. 2008-12-13 02:32:01 +01:00
Timo Paulssen
5863453877 fixed: added recently and first answered always displayed 0 for the "first" day shown. 2008-12-10 19:11:42 +01:00
Damien Elmes
82870a9a19 remove labels from graphs, they don't support foreign text 2008-12-10 23:47:51 +09:00
Damien Elmes
89591073de properly set midnight offset, fix graph offset 2008-12-10 23:07:13 +09:00
Damien Elmes
31d96923dc update legends for old matplotlib 2008-12-05 23:43:19 +09:00
Damien Elmes
82c3b83f57 remove obsolete graphs code 2008-12-05 21:43:54 +09:00
Damien Elmes
60fdadd9e8 fix ease graphs for new button layout 2008-12-05 15:15:16 +09:00
Damien Elmes
7463ef570b remove redundant new cards from graphs, rewrite queries 2008-12-05 14:37:31 +09:00
Timo Paulssen
7b2abd7153 added a good-looking legend to the due cards graph.
i feel dirty now.
2008-12-03 22:23:44 +01:00
Timo Paulssen
3a1f6a9274 seperated cards due graph into three layers: new, young and mature. 2008-12-03 22:23:44 +01:00