예제 #1
0
def JapaneseModel():
    m = Model(_("Japanese"))
    # expression
    f = FieldModel(u'Expression', True, True)
    font = u"Mincho"
    f.quizFontSize = 50
    f.quizFontFamily = font
    f.editFontFamily = font
    m.addFieldModel(f)
    # meaning
    m.addFieldModel(FieldModel(u'Meaning', False, False))
    # reading
    f = FieldModel(u'Reading', False, False)
    font = u"Arial"
    f.quizFontSize = 50
    f.quizFontFamily = font
    f.editFontFamily = font
    m.addFieldModel(f)
    m.addCardModel(CardModel(u"Recognition",
                   u"%(Expression)s",
                   u"%(Reading)s<br>%(Meaning)s"))
    m.addCardModel(CardModel(u"Recall",
                             u"%(Meaning)s",
                             u"%(Reading)s",
                             active=False))
    m.tags = u"Japanese"
    return m
예제 #2
0
 def createModel(self, modelName, production, listening, reading):
     model = Model(modelName)
     model.addFieldModel(FieldModel(u'Expression', True, False))
     model.addFieldModel(FieldModel(u'Meaning', True, False))
     model.addFieldModel(FieldModel(u'Reading', False, False))
     model.addFieldModel(FieldModel(u'Audio', False, False))
     model.addFieldModel(FieldModel(u'Image_URI', False, False))
     model.addFieldModel(FieldModel(u'iKnowID', True, True))
     model.addFieldModel(FieldModel(u'iKnowType', False, False))
     if listening:
         model.addCardModel(CardModel(
             u'Listening',
             u'Listen.%(Audio)s',
             u'%(Expression)s<br>%(Reading)s<br>%(Meaning)s'))
     if production:
         model.addCardModel(CardModel(
             u'Production',
             u'%(Meaning)s<br>%(Image_URI)s',
             u'%(Expression)s<br>%(Reading)s<br>%(Audio)s'))
     if reading:
         model.addCardModel(CardModel(
             u'Reading',
             u'%(Expression)s',
             u'%(Reading)s<br>%(Meaning)s<br>%(Audio)s'))
     mw.deck.addModel(model)
예제 #3
0
def BasicModel():
    m = Model(_('Basic'))
    m.addFieldModel(FieldModel(u'Front', True, True))
    m.addFieldModel(FieldModel(u'Back', False, False))
    m.addCardModel(CardModel(u'Forward', u'%(Front)s', u'%(Back)s'))
    m.addCardModel(CardModel(u'Reverse', u'%(Back)s', u'%(Front)s',
                             active=False))
    m.tags = u"Basic"
    return m
예제 #4
0
def test_modelChange():
    deck = DeckStorage.Deck()
    m = Model(u"Japanese")
    m1 = m
    f = FieldModel(u'Expression', True, True)
    m.addFieldModel(f)
    m.addFieldModel(FieldModel(u'Meaning', False, False))
    f = FieldModel(u'Reading', False, False)
    m.addFieldModel(f)
    m.addCardModel(
        CardModel(u"Recognition", u"%(Expression)s",
                  u"%(Reading)s<br>%(Meaning)s"))
    m.addCardModel(
        CardModel(u"Recall",
                  u"%(Meaning)s",
                  u"%(Expression)s<br>%(Reading)s",
                  active=False))
    m.tags = u"Japanese"
    m1.cardModels[1].active = True
    deck.addModel(m1)
    f = deck.newFact()
    f['Expression'] = u'e'
    f['Meaning'] = u'm'
    f['Reading'] = u'r'
    f = deck.addFact(f)
    f2 = deck.newFact()
    f2['Expression'] = u'e2'
    f2['Meaning'] = u'm2'
    f2['Reading'] = u'r2'
    deck.addFact(f2)
    m2 = BasicModel()
    m2.cardModels[1].active = True
    deck.addModel(m2)
    # convert to basic
    assert deck.modelUseCount(m1) == 2
    assert deck.modelUseCount(m2) == 0
    assert deck.cardCount == 4
    assert deck.factCount == 2
    fmap = {
        m1.fieldModels[0]: m2.fieldModels[0],
        m1.fieldModels[1]: None,
        m1.fieldModels[2]: m2.fieldModels[1]
    }
    cmap = {m1.cardModels[0]: m2.cardModels[0], m1.cardModels[1]: None}
    deck.changeModel([f.id], m2, fmap, cmap)
    assert deck.modelUseCount(m1) == 1
    assert deck.modelUseCount(m2) == 1
    assert deck.cardCount == 3
    assert deck.factCount == 2
    (q, a) = deck.s.first("""
select question, answer from cards where factId = :id""",
                          id=f.id)
    assert stripHTML(q) == u"e"
    assert stripHTML(a) == u"r"
