Beispiel #1
0
def getNextScheduledCard(msg):
    """Fetch next scheduled card"""

    typeCheck(msg, {
        'deckName': str,
    })

    with Col() as col:
        deckName = msg['deckName']
        deck = col.decks.byName(deckName)
        col.decks.select(deck['id'])

        card = col.sched.getCard()
        if card is None:
            return emit.emitResult(None)

        answerButtonCount = col.sched.answerButtons(card)

        cardDict[card.id] = card

        return emit.emitResult({
            'cardId': card.id,
            'noteId': card.nid,
            'front': card.q(),
            'back': card.a(),
            'ansButtonCount': answerButtonCount,
        })
Beispiel #2
0
def deleteCardBatch(msg):
    typeCheck(msg, {
        'cardIds': list,
    })
    with Col() as col:
        col.remCards(msg['cardIds'])
        return emit.emitResult(True)
Beispiel #3
0
def listDeckDue(msg):
    with Col() as col:
        dueTree = col.sched.deckDueTree()

        def traverseDueTree(tree, prefix=''):
            result = []
            for name, deckId, rev, lrn, new, subTree in tree:
                deck = col.decks.get(deckId)
                result.append({
                    'name':
                    name,
                    'fullname':
                    prefix + name,
                    'newCount':
                    new,
                    'lrnCount':
                    lrn,
                    'revCount':
                    rev,
                    'subDecks':
                    traverseDueTree(subTree, prefix + name + '::'),
                    'collapsed':
                    deck['collapsed']
                })
            return result

        return emit.emitResult(traverseDueTree(dueTree))
Beispiel #4
0
def changeDues(msg):
    typeCheck(msg, {'cardIds': list, 'minDue': int, 'maxDue': int})
    cids = msg['cardIds']
    with Col() as col:
        checkpoint(col, 'Change card dues')
        minDue = (msg['minDue'] - col.crt) // 86400
        maxDue = (msg['maxDue'] - col.crt) // 86400
        for cid in cids:
            card = col.getCard(cid)
            oldIvl, oldDue = card.ivl, card.due

            if card.queue == 0 or card.type == 0:  # Ignore for new cards
                continue

            # TODO: Properly calculate the next interval using exponential learning curve
            oldDue = card.due
            newDue = random.randint(minDue, maxDue)
            print(oldDue, newDue)

            card.type = 2
            card.queue = 2
            card.due = newDue
            card.ivl += newDue - oldDue
            card.flush()
        col.reset()
        return emit.emitResult(True)
Beispiel #5
0
def resetScheduling(msg):
    typeCheck(msg, {'cardIds': list})
    cids = msg['cardIds']
    with Col() as col:
        checkpoint(col, "Reset scheduling and learning on selected cards")
        col.sched.resetCards(cids)
        col.sched.removeLrn(cids)
        return emit.emitResult(True)
Beispiel #6
0
def queryTagSuggestions(msg):
    typeCheck(msg, {
        'query': str,
    })
    query = msg['query']
    with Col() as col:
        tagList = col.tags.all()
        tagList = [tag for tag in tagList if tag.startswith(query)]
        return emit.emitResult(tagList)
Beispiel #7
0
def updateCardsModel(msg):
    typeCheck(msg, {
        'model': str,
        'cardIds': list,
    })
    with Col() as col:
        model = col.models.byName(msg['model'])
        nidSet = getNidSet(col, msg['cardIds'])
        modelChanger.changeNotesModel(col, nidSet, model)

        return emit.emitResult(True)
Beispiel #8
0
def getModelList(msg):
    typeCheck(msg, {
        'filename': str,
        'datab64': str,
    })

    filename = msg['filename']
    data = base64.b64decode(msg['datab64'])

    with Col() as col:
        mediaFilename = col.media.writeData(filename, data)
        print('UPLOAD', filename, len(data), mediaFilename)
        return emit.emitResult(mediaFilename)
Beispiel #9
0
def collapseDeck(msg):
    typeCheck(msg, {
        'deckName': str,
        'collapse': bool,
    })
    with Col() as col:
        deckName = msg['deckName']
        newCollapse = msg['collapse']
        deck = col.decks.byName(deckName)
        did = deck['id']
        if deck['collapsed'] != newCollapse:
            col.decks.collapse(did)

        return emit.emitResult(deck['collapsed'])
Beispiel #10
0
def updateNote(msg):
    typeCheck(msg, {'noteId': int, 'fields': list, 'tags': list})
    with Col() as col:
        noteId = msg['noteId']
        fields = msg['fields']
        tags = msg['tags']

        note = col.getNote(noteId)
        assert len(fields) == len(note.fields)

        note.fields[:] = fields
        note.tags = tags
        note.flush()
        return emit.emitResult(True)
