Search in sources :

Example 26 with Queue

use of com.ichi2.libanki.sched.Counts.Queue in project AnkiChinaAndroid by ankichinateam.

the class Sched method _answerLrnCard.

/**
 * @param ease 1=no, 2=yes, 3=remove
 */
@Override
protected void _answerLrnCard(@NonNull Card card, @Consts.BUTTON_TYPE int ease) {
    JSONObject conf = _lrnConf(card);
    @Consts.CARD_TYPE int type;
    if (card.getODid() != 0 && !card.getWasNew()) {
        type = Consts.CARD_TYPE_RELEARNING;
    } else if (card.getType() == Consts.CARD_TYPE_REV) {
        type = Consts.CARD_TYPE_REV;
    } else {
        type = Consts.CARD_TYPE_NEW;
    }
    boolean leaving = false;
    // lrnCount was decremented once when card was fetched
    int lastLeft = card.getLeft();
    // immediate graduate?
    if (ease == Consts.BUTTON_THREE) {
        _rescheduleAsRev(card, conf, true);
        leaving = true;
    // graduation time?
    } else if (ease == Consts.BUTTON_TWO && (card.getLeft() % 1000) - 1 <= 0) {
        _rescheduleAsRev(card, conf, false);
        leaving = true;
    } else {
        // one step towards graduation
        if (ease == Consts.BUTTON_TWO) {
            // decrement real left count and recalculate left today
            int left = (card.getLeft() % 1000) - 1;
            card.setLeft(_leftToday(conf.getJSONArray("delays"), left) * 1000 + left);
        // failed
        } else {
            card.setLeft(_startingLeft(card));
            boolean resched = _resched(card);
            if (conf.has("mult") && resched) {
                // review that's lapsed
                card.setIvl(Math.max(Math.max(1, (int) (card.getIvl() * conf.getDouble("mult"))), conf.getInt("minInt")));
            } else {
            // new card; no ivl adjustment
            // pass
            }
            if (resched && card.getODid() != 0) {
                card.setODue(mToday + 1);
            }
        }
        int delay = _delayForGrade(conf, card.getLeft());
        if (card.getDue() < getTime().intTime()) {
            // not collapsed; add some randomness
            delay *= Utils.randomFloatInRange(1f, 1.25f);
        }
        card.setDue(getTime().intTime() + delay);
        // due today?
        if (card.getDue() < mDayCutoff) {
            mLrnCount += card.getLeft() / 1000;
            // if the queue is not empty and there's nothing else to do, make
            // sure we don't put it at the head of the queue and end up showing
            // it twice in a row
            card.setQueue(Consts.QUEUE_TYPE_LRN);
            if (!mLrnQueue.isEmpty() && revCount() == 0 && newCount() == 0) {
                long smallestDue = mLrnQueue.getFirstDue();
                card.setDue(Math.max(card.getDue(), smallestDue + 1));
            }
            _sortIntoLrn(card.getDue(), card.getId());
        } else {
            // the card is due in one or more days, so we need to use the day learn queue
            long ahead = ((card.getDue() - mDayCutoff) / SECONDS_PER_DAY) + 1;
            card.setDue(mToday + ahead);
            card.setQueue(Consts.QUEUE_TYPE_DAY_LEARN_RELEARN);
        }
    }
    _logLrn(card, ease, conf, leaving, type, lastLeft);
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Example 27 with Queue

use of com.ichi2.libanki.sched.Counts.Queue in project AnkiChinaAndroid by ankichinateam.

the class Sched method _rescheduleLapse.

@Override
protected int _rescheduleLapse(@NonNull Card card) {
    JSONObject conf;
    conf = _lapseConf(card);
    card.setLastIvl(card.getIvl());
    if (_resched(card)) {
        card.setLapses(card.getLapses() + 1);
        card.setIvl(_nextLapseIvl(card, conf));
        card.setFactor(Math.max(1300, card.getFactor() - 200));
        card.setDue(mToday + card.getIvl());
        // if it's a filtered deck, update odue as well
        if (card.getODid() != 0) {
            card.setODue(card.getDue());
        }
    }
    // if suspended as a leech, nothing to do
    int delay = 0;
    if (_checkLeech(card, conf) && card.getQueue() == Consts.QUEUE_TYPE_SUSPENDED) {
        return delay;
    }
    // if no relearning steps, nothing to do
    if (conf.getJSONArray("delays").length() == 0) {
        return delay;
    }
    // record rev due date for later
    if (card.getODue() == 0) {
        card.setODue(card.getDue());
    }
    delay = _delayForGrade(conf, 0);
    card.setDue(delay + getTime().intTime());
    card.setLeft(_startingLeft(card));
    // queue 1
    if (card.getDue() < mDayCutoff) {
        mLrnCount += card.getLeft() / 1000;
        card.setQueue(Consts.QUEUE_TYPE_LRN);
        _sortIntoLrn(card.getDue(), card.getId());
    } else {
        // day learn queue
        long ahead = ((card.getDue() - mDayCutoff) / SECONDS_PER_DAY) + 1;
        card.setDue(mToday + ahead);
        card.setQueue(Consts.QUEUE_TYPE_DAY_LEARN_RELEARN);
    }
    return delay;
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Example 28 with Queue

use of com.ichi2.libanki.sched.Counts.Queue in project AnkiChinaAndroid by ankichinateam.

the class SchedV2 method undoReview.

@Override
public void undoReview(@NonNull Card oldCardData, boolean wasLeech) {
    // remove leech tag if it didn't have it before
    if (!wasLeech && oldCardData.note().hasTag("leech")) {
        oldCardData.note().delTag("leech");
        oldCardData.note().flush();
    }
    Timber.i("Undo Review of card %d, leech: %b", oldCardData.getId(), wasLeech);
    // write old data
    oldCardData.flush(false);
    DeckConfig conf = _cardConf(oldCardData);
    boolean previewing = conf.getInt("dyn") != 0 && !conf.getBoolean("resched");
    if (!previewing) {
        // and delete revlog entry
        long last = mCol.getDb().queryLongScalar("SELECT id FROM revlog WHERE cid = ? ORDER BY id DESC LIMIT 1", oldCardData.getId());
        mCol.getDb().execute("DELETE FROM revlog WHERE id = " + last);
    }
    // restore any siblings
    mCol.getDb().execute("update cards set queue=type,mod=?,usn=? where queue=" + Consts.QUEUE_TYPE_SIBLING_BURIED + " and nid=?", getTime().intTime(), mCol.usn(), oldCardData.getNid());
    // and finally, update daily count
    @Consts.CARD_QUEUE int n = oldCardData.getQueue() == Consts.QUEUE_TYPE_DAY_LEARN_RELEARN ? Consts.QUEUE_TYPE_LRN : oldCardData.getQueue();
    String type = (new String[] { "new", "lrn", "rev" })[n];
    _updateStats(oldCardData, type, -1);
    decrReps();
}
Also used : DeckConfig(com.ichi2.libanki.DeckConfig)

Example 29 with Queue

use of com.ichi2.libanki.sched.Counts.Queue in project AnkiChinaAndroid by ankichinateam.

the class SchedV2 method setCurrentCard.

/**
 * This imitate the action of the method answerCard, except that it does not change the state of any card.
 *
 * It means in particular that: + it removes the siblings of card from all queues + change the next card if required
 * it also set variables, so that when querying the next card, the current card can be taken into account.
 */
public void setCurrentCard(@NonNull Card card) {
    mCurrentCard = card;
    long did = card.getDid();
    List<Deck> parents = mCol.getDecks().parents(did);
    List<Long> currentCardParentsDid = new ArrayList<>(parents.size() + 1);
    for (JSONObject parent : parents) {
        currentCardParentsDid.add(parent.getLong("id"));
    }
    currentCardParentsDid.add(did);
    // We set the member only once it is filled, to ensure we avoid null pointer exception if `discardCurrentCard`
    // were called during `setCurrentCard`.
    mCurrentCardParentsDid = currentCardParentsDid;
    _burySiblings(card);
    // if current card is next card or in the queue
    mRevQueue.remove(card.getId());
    mNewQueue.remove(card.getId());
}
Also used : JSONObject(com.ichi2.utils.JSONObject) ArrayList(java.util.ArrayList) Deck(com.ichi2.libanki.Deck)

Example 30 with Queue

use of com.ichi2.libanki.sched.Counts.Queue in project AnkiChinaAndroid by ankichinateam.

the class SchedV2 method getCard.

/**
 * Pop the next card from the queue. null if finished.
 */
@Nullable
public Card getCard() {
    _checkDay();
    // check day deal with cutoff if required. No need to do it in resets
    if (!mHaveCounts) {
        resetCounts(false);
    }
    if (!mHaveQueues) {
        resetQueues(false);
    }
    @Nullable Card card = _getCard();
    if (card != null) {
        mCol.log(card);
        incrReps();
        // In upstream, counts are decremented when the card is
        // gotten; i.e. in _getLrnCard, _getRevCard and
        // _getNewCard. This can not be done anymore since we use
        // those methods to pre-fetch the next card. Instead we
        // decrement the counts here, when the card is returned to
        // the reviewer.
        decrementCounts(card);
        setCurrentCard(card);
        card.startTimer();
    } else {
        discardCurrentCard();
    }
    return card;
}
Also used : Nullable(androidx.annotation.Nullable) Card(com.ichi2.libanki.Card) Nullable(androidx.annotation.Nullable)

Aggregations

Card (com.ichi2.libanki.Card)31 Test (org.junit.Test)30 RobolectricTest (com.ichi2.anki.RobolectricTest)29 Collection (com.ichi2.libanki.Collection)27 Note (com.ichi2.libanki.Note)24 JSONObject (com.ichi2.utils.JSONObject)20 JSONArray (com.ichi2.utils.JSONArray)17 DeckConfig (com.ichi2.libanki.DeckConfig)15 Cursor (android.database.Cursor)10 ArrayList (java.util.ArrayList)10 Deck (com.ichi2.libanki.Deck)6 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)4 JSONException (com.ichi2.utils.JSONException)3 Nullable (androidx.annotation.Nullable)2 SupportSQLiteDatabase (androidx.sqlite.db.SupportSQLiteDatabase)2 Model (com.ichi2.libanki.Model)2 FileNotFoundException (java.io.FileNotFoundException)2 IOException (java.io.IOException)2 HashMap (java.util.HashMap)2 SuppressLint (android.annotation.SuppressLint)1