예제 #5
0
파일: model.py 프로젝트: fqhuy/JpEnVi_Anki
def JpEnViModel():
    m = Model(_("JpEnVi"))
    # expression
    f = FieldModel(u'Japanese', True, True)
    font = u"Mincho"
    f.quizFontSize = 50
    f.quizFontFamily = font
    f.editFontFamily = font
    m.addFieldModel(f)
    # meaning
    f = FieldModel(u'English', False, False)
    font = u"Mincho"
    f.quizFontSize = 20
    f.quizFontFamily = font
    f.editFontFamily = font
    m.addFieldModel(f)
    # reading
    f = FieldModel(u'Sino-Vietnamese', False, False)  #for Kanji only (?)
    font = u"Arial"
    f.quizFontSize = 20
    f.quizFontFamily = font
    f.editFontFamily = font
    m.addFieldModel(f)
    #vietnamese
    f = FieldModel(u'Vietnamese', False, False)
    font = u"Mincho"
    f.quizFontSize = 20
    f.quizFontFamily = font
    f.editFontFamily = font
    m.addFieldModel(f)

    f = FieldModel(u'Example', False, False)
    font = u"Mincho"
    f.quizFontSize = 20
    f.quizFontFamily = font
    f.editFontFamily = font
    m.addFieldModel(f)

    m.addCardModel(
        CardModel(
            u"Recognition", u"%(Japanese)s",
            u"<div align='left'>English</div><hr> <br> %(English)s <div align='left'>Sino-Vietnamese</div><hr><br>%(Sino-Vietnamese)s <div align='left'>Vietnamese</div><hr><br>%(Vietnamese)s <div align='left'>Examples from tratu.vn</div><hr><br>%(Example)s"
        ))
    m.addCardModel(
        CardModel(u"Recall", u"%(Vietnamese)s", u"%(Japanese)s", active=False))

    m.tags = u"JpEnVi, JpEnVi_offline"
    return m
예제 #6
0
def RecoveryModel():
    m = Model(_('Recovery'))
    m.addFieldModel(FieldModel(u'Question', False, False))
    m.addFieldModel(FieldModel(u'Answer', False, False))
    m.addCardModel(CardModel(u'Single', u'{{{Question}}}', u'{{{Answer}}}'))
    m.tags = u"Recovery"
    return m
예제 #7
0
 def getCardModel(self, model, remote):
     for cm in model.cardModels:
         if cm.id == remote['id']:
             return cm
     cm = CardModel()
     model.addCardModel(cm)
     return cm
예제 #8
0
 def MandarinModel():
    m = Model(_("Mandarin"))
    f = FieldModel(u'Expression')
    f.quizFontSize = 72
    m.addFieldModel(f)
    m.addFieldModel(FieldModel(u'Meaning', False, False))
    m.addFieldModel(FieldModel(u'Reading', False, False))
    m.addCardModel(CardModel(u"Recognition",
                             u"%(Expression)s",
                             u"%(Reading)s<br>%(Meaning)s"))
    m.addCardModel(CardModel(u"Recall",
                             u"%(Meaning)s",
                             u"%(Expression)s<br>%(Reading)s",
                             active=False))
    m.tags = u"Mandarin"
    return m
