From 972526d2659c26963bdfd3ca724be838915c866a Mon Sep 17 00:00:00 2001 From: Damien Elmes Date: Wed, 7 Mar 2012 06:58:06 +0900 Subject: [PATCH] update supermemo importer; fix factor --- anki/importing/mnemo.py | 2 +- anki/importing/noteimp.py | 2 +- anki/importing/supermemo_xml.py | 71 ++++++++++++++------------------- tests/test_importing.py | 25 ++++-------- 4 files changed, 41 insertions(+), 59 deletions(-) diff --git a/anki/importing/mnemo.py b/anki/importing/mnemo.py index f44295e7e..8c5de5b9b 100644 --- a/anki/importing/mnemo.py +++ b/anki/importing/mnemo.py @@ -62,7 +62,7 @@ acq_reps+ret_reps, lapses from cards"""): continue # add the card c = ForeignCard() - c.factor = row[5] + c.factor = int(row[5]*1000) c.reps = row[6] c.lapses = row[7] # ivl is inferred in mnemosyne diff --git a/anki/importing/noteimp.py b/anki/importing/noteimp.py index 22c7156eb..6ade752f5 100644 --- a/anki/importing/noteimp.py +++ b/anki/importing/noteimp.py @@ -24,7 +24,7 @@ class ForeignCard(object): def __init__(self): self.due = 0 self.ivl = 1 - self.factor = 2.5 + self.factor = 2500 self.reps = 0 self.lapses = 0 diff --git a/anki/importing/supermemo_xml.py b/anki/importing/supermemo_xml.py index f3c148fa6..3c9f744df 100644 --- a/anki/importing/supermemo_xml.py +++ b/anki/importing/supermemo_xml.py @@ -4,7 +4,8 @@ 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.errors import * @@ -12,10 +13,6 @@ from xml.dom import minidom, Node from types import DictType, InstanceType from string import capwords, maketrans import re, unicodedata, time -#import chardet - - -#from anki import Deck class SmartDict(dict): """ @@ -81,8 +78,12 @@ class SupermemoXmlImporter(NoteImporter): def __init__(self, *args): """Initialize internal varables. 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.numFields=int(2) @@ -110,7 +111,7 @@ class SupermemoXmlImporter(NoteImporter): self.META.tagMemorizedItems = True # implemented self.META.logToStdOutput = False # implemented - self.cards = [] + self.notes = [] ## TOOLS @@ -197,7 +198,7 @@ class SupermemoXmlImporter(NoteImporter): ## DEFAULT IMPORTER METHODS - def foreignCards(self): + def foreignNotes(self): # Load file and parse it by minidom self.loadSource(self.file) @@ -209,7 +210,7 @@ class SupermemoXmlImporter(NoteImporter): self.logger(u'Parsing done.') # Return imported cards - return self.cards + return self.notes def fields(self): return 2 @@ -220,38 +221,28 @@ class SupermemoXmlImporter(NoteImporter): "This method actually do conversion" # new anki card - card = ForeignCard() + note = ForeignNote() # clean Q and A - card.fields.append(self._fudgeText(self._decode_htmlescapes(item.Question))) - card.fields.append(self._fudgeText(self._decode_htmlescapes(item.Answer))) - card.tags = u"" + note.fields.append(self._fudgeText(self._decode_htmlescapes(item.Question))) + note.fields.append(self._fudgeText(self._decode_htmlescapes(item.Answer))) + note.tags = [] # pre-process scheduling data - tLastrep = time.mktime(time.strptime(item.LastRepetition, '%d.%m.%Y')) - tToday = time.time() - # convert learning data - if not self.META.resetLearningData: + if not self.META.resetLearningData and item.Interval >= 1: # migration of LearningData algorithm - card.interval = item.Interval - card.successive = item.Repetitions - ##card.due = tToday + (float(item.Interval) * 86400.0) - tLastrep - card.due = tLastrep + (float(item.Interval) * 86400.0) - card.lastDue = 0 - - card.factor = float(item.AFactor.replace(',','.')) - card.lastFactor = float(item.AFactor.replace(',','.')) - - # SM is not exporting all the information Anki keeps track off, so it - # needs to be fudged - 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 + tLastrep = time.mktime(time.strptime(item.LastRepetition, '%d.%m.%Y')) + tToday = time.time() + card = ForeignCard() + card.ivl = int(item.Interval) + card.lapses = int(item.Lapses) + card.reps = int(item.Repetitions) + int(item.Lapses) + nextDue = tLastrep + (float(item.Interval) * 86400.0) + remDays = max(0, int((nextDue - time.time())/86400)) + card.due = self.col.sched.today+remDays + card.factor = int(float(item.AFactor.replace(',','.'))*1000) + note.cards[0] = card # categories & tags # 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 ])) 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: - 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): "Wrapper for Anki logger" @@ -323,7 +314,7 @@ class SupermemoXmlImporter(NoteImporter): """Load source file and parse with xml.dom.minidom""" self.source = source self.logger(u'Load started...') - sock = self.openAnything(self.source) + sock = open(self.source) self.xmldoc = minidom.parse(sock).documentElement sock.close() self.logger(u'Load done.') diff --git a/tests/test_importing.py b/tests/test_importing.py index a36202f1b..a175b6b06 100644 --- a/tests/test_importing.py +++ b/tests/test_importing.py @@ -96,27 +96,17 @@ def test_csv(): assert i.total == 0 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(): - print "disabled"; return - deck = Deck() - deck.addModel(BasicModel()) - file = unicode(os.path.join(testDir, "importing/supermemo1.xml")) - i = supermemo_xml.SupermemoXmlImporter(deck, file) + deck = getEmptyDeck() + file = unicode(os.path.join(testDir, "support/supermemo1.xml")) + i = SupermemoXmlImporter(deck, file) #i.META.logToStdOutput = True i.run() - # only returning top-level elements? 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() def test_mnemo(): @@ -127,3 +117,4 @@ def test_mnemo(): assert deck.cardCount() == 7 assert "a_longer_tag" in deck.tags.all() assert deck.db.scalar("select count() from cards where type = 0") == 1 + deck.close()