Search in sources :

Example 41 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class Sched method _checkLeech.

/**
 * Leeches ****************************************************************** *****************************
 */
/**
 * Leech handler. True if card was a leech.
 */
@Override
protected boolean _checkLeech(@NonNull Card card, @NonNull JSONObject conf) {
    int lf;
    lf = conf.getInt("leechFails");
    if (lf == 0) {
        return false;
    }
    // if over threshold or every half threshold reps after that
    if (card.getLapses() >= lf && (card.getLapses() - lf) % Math.max(lf / 2, 1) == 0) {
        // add a leech tag
        Note n = card.note();
        n.addTag("leech");
        n.flush();
        // handle
        if (conf.getInt("leechAction") == Consts.LEECH_SUSPEND) {
            // if it has an old due, remove it from cram/relearning
            if (card.getODue() != 0) {
                card.setDue(card.getODue());
            }
            if (card.getODid() != 0) {
                card.setDid(card.getODid());
            }
            card.setODue(0);
            card.setODid(0);
            card.setQueue(Consts.QUEUE_TYPE_SUSPENDED);
        }
        // notify UI
        if (mContextReference != null) {
            Activity context = mContextReference.get();
            leech(card, context);
        }
        return true;
    }
    return false;
}
Also used : Note(com.ichi2.libanki.Note) Activity(android.app.Activity)

Example 42 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class Sched method _updateRevIvl.

@Override
protected void _updateRevIvl(@NonNull Card card, @Consts.BUTTON_TYPE int ease) {
    try {
        int idealIvl = _nextRevIvl(card, ease);
        JSONObject conf = _revConf(card);
        card.setIvl(Math.min(Math.max(_adjRevIvl(card, idealIvl), card.getIvl() + 1), conf.getInt("maxIvl")));
    } catch (JSONException e) {
        throw new RuntimeException(e);
    }
}
Also used : JSONObject(com.ichi2.utils.JSONObject) JSONException(com.ichi2.utils.JSONException)

Example 43 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class Sched method _fillRev.

@Override
protected boolean _fillRev(boolean allowSibling) {
    if (!mRevQueue.isEmpty()) {
        return true;
    }
    if (mRevCount == 0) {
        return false;
    }
    SupportSQLiteDatabase db = mCol.getDb().getDatabase();
    while (!mRevDids.isEmpty()) {
        long did = mRevDids.getFirst();
        int lim = Math.min(mQueueLimit, _deckRevLimit(did));
        Cursor cur = null;
        if (lim != 0) {
            mRevQueue.clear();
            // fill the queue with the current did
            try {
                /* Difference with upstream: we take current card into account.
                     *
                     * When current card is answered, the card is not due anymore, so does not belong to the queue.
                     * Furthermore, _burySiblings ensure that the siblings of the current cards are removed from the
                     * queue to ensure same day spacing. We simulate this action by ensuring that those siblings are not
                     * filled, except if we know there are cards and we didn't find any non-sibling card. This way, the
                     * queue is not empty if it should not be empty (important for the conditional belows), but the
                     * front of the queue contains distinct card.
                     */
                String idName = (allowSibling) ? "id" : "nid";
                long id = (allowSibling) ? currentCardId() : currentCardNid();
                cur = db.query("SELECT id FROM cards WHERE did = ? AND queue = " + Consts.QUEUE_TYPE_REV + " AND due <= ?" + " AND " + idName + " != ? LIMIT ?", new Object[] { did, mToday, id, lim });
                while (cur.moveToNext()) {
                    mRevQueue.add(cur.getLong(0));
                }
            } finally {
                if (cur != null && !cur.isClosed()) {
                    cur.close();
                }
            }
            if (!mRevQueue.isEmpty()) {
                // ordering
                if (mCol.getDecks().get(did).getInt("dyn") != 0) {
                // dynamic decks need due order preserved
                // Note: libanki reverses mRevQueue and returns the last element in _getRevCard().
                // AnkiDroid differs by leaving the queue intact and returning the *first* element
                // in _getRevCard().
                } else {
                    Random r = new Random();
                    r.setSeed(mToday);
                    mRevQueue.shuffle(r);
                }
                // is the current did empty?
                if (mRevQueue.size() < lim) {
                    mRevDids.remove();
                }
                return true;
            }
        }
        // nothing left in the deck; move to next
        mRevDids.remove();
    }
    // Since we didn't get a card and the count is non-zero, we
    // need to check again for any cards that were removed from
    // the queue but not buried
    _resetRev();
    return _fillRev(true);
}
Also used : SupportSQLiteDatabase(androidx.sqlite.db.SupportSQLiteDatabase) Random(java.util.Random) JSONObject(com.ichi2.utils.JSONObject) Cursor(android.database.Cursor)