def doImport():
    # add an iknow model
    if not [m for m in mw.deck.models if m.name == 'Smart.fm']:
        m = Model(u'Smart.fm')
        m.addFieldModel(FieldModel(u'Expression', False, False))
        m.addFieldModel(FieldModel(u'Meaning', False, False))
        m.addFieldModel(FieldModel(u'Reading', False, False))
        m.addFieldModel(FieldModel(u'Audio', False, False))
        m.addFieldModel(FieldModel(u'Image', False, False))
        m.addCardModel(CardModel(
            u'Listening',
            u'Listen.%(Audio)s',
            u'%(Expression)s<br>%(Reading)s<br>%(Meaning)s<br>%(Image)s'))
        mw.deck.addModel(m)
    while 1:
        mw.reset()
        url = getOnlyText("Enter list URL:")
        if not url:
            return
        id = re.search("/lists/(\d+)", url).group(1)
        # get sentences
        f = urllib2.urlopen(
            "http://api.smart.fm/lists/%s/sentences.json" % id)
        d = simplejson.load(f)
        # add facts
        diag = QProgressDialog(_("Importing..."), "", 0, 0, mw)
        diag.setCancelButton(None)
        diag.setMaximum(len(d))
        diag.setMinimumDuration(0)
        for i, sen in enumerate(d):
            diag.setValue(i)
            diag.setLabelText(sen['text'])
            mw.app.processEvents()
            f = mw.deck.newFact()
            f['Expression'] = sen['text']
            f['Meaning'] = sen['translations'] and sen['translations'][0]['text'] or u""
            try:
                f['Reading'] = sen['transliterations']['Hrkt'] or u""
                # reading is sometimes missing
                if not f['Reading'] and kakasi:
                    f['Reading'] = kakasi.toFurigana(f['Expression'])
            except KeyError:
                f['Reading'] = u""
            if includeSounds and sen['sound']:
                (file, headers) = urllib.urlretrieve(sen['sound'])
                path = mw.deck.addMedia(file)
                f['Audio'] = u'[sound:%s]' % path
            else:
                f['Audio'] = u""
            if includeImages and sen['image']:
                (file, headers) = urllib.urlretrieve(sen['image'])
                path = mw.deck.addMedia(file)
                f['Image'] = u'<img src="%s">' % path
            else:
                f['Image'] = u""
            mw.deck.addFact(f)
        diag.cancel()
        mw.deck.save()
예제 #10
0
    def createModel(self, attrs):
        """Makes a new Anki (fact) model from an entry type.
        The card models are made each time from scratch in order that evt. model specific fields (attributes) can make part."""
        m = Model(attrs["n"])
        # field model for standard fields
        m.addFieldModel(
            FieldModel(self.labels["b"], True,
                       False))  #there is no uniqueness check in DingsBums?!
        m.addFieldModel(FieldModel(self.labels["t"], True, False))
        for aField in ["exp", "ex", "pro", "rel"]:
            if self.visibility[aField] in "012":
                m.addFieldModel(FieldModel(self.labels[aField], False, False))
        # field models for attributes
        for attr in ["a1", "a2" "a3", "a4"]:
            if attr in attrs.keys():
                m.addFieldModel(
                    FieldModel(self.attributes[attrs[attr]], False, False))
                self.typeAttributes[attrs["eid"] + "_" +
                                    attr] = self.attributes[attrs[attr]]

        # card model for front
        frontStrings = ["%(" + self.labels["b"] + ")s"]
        backStrings = ["%(" + self.labels["t"] + ")s"]
        for aField in ["exp", "ex", "pro", "rel"]:
            if self.visibility[aField] in "01":
                frontStrings.append("%(" + self.labels[aField] + ")s")
            if self.visibility[aField] in "02":
                backStrings.append("%(" + self.labels[aField] + ")s")
        m.addCardModel(
            CardModel(u'Forward', "<br>".join(frontStrings),
                      "<br>".join(backStrings)))
        # card model for back
        m.addCardModel(
            CardModel(u'Reverse', unicode("%(" + self.labels["t"] + ")s"),
                      unicode("%(" + self.labels["b"] + ")s")))
        # tags is just the name without spaces
        m.tags = self.prepareTag(m.name)

        # link
        self.models[attrs["eid"]] = m
        self.deck.addModel(m)
