update supermemo importer; fix factor

This commit is contained in:
Damien Elmes 2012-03-07 06:58:06 +09:00
parent beef571d95
commit 972526d265
4 changed files with 41 additions and 59 deletions

View file

@ -62,7 +62,7 @@ acq_reps+ret_reps, lapses from cards"""):
continue continue
# add the card # add the card
c = ForeignCard() c = ForeignCard()
c.factor = row[5] c.factor = int(row[5]*1000)
c.reps = row[6] c.reps = row[6]
c.lapses = row[7] c.lapses = row[7]
# ivl is inferred in mnemosyne # ivl is inferred in mnemosyne

View file

@ -24,7 +24,7 @@ class ForeignCard(object):
def __init__(self): def __init__(self):
self.due = 0 self.due = 0
self.ivl = 1 self.ivl = 1
self.factor = 2.5 self.factor = 2500
self.reps = 0 self.reps = 0
self.lapses = 0 self.lapses = 0

View file

@ -4,7 +4,8 @@
import sys import sys
from anki.importing.noteimp import NoteImporter, ForeignNote from anki.stdmodels import addBasicModel
from anki.importing.noteimp import NoteImporter, ForeignNote, ForeignCard
from anki.lang import _ from anki.lang import _
from anki.errors import * from anki.errors import *
@ -12,10 +13,6 @@ from xml.dom import minidom, Node
from types import DictType, InstanceType from types import DictType, InstanceType
from string import capwords, maketrans from string import capwords, maketrans
import re, unicodedata, time import re, unicodedata, time
#import chardet
#from anki import Deck
class SmartDict(dict): class SmartDict(dict):
""" """
@ -81,8 +78,12 @@ class SupermemoXmlImporter(NoteImporter):
def __init__(self, *args): def __init__(self, *args):
"""Initialize internal varables. """Initialize internal varables.
Pameters to be exposed to GUI are stored in self.META""" Pameters to be exposed to GUI are stored in self.META"""
NoteImporter.__init__(self, *args)
m = addBasicModel(self.col)
m['name'] = "Supermemo"
self.col.models.save(m)
self.initMapping()
Importer.__init__(self, *args)
self.lines = None self.lines = None
self.numFields=int(2) self.numFields=int(2)
@ -110,7 +111,7 @@ class SupermemoXmlImporter(NoteImporter):
self.META.tagMemorizedItems = True # implemented self.META.tagMemorizedItems = True # implemented
self.META.logToStdOutput = False # implemented self.META.logToStdOutput = False # implemented
self.cards = [] self.notes = []
## TOOLS ## TOOLS
@ -197,7 +198,7 @@ class SupermemoXmlImporter(NoteImporter):
## DEFAULT IMPORTER METHODS ## DEFAULT IMPORTER METHODS
def foreignCards(self): def foreignNotes(self):
# Load file and parse it by minidom # Load file and parse it by minidom
self.loadSource(self.file) self.loadSource(self.file)
@ -209,7 +210,7 @@ class SupermemoXmlImporter(NoteImporter):
self.logger(u'Parsing done.') self.logger(u'Parsing done.')
# Return imported cards # Return imported cards
return self.cards return self.notes
def fields(self): def fields(self):
return 2 return 2
@ -220,38 +221,28 @@ class SupermemoXmlImporter(NoteImporter):
"This method actually do conversion" "This method actually do conversion"
# new anki card # new anki card
card = ForeignCard() note = ForeignNote()
# clean Q and A # clean Q and A
card.fields.append(self._fudgeText(self._decode_htmlescapes(item.Question))) note.fields.append(self._fudgeText(self._decode_htmlescapes(item.Question)))
card.fields.append(self._fudgeText(self._decode_htmlescapes(item.Answer))) note.fields.append(self._fudgeText(self._decode_htmlescapes(item.Answer)))
card.tags = u"" note.tags = []
# pre-process scheduling data # pre-process scheduling data
tLastrep = time.mktime(time.strptime(item.LastRepetition, '%d.%m.%Y'))
tToday = time.time()
# convert learning data # convert learning data
if not self.META.resetLearningData: if not self.META.resetLearningData and item.Interval >= 1:
# migration of LearningData algorithm # migration of LearningData algorithm
card.interval = item.Interval tLastrep = time.mktime(time.strptime(item.LastRepetition, '%d.%m.%Y'))
card.successive = item.Repetitions tToday = time.time()
##card.due = tToday + (float(item.Interval) * 86400.0) - tLastrep card = ForeignCard()
card.due = tLastrep + (float(item.Interval) * 86400.0) card.ivl = int(item.Interval)
card.lastDue = 0 card.lapses = int(item.Lapses)
card.reps = int(item.Repetitions) + int(item.Lapses)
card.factor = float(item.AFactor.replace(',','.')) nextDue = tLastrep + (float(item.Interval) * 86400.0)
card.lastFactor = float(item.AFactor.replace(',','.')) remDays = max(0, int((nextDue - time.time())/86400))
card.due = self.col.sched.today+remDays
# SM is not exporting all the information Anki keeps track off, so it card.factor = int(float(item.AFactor.replace(',','.'))*1000)
# needs to be fudged note.cards[0] = card
card.youngEase0 = item.Lapses
card.youngEase3 = item.Repetitions + item.Lapses
card.yesCount = item.Repetitions
card.noCount = item.Lapses
card.reps = card.yesCount + card.noCount
card.spaceUntil = card.due
card.combinedDue = card.due
# categories & tags # categories & tags
# it's worth to have every theme (tree structure of sm collection) stored in tags, but sometimes not # it's worth to have every theme (tree structure of sm collection) stored in tags, but sometimes not
@ -275,14 +266,14 @@ class SupermemoXmlImporter(NoteImporter):
tmp = list(set([ capwords(i).replace(' ','') for i in tmp ])) tmp = list(set([ capwords(i).replace(' ','') for i in tmp ]))
tags = [ j[0].lower() + j[1:] for j in tmp if j.strip() <> ''] tags = [ j[0].lower() + j[1:] for j in tmp if j.strip() <> '']
card.tags += u" ".join(tags) note.tags += tags
if self.META.tagMemorizedItems and item.Interval >0: if self.META.tagMemorizedItems and item.Interval >0:
card.tags += " Memorized" note.tags.append("Memorized")
self.logger(u'Element tags\t- ' + card.tags, level=3) self.logger(u'Element tags\t- ' + `note.tags`, level=3)
self.cards.append(card) self.notes.append(note)
def logger(self,text,level=1): def logger(self,text,level=1):
"Wrapper for Anki logger" "Wrapper for Anki logger"
@ -323,7 +314,7 @@ class SupermemoXmlImporter(NoteImporter):
"""Load source file and parse with xml.dom.minidom""" """Load source file and parse with xml.dom.minidom"""
self.source = source self.source = source
self.logger(u'Load started...') self.logger(u'Load started...')
sock = self.openAnything(self.source) sock = open(self.source)
self.xmldoc = minidom.parse(sock).documentElement self.xmldoc = minidom.parse(sock).documentElement
sock.close() sock.close()
self.logger(u'Load done.') self.logger(u'Load done.')

View file

@ -96,27 +96,17 @@ def test_csv():
assert i.total == 0 assert i.total == 0
deck.close() deck.close()
def test_csv_tags():
print "disabled"; return
deck = getEmptyDeck()
file = unicode(os.path.join(testDir, "support/text-tags.txt"))
i = TextImporter(deck, file)
i.run()
notes = deck.db.query(Note).all()
assert len(notes) == 2
assert notes[0].tags == "baz qux" or notes[1].tags == "baz qux"
deck.close()
def test_supermemo_xml_01_unicode(): def test_supermemo_xml_01_unicode():
print "disabled"; return deck = getEmptyDeck()
deck = Deck() file = unicode(os.path.join(testDir, "support/supermemo1.xml"))
deck.addModel(BasicModel()) i = SupermemoXmlImporter(deck, file)
file = unicode(os.path.join(testDir, "importing/supermemo1.xml"))
i = supermemo_xml.SupermemoXmlImporter(deck, file)
#i.META.logToStdOutput = True #i.META.logToStdOutput = True
i.run() i.run()
# only returning top-level elements?
assert i.total == 1 assert i.total == 1
cid = deck.db.scalar("select id from cards")
c = deck.getCard(cid)
assert c.factor == 5701
assert c.reps == 7
deck.close() deck.close()
def test_mnemo(): def test_mnemo():
@ -127,3 +117,4 @@ def test_mnemo():
assert deck.cardCount() == 7 assert deck.cardCount() == 7
assert "a_longer_tag" in deck.tags.all() assert "a_longer_tag" in deck.tags.all()
assert deck.db.scalar("select count() from cards where type = 0") == 1 assert deck.db.scalar("select count() from cards where type = 0") == 1
deck.close()