Example 44 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class Sched method _deckRevLimitSingle.

/**
 * Maximal number of rev card still to see today in deck d. It's computed as:
 * the number of rev card to see by day according
 * minus the number of rev cards seen today in deck d or a descendant
 * plus the number of extra cards to see today in deck d, a parent or a descendant.
 *
 * Limits of its ancestors are not applied.  Current card is treated the same way as other cards.
 */
@Override
protected int _deckRevLimitSingle(@NonNull Deck d) {
    if (d.getInt("dyn") != 0) {
        return mReportLimit;
    }
    long did = d.getLong("id");
    DeckConfig c = mCol.getDecks().confForDid(did);
    int lim = Math.max(0, c.getJSONObject("rev").getInt("perDay") - d.getJSONArray("revToday").getInt(1));
    if (currentCardIsInQueueWithDeck(Consts.QUEUE_TYPE_REV, did)) {
        lim--;
    }
    // So currentCard does not have to be taken into consideration in this method
    return lim;
}
Also used : DeckConfig(com.ichi2.libanki.DeckConfig)

Example 45 with CARD

use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.

the class Sched method _lapseConf.

@Override
@NonNull
protected JSONObject _lapseConf(@NonNull Card card) {
    DeckConfig conf = _cardConf(card);
    // normal deck
    if (card.getODid() == 0) {
        return conf.getJSONObject("lapse");
    }
    // dynamic deck; override some attributes, use original deck for others
    DeckConfig oconf = mCol.getDecks().confForDid(card.getODid());
    JSONArray delays = conf.optJSONArray("delays");
    if (delays == null) {
        delays = oconf.getJSONObject("lapse").getJSONArray("delays");
    }
    JSONObject dict = new JSONObject();
    // original deck
    dict.put("minInt", oconf.getJSONObject("lapse").getInt("minInt"));
    dict.put("leechFails", oconf.getJSONObject("lapse").getInt("leechFails"));
    dict.put("leechAction", oconf.getJSONObject("lapse").getInt("leechAction"));
    dict.put("mult", oconf.getJSONObject("lapse").getDouble("mult"));
    // overrides
    dict.put("delays", delays);
    dict.put("resched", conf.getBoolean("resched"));
    return dict;
}
Also used : JSONObject(com.ichi2.utils.JSONObject) JSONArray(com.ichi2.utils.JSONArray) DeckConfig(com.ichi2.libanki.DeckConfig) NonNull(androidx.annotation.NonNull)

Aggregations

Card (com.ichi2.libanki.Card)222 Test (org.junit.Test)212 Collection (com.ichi2.libanki.Collection)179 Note (com.ichi2.libanki.Note)173 RobolectricTest (com.ichi2.anki.RobolectricTest)168 JSONObject (com.ichi2.utils.JSONObject)114 JSONArray (com.ichi2.utils.JSONArray)80 DeckConfig (com.ichi2.libanki.DeckConfig)72 ArrayList (java.util.ArrayList)48 NonNull (androidx.annotation.NonNull)33 Deck (com.ichi2.libanki.Deck)32 Intent (android.content.Intent)29 JSONException (com.ichi2.utils.JSONException)27 Model (com.ichi2.libanki.Model)26 Context (android.content.Context)23 SuppressLint (android.annotation.SuppressLint)22 Cursor (android.database.Cursor)22 HashMap (java.util.HashMap)21 Matchers.containsString (org.hamcrest.Matchers.containsString)20 List (java.util.List)17