예제 #11
0
 def addCard(self):
     cards = len(self.m.cardModels)
     name = _("Template_%d") % (cards + 1)
     fields = self.m.fieldModels
     qformat = "{{%s}}" % fields[0].name
     if len(fields) > 1:
         aformat = "{{%s}}" % fields[1].name
     else:
         aformat = ""
     cm = CardModel(name, qformat, aformat)
     self.m.addCardModel(cm)
     self.updateCards()
     self.dialog.cardList.setCurrentRow(len(self.m.cardModels) - 1)
예제 #12
0
def VocabModel():
    m = Model(_("Vocab"))
    m.addFieldModel(FieldModel(u'Expression', True, False))
    m.addFieldModel(FieldModel(u'Reading', False, False))
    m.addFieldModel(FieldModel(u'Meaning', False, False))
    m.addFieldModel(FieldModel(u'From', False, False))
    
    m.addCardModel(CardModel(u"Recognition",
                             #Question side
                             u"%(Expression)s",
                             #Answer side
                             u"%(Reading)s<br>"+
                             u"%(Meaning)s<br>"+
                             u"%(From)s"))
    
    m.tags = u"Japanese Vocab Vocabulary"
    return m
예제 #13
0
 def ensureKanjiModelExists(self):
     model = None
     for m in mw.deck.models:
         if m.name.lower() == RTKImportDialog.KANJI_MODEL.lower():
             return m
     if not model:
         model = Model(RTKImportDialog.KANJI_MODEL)
         model.addFieldModel(FieldModel(u'Kanji', True, True))
         model.addFieldModel(FieldModel(u'HeisigFrameID', True, True))
         model.addFieldModel(FieldModel(u'Keyword', True, True))
         model.addFieldModel(FieldModel(u'Story', True, True))
         model.addFieldModel(FieldModel(u'PrimitiveMeanings', False, False))
         model.addFieldModel(
             FieldModel(u'Image_StrokeOrderDiagram', False, False))
         model.addFieldModel(
             FieldModel(u'Image_StrokeOrderAnimation', False, False))
         model.addCardModel(
             CardModel(
                 u'Remembering', u'%(Keyword)s',
                 u'%(Kanji)s<br>%(Story)s<br>%(PrimitiveMeanings)s<br>%(Image_StrokeOrderAnimation)s<br>%(Image_StrokeOrderDiagram)s'
             ))
         mw.deck.addModel(model)
     return model