Beispiel #11
0
def updateCardsDeck(msg):
    typeCheck(msg, {
        'deck': str,
        'cardIds': list,
    })
    with Col() as col:
        newDeck = col.decks.byName(msg['deck'])

        for cardId in msg['cardIds']:
            card = col.getCard(cardId)
            card.did = newDeck['id']
            card.flush()

        col.reset()
        return emit.emitResult(True)
Beispiel #12
0
def answerCard(msg):
    typeCheck(msg, {
        'cardId': int,
        'ease': int,
    })

    cardId, ease = int(msg['cardId']), int(msg['ease'])
    cardId = msg['cardId']
    card = cardDict[cardId]
    ease = int(msg['ease'])

    with Col() as col:
        col.sched.answerCard(card, ease)
        logging.info("Cid[%d] Reviewed with ease %d" % (cardId, ease))
        return emit.emitResult(True)
Beispiel #13
0
def deleteCardTags(msg):
    typeCheck(msg, {
        'tags': list,
        'cardIds': list,
    })
    with Col() as col:
        tags = msg['tags']
        nidSet = getNidSet(col, msg['cardIds'])
        for nid in nidSet:
            note = col.getNote(nid)
            for tag in tags:
                note.delTag(tag)
            note.flush()

        return emit.emitResult(True)
Beispiel #14
0
def getDeckInfo(msg):
    typeCheck(msg, {
        'deckName': str,
    })
    with Col() as col:
        deckNameReq = msg['deckName']
        for deckName, did, rev, lrn, new in col.sched.deckDueList():
            if deckName == deckNameReq:
                # SQL Code from More Overview Stats 2 addon
                col.decks.select(did)
                total, mature, young, unseen, suspended, due = col.db.first(
                    '''select
                        -- total
                        count(id),
                        -- mature
                        sum(case when queue = 2 and ivl >= 21 then 1 else 0 end),
                        -- young / learning
                        sum(case when queue in (1, 3) or (queue = 2 and ivl < 21) then 1 else 0 end),
                        -- unseen
                        sum(case when queue = 0 then 1 else 0 end),
                        -- suspended
                        sum(case when queue < 0 then 1 else 0 end),
                        -- due
                        sum(case when queue = 1 and due <= ? then 1 else 0 end)
                        from cards where did in %s
                        ''' % col.sched._deckLimit(), round(time.time()))

                # If there are no cards in current selected deck,
                if total == 0:
                    mature = young = unseen = suspended = due = 0
                return emit.emitResult({
                    'name': deckName,
                    'due': {
                        'newCount': new,
                        'lrnCount': lrn,
                        'revCount': rev,
                    },
                    'stat': {
                        'mature': mature,
                        'young': young,
                        'total': total,
                        'unseen': unseen,
                        'suspended': suspended,
                        'due': due
                    }
                })
Beispiel #15
0
def getCardsBatch(msg):
    typeCheck(msg, {'cardIds': list})
    with Col() as col:
        noteDict = {}
        cards = [col.getCard(cid) for cid in msg['cardIds']]
        ret = []

        for card in cards:
            try:
                note = noteDict[card.nid]
            except KeyError:
                note = noteDict[card.nid] = card.note()
            model = card.model()

            # Code from aqt/browser.py
            if card.odid:  # Special case: filtered decks
                due = '(filtered)'
            elif card.queue == 1:  # Learning card
                due = card.due
            elif card.queue == 0 or card.type == 0:  # New cards
                due = '(new card)'
            elif card.queue in (2, 3) or (card.type == 2 and card.queue < 0):
                due = col.crt + 86400 * card.due
            else:
                due = ''

            ret.append({
                'id': card.id,
                'deck': col.decks.get(card.did)['name'],
                'noteId': note.id,
                'ord': card.ord,
                'model': model['name'],
                'preview': htmlToTextLine(card.q(browser=True)),
                'tags': note.tags,
                'createdAt': card.id // 1000,
                'updatedAt': card.mod,
                'due': due,
                'type': card.type,
                'queue': card.queue,
            })
        return emit.emitResult(ret)
Beispiel #16
0
def getCard(msg):
    typeCheck(msg, {
        'cardId': int,
    })
    with Col() as col:
        cardId = msg['cardId']
        card = col.getCard(cardId)
        note = card.note()
        model = card.model()
        return emit.emitResult({
            'id': card.id,
            'deck': col.decks.get(card.did)['name'],
            'noteId': note.id,
            'model': model['name'],
            'fieldFormats': [{
                'name': fFormat['name'],
                'sticky': fFormat['sticky'],
            } for fFormat in model['flds']],
            'fields': note.fields,
            'tags': note.tags,
        })
