Search in sources :

Example 91 with DUE

use of com.ichi2.anki.CardBrowser.Column.DUE in project Anki-Android by ankidroid.

the class ImportUtilsTest method fileNamesAreLimitedTo100Chars.

@Test
public void fileNamesAreLimitedTo100Chars() {
    // #6137 - We URLEncode due to the above. Therefore: 好 -> %E5%A5%BD
    // This caused filenames to be too long.
    String inputFileName = "好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好好.apkg";
    String actualFilePath = importValidFile(inputFileName);
    assertThat(actualFilePath, endsWith(".apkg"));
    assertThat(actualFilePath, containsString("..."));
    // Obtain the filename from the path
    assertThat(actualFilePath, containsString("%E5%A5%BD"));
    String fileName = actualFilePath.substring(actualFilePath.indexOf("%E5%A5%BD"));
    assertThat(fileName.length(), lessThanOrEqualTo(100));
}
Also used : Matchers.containsString(org.hamcrest.Matchers.containsString) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 92 with DUE

use of com.ichi2.anki.CardBrowser.Column.DUE in project Anki-Android by ankidroid.

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.REVLOG_TYPE int type;
    if (card.isInDynamicDeck() && !card.getWasNew()) {
        type = Consts.REVLOG_CRAM;
    } else if (card.getType() == Consts.CARD_TYPE_REV) {
        type = Consts.REVLOG_RELRN;
    } else {
        type = Consts.REVLOG_LRN;
    }
    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.isInDynamicDeck()) {
                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 93 with DUE

use of com.ichi2.anki.CardBrowser.Column.DUE in project Anki-Android by ankidroid.

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 = 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.isInDynamicDeck()) {
                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 94 with DUE

use of com.ichi2.anki.CardBrowser.Column.DUE in project Anki-Android by ankidroid.

the class Sched method _rescheduleLapse.

@Override
protected int _rescheduleLapse(@NonNull Card card) {
    JSONObject 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.isInDynamicDeck()) {
            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 95 with DUE

use of com.ichi2.anki.CardBrowser.Column.DUE in project Anki-Android by ankidroid.

the class SchedV2 method _burySiblings.

/**
 * Sibling spacing
 * ********************
 */
protected void _burySiblings(@NonNull Card card) {
    ArrayList<Long> toBury = new ArrayList<>();
    JSONObject nconf = _newConf(card);
    boolean buryNew = nconf.optBoolean("bury", true);
    JSONObject rconf = _revConf(card);
    boolean buryRev = rconf.optBoolean("bury", true);
    // loop through and remove from queues
    try (Cursor cur = mCol.getDb().query("select id, queue from cards where nid=? and id!=? " + "and (queue=" + Consts.QUEUE_TYPE_NEW + " or (queue=" + Consts.QUEUE_TYPE_REV + " and due<=?))", card.getNid(), card.getId(), mToday)) {
        while (cur.moveToNext()) {
            long cid = cur.getLong(0);
            int queue = cur.getInt(1);
            SimpleCardQueue queue_object;
            if (queue == Consts.QUEUE_TYPE_REV) {
                queue_object = mRevQueue;
                if (buryRev) {
                    toBury.add(cid);
                }
            } else {
                queue_object = mNewQueue;
                if (buryNew) {
                    toBury.add(cid);
                }
            }
            // even if burying disabled, we still discard to give
            // same-day spacing
            queue_object.remove(cid);
        }
    }
    // then bury
    if (!toBury.isEmpty()) {
        buryCards(Utils.collection2Array(toBury), false);
    }
}
Also used : JSONObject(com.ichi2.utils.JSONObject) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor)

Aggregations

Test (org.junit.Test)58 Collection (com.ichi2.libanki.Collection)57 Card (com.ichi2.libanki.Card)55 Note (com.ichi2.libanki.Note)52 RobolectricTest (com.ichi2.anki.RobolectricTest)51 JSONObject (com.ichi2.utils.JSONObject)25 DeckConfig (com.ichi2.libanki.DeckConfig)20 JSONArray (com.ichi2.utils.JSONArray)16 ArrayList (java.util.ArrayList)16 Cursor (android.database.Cursor)14 Deck (com.ichi2.libanki.Deck)10 ContentResolver (android.content.ContentResolver)6 ContentValues (android.content.ContentValues)6 Uri (android.net.Uri)6 IOException (java.io.IOException)6 HashMap (java.util.HashMap)6 SuppressLint (android.annotation.SuppressLint)5 FileNotFoundException (java.io.FileNotFoundException)5 Activity (android.app.Activity)4 WebView (android.webkit.WebView)4