예제 #14
0
def addPassword():
	""" Model's not there? Fix it before we get into worse trouble. """
	if not [m for m in mw.deck.models if m.name == MODEL]:
		m = Model(unicode(MODEL))
		m.addFieldModel(FieldModel(u'Description', True, True))
		m.addFieldModel(FieldModel(u'HMAC_%s' % HASH, True, True))
		m.addFieldModel(FieldModel(u'GPG', True, True))
		cm=CardModel(u'Password',u'%(Description)s',u'%%(HMAC_%s)s' % HASH)
		cm.typeAnswer = u'HMAC_%s' % HASH
		m.addCardModel(cm)
		mw.deck.addModel(m)
	else:
		m, = [m for m in mw.deck.models if m.name == MODEL]
		# Monkey patch existing models
		if 'HMAC_%s' % HASH not in [ a.name for a in m.fieldModels ]:
			m.addFieldModel(FieldModel(u'HMAC_%s' % HASH, True, True))

	ret = QInputDialog.getText(mw, "Description", "Enter a description for the password")
	if ret[1]:
		desc = unicode(ret[0])
	else:
		return

	ret = QInputDialog.getText(mw, "Password", "Enter the password", QLineEdit.Password)
	if ret[1]:
		pass1 = unicode(ret[0])
	else:
		return

	ret = QInputDialog.getText(mw, "Confirm", "Confirm the password", QLineEdit.Password)
	if ret[1]:
		pass2 = unicode(ret[0])
	else:
		return

	if pass1 != pass2:
		QMessageBox.information(mw, "Mismatch", "Your passwords didn't match")
		return

	""" Attempt to add the card. """
	try:
		fact = mw.deck.newFact()

		fact['Description'] = desc

		""" Fill in the MAC """
		mac = hmac.new(config.key, pass1.encode('utf-8'), getattr(hashlib, HASH))
		fact['HMAC_%s' % HASH] = unicode(mac.hexdigest())

		""" PyMe setup """
		c = Context();
		c.set_armor(1);
		c.op_keylist_start(GPG_USER_NAME, 0)
		key = c.op_keylist_next()

		if not key:
			QMessageBox.information(mw, "Error", "Could not find your key. Check you've set it up in the plugin file.")
			return

		print "Encrypting with key: " + key.uids[0].uid

		""" Do the encryption, or try to """
		plain = Data(pass1.encode('utf-8'))
		cipher = Data()
		try:
			c.op_encrypt([key], 1, plain, cipher)
			cipher.seek(0,0)
			fact['GPG'] = unicode(re.sub("\n","<br>",cipher.read()), 'ascii')
			mw.deck.addFact(fact)
		except GPGMEError, e:
			QMessageBox.information(mw, "Error", "Could not encrypt your password.\nError: " + str(e))

	except FactInvalidError, e:
		QMessageBox.information(mw, "Error", "Could not store your password.\nError: " + str(e))