Beispiel #17
0
def getNote(msg):
    typeCheck(msg, {
        'noteId': int,
    })
    with Col() as col:
        noteId = msg['noteId']
        note = col.getNote(noteId)
        fieldTemplateList = note.model()['flds']
        return emit.emitResult({
            'id':
            note.id,
            'model':
            note.model()['name'],
            'fieldFormats': [{
                'name': fFormat['name'],
                'sticky': fFormat['sticky'],
            } for fFormat in fieldTemplateList],
            'fields':
            note.fields,
            'tags':
            note.tags,
        })
Beispiel #18
0
def updateCard(msg):
    typeCheck(msg, {
        'cardId': int,
        'deck': str,
        'fields': list,
        'tags': list
    })
    with Col() as col:
        card = col.getCard(msg['cardId'])
        note = col.getNote(card.nid)
        deck = col.decks.byName(msg['deck'])

        fields = msg['fields']
        tags = msg['tags']

        assert len(fields) == len(note.fields)

        note.fields[:] = fields
        note.tags = tags
        note.flush()

        card.did = deck['id']
        card.flush()
        return emit.emitResult(True)
Beispiel #19
0
def getModel(msg):
    typeCheck(msg, {
        'modelName': str,
    })
    with Col() as col:
        modelName = msg['modelName']
        model = col.models.byName(modelName)
        return emit.emitResult({
            'type':
            'basic' if model['type'] == 0 else 'cloze',
            'name':
            model['name'],
            'templates': [{
                'name': template['name'],
                'front': template['qfmt'],
                'back': template['afmt'],
            } for template in model['tmpls']],
            'css':
            model['css'],
            'fieldFormats': [{
                'name': fFormat['name'],
                'sticky': fFormat['sticky'],
            } for fFormat in model['flds']]
        })
Beispiel #20
0
def addNote(msg):
    typeCheck(msg, {'deck': str, 'model': str, 'fields': list, 'tags': list})
    with Col() as col:
        model = col.models.byName(msg['model'])
        did = col.decks.id(msg['deck'],
                           create=True)  # cf) Create deck if not exists
        fields = msg['fields']
        tags = msg['tags']

        if not htmlToTextLine(fields[0]):
            return emit.emitError('First field should not be empty')

        if isClozeNote(fields) and model['type'] == 0:
            if msg['model'] in ('Basic',
                                _('Basic')):  # Automatic Basic → Cloze
                model = col.models.byName('Cloze') or col.models.byName(
                    _('Cloze'))
            else:
                model = None
            if not model:
                return emit.emitError(
                    'You need a cloze note type to make cloze notes')

        if not isClozeNote(fields) and model['type'] == 1:
            return emit.emitError('You need at least one cloze deletion.')

        note = Note(col, model)
        if len(note.fields) != len(fields):
            raise RuntimeError('Field number mismatch')
        note.fields[:] = fields
        note.tags[:] = tags

        model['did'] = did
        cardNum = col.addNote(note)

        return emit.emitResult({'noteId': note.id, 'cardNum': cardNum})
Beispiel #21
0
def listDeck(msg):
    typeCheck(msg, {
        'query': str,
    })
    query = msg['query']
    with Col() as col:
        sortBy = msg.get('sortBy', 'createdAt')
        sortOrder = msg.get('sortOrder', 'desc')

        orderBy = {
            'id': 'c.id',
            'deck': 'n.did',
            'noteId': 'n.id',
            'model': 'n.mid',
            'preview': 'n.sfld collate nocase, c.ord',
            'createdAt': 'n.id, c.ord',
            'updatedAt': 'c.mod',
            'due': 'c.type, c.due',
        }[sortBy]

        cIds = col.findCards(query, orderBy)
        if sortOrder == 'desc':
            cIds.reverse()
        return emit.emitResult(cIds)
Beispiel #22
0
def getCidFromNid(msg):
    typeCheck(msg, {'noteId': int})
    with Col() as col:
        return emit.emitResult(col.findCards('nid:%d' % msg['noteId']))
Beispiel #23
0
def listDeck(msg):
    with Col() as col:
        deckNames = [d['name'] for d in col.decks.all()]
        deckNames.sort()
        return emit.emitResult(deckNames)
Beispiel #24
0
def getNidFromCid(msg):
    typeCheck(msg, {'cardId': int})
    with Col() as col:
        cid = msg['cardId']
        return emit.emitResult(col.getCard(cid).nid)
Beispiel #25
0
def getModelList(msg):
    with Col() as col:
        return emit.emitResult(col.models.allNames())