예제 #15
0
 def doImport(self):
     oldDeck = load(self.file)
     maybeUpgrade(oldDeck)
     # mappings for old->new ids
     cardModels = {}
     fieldModels = {}
     # start with the models
     s = self.deck.s
     deck = self.deck
     import types
     def uni(txt):
         if txt is None:
             return txt
         if not isinstance(txt, types.UnicodeType):
             txt = unicode(txt, "utf-8")
         return txt
     for oldModel in oldDeck.facts.models:
         model = Model(uni(oldModel.name), uni(oldModel.description))
         model.id = oldModel.id
         model.tags = u", ".join(oldModel.tags)
         model.features = u", ".join(oldModel.decorators)
         model.created = oldModel.created
         model.modified = oldModel.modified
         deck.newCardOrder = min(1, oldModel.position)
         deck.addModel(model)
         # fields
         for oldField in oldModel.fields:
             fieldModel = FieldModel(uni(oldField.name),
                                     uni(oldField.description),
                                     oldField.name in oldModel.required,
                                     oldField.name in oldModel.unique)
             fieldModel.features = u", ".join(oldField.features)
             fieldModel.quizFontFamily = uni(oldField.display['quiz']['fontFamily'])
             fieldModel.quizFontSize = oldField.display['quiz']['fontSize']
             fieldModel.quizFontColour = uni(oldField.display['quiz']['fontColour'])
             fieldModel.editFontFamily = uni(oldField.display['edit']['fontFamily'])
             fieldModel.editFontSize = oldField.display['edit']['fontSize']
             fieldModel.id = oldField.id
             model.addFieldModel(fieldModel)
             s.flush() # we need the id
             fieldModels[id(oldField)] = fieldModel
         # card models
         for oldCard in oldModel.allcards:
             cardModel = CardModel(uni(oldCard.name),
                                   uni(oldCard.description),
                                   uni(oldCard.qformat),
                                   uni(oldCard.aformat))
             cardModel.active = oldCard in oldModel.cards
             cardModel.questionInAnswer = oldCard.questionInAnswer
             cardModel.id = oldCard.id
             model.spacing = 0.25
             cardModel.questionFontFamily = uni(oldCard.display['question']['fontFamily'])
             cardModel.questionFontSize = oldCard.display['question']['fontSize']
             cardModel.questionFontColour = uni(oldCard.display['question']['fontColour'])
             cardModel.questionAlign = oldCard.display['question']['align']
             cardModel.answerFontFamily = uni(oldCard.display['answer']['fontFamily'])
             cardModel.answerFontSize = oldCard.display['answer']['fontSize']
             cardModel.answerFontColour = uni(oldCard.display['answer']['fontColour'])
             cardModel.answerAlign = oldCard.display['answer']['align']
             cardModel.lastFontFamily = uni(oldCard.display['last']['fontFamily'])
             cardModel.lastFontSize = oldCard.display['last']['fontSize']
             cardModel.lastFontColour = uni(oldCard.display['last']['fontColour'])
             cardModel.editQuestionFontFamily = (
                 uni(oldCard.display['editQuestion']['fontFamily']))
             cardModel.editQuestionFontSize = (
                 oldCard.display['editQuestion']['fontSize'])
             cardModel.editAnswerFontFamily = (
                 uni(oldCard.display['editAnswer']['fontFamily']))
             cardModel.editAnswerFontSize = (
                 oldCard.display['editAnswer']['fontSize'])
             model.addCardModel(cardModel)
             s.flush() # we need the id
             cardModels[id(oldCard)] = cardModel
     # facts
     def getSpace(lastCard, lastAnswered):
         if not lastCard:
             return 0
         return lastAnswered + lastCard.delay
     def getLastCardId(fact):
         if not fact.lastCard:
             return None
         ret = [c.id for c in fact.cards if c.model.id == fact.lastCard.id]
         if ret:
             return ret[0]
     d = [{'id': f.id,
           'modelId': f.model.id,
           'created': f.created,
           'modified': f.modified,
           'tags': u",".join(f.tags),
           'spaceUntil': getSpace(f.lastCard, f.lastAnswered),
           'lastCardId': getLastCardId(f)
           } for f in oldDeck.facts]
     if d:
         s.execute(factsTable.insert(), d)
     self.total = len(oldDeck.facts)
     # fields in facts
     toAdd = []
     for oldFact in oldDeck.facts:
         for field in oldFact.model.fields:
             toAdd.append({'factId': oldFact.id,
                           'id': genID(),
                           'fieldModelId': fieldModels[id(field)].id,
                           'ordinal': fieldModels[id(field)].ordinal,
                           'value': uni(oldFact.get(field.name, u""))})
     if toAdd:
         s.execute(fieldsTable.insert(), toAdd)
     # cards
     class FakeObj(object):
         pass
     fake = FakeObj()
     fake.fact = FakeObj()
     fake.fact.model = FakeObj()
     fake.cardModel = FakeObj()
     def renderQA(c, type):
         fake.tags = u", ".join(c.tags)
         fake.fact.tags = u", ".join(c.fact.tags)
         fake.fact.model.tags = u", ".join(c.fact.model.tags)
         fake.cardModel.name = c.model.name
         return cardModels[id(c.model)].renderQA(fake, c.fact, type)
     d = [{'id': c.id,
           'created': c.created,
           'modified': c.modified,
           'factId': c.fact.id,
           'ordinal': cardModels[id(c.model)].ordinal,
           'cardModelId': cardModels[id(c.model)].id,
           'tags': u", ".join(c.tags),
           'factor': 2.5,
           'firstAnswered': c.firstAnswered,
           'interval': c.interval,
           'lastInterval': c.lastInterval,
           'modified': c.modified,
           'due': c.nextTime,
           'lastDue': c.lastTime,
           'reps': c.total,
           'question': renderQA(c, 'question'),
           'answer': renderQA(c, 'answer'),
           'averageTime': c.stats['averageTime'],
           'reviewTime': c.stats['totalTime'],
           'yesCount': (c.stats['new']['yes'] +
                        c.stats['young']['yes'] +
                        c.stats['old']['yes']),
           'noCount': (c.stats['new']['no'] +
                       c.stats['young']['no'] +
                       c.stats['old']['no']),
           'successive': c.stats['successivelyCorrect']}
          for c in oldDeck]
     if d:
         s.execute(cardsTable.insert(), d)
     # scheduler
     deck.description = uni(oldDeck.description)
     deck.created = oldDeck.created
     deck.maxScheduleTime = oldDeck.sched.maxScheduleTime
     deck.hardIntervalMin = oldDeck.sched.hardInterval[0]
     deck.hardIntervalMax = oldDeck.sched.hardInterval[1]
     deck.midIntervalMin = oldDeck.sched.midInterval[0]
     deck.midIntervalMax = oldDeck.sched.midInterval[1]
     deck.easyIntervalMin = oldDeck.sched.easyInterval[0]
     deck.easyIntervalMax = oldDeck.sched.easyInterval[1]
     deck.delay0 = oldDeck.sched.delay0
     deck.delay1 = oldDeck.sched.delay1
     deck.delay2 = oldDeck.sched.delay2
     deck.collapseTime = 3600 # oldDeck.sched.collapse
     deck.highPriority = u", ".join(oldDeck.sched.highPriority)
     deck.medPriority = u", ".join(oldDeck.sched.medPriority)
     deck.lowPriority = u", ".join(oldDeck.sched.lowPriority)
     deck.suspended = u", ".join(oldDeck.sched.suspendedTags)
     # scheduler global stats
     stats = Stats(STATS_LIFE)
     stats.day = datetime.date.fromtimestamp(oldDeck.created)
     stats.averageTime = oldDeck.sched.globalStats['averageTime']
     stats.reviewTime = oldDeck.sched.globalStats['totalTime']
     stats.distractedTime = 0
     stats.distractedReps = 0
     stats.newEase0 = oldDeck.sched.easeStats.get('new', {}).get(0, 0)
     stats.newEase1 = oldDeck.sched.easeStats.get('new', {}).get(1, 0)
     stats.newEase2 = oldDeck.sched.easeStats.get('new', {}).get(2, 0)
     stats.newEase3 = oldDeck.sched.easeStats.get('new', {}).get(3, 0)
     stats.newEase4 = oldDeck.sched.easeStats.get('new', {}).get(4, 0)
     stats.youngEase0 = oldDeck.sched.easeStats.get('young', {}).get(0, 0)
     stats.youngEase1 = oldDeck.sched.easeStats.get('young', {}).get(1, 0)
     stats.youngEase2 = oldDeck.sched.easeStats.get('young', {}).get(2, 0)
     stats.youngEase3 = oldDeck.sched.easeStats.get('young', {}).get(3, 0)
     stats.youngEase4 = oldDeck.sched.easeStats.get('young', {}).get(4, 0)
     stats.matureEase0 = oldDeck.sched.easeStats.get('old', {}).get(0, 0)
     stats.matureEase1 = oldDeck.sched.easeStats.get('old', {}).get(1, 0)
     stats.matureEase2 = oldDeck.sched.easeStats.get('old', {}).get(2, 0)
     stats.matureEase3 = oldDeck.sched.easeStats.get('old', {}).get(3, 0)
     stats.matureEase4 = oldDeck.sched.easeStats.get('old', {}).get(4, 0)
     yesCount = (oldDeck.sched.globalStats['new']['yes'] +
                 oldDeck.sched.globalStats['young']['yes'] +
                 oldDeck.sched.globalStats['old']['yes'])
     noCount = (oldDeck.sched.globalStats['new']['no'] +
                oldDeck.sched.globalStats['young']['no'] +
                oldDeck.sched.globalStats['old']['no'])
     stats.reps = yesCount + noCount
     s.save(stats)
     # ignore daily stats & history, they make no sense on new version
     s.flush()
     deck.updateAllPriorities()
     # save without updating mod time
     deck.modified = oldDeck.modified
     deck.lastLoaded = deck.modified
     deck.s.commit()
     deck.save()