Search in sources :

Example 41 with DUE

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

the class Collection method addNote.

/**
 * Add a note and cards to the collection. If allowEmpty, at least one card is generated.
 * @param note  The note to add to the collection
 * @param allowEmpty Whether we accept to add it even if it should generate no card. Useful to import note even if buggy
 * @return Number of card added
 */
public int addNote(@NonNull Note note, Models.AllowEmpty allowEmpty) {
    // check we have card models available, then save
    ArrayList<JSONObject> cms = findTemplates(note, allowEmpty);
    // Todo: upstream, we accept to add a not even if it generates no card. Should be ported to ankidroid
    if (cms.isEmpty()) {
        return 0;
    }
    note.flush();
    // deck conf governs which of these are used
    int due = nextID("pos");
    // add cards
    int ncards = 0;
    for (JSONObject template : cms) {
        _newCard(note, template, due);
        ncards += 1;
    }
    return ncards;
}
Also used : JSONObject(com.ichi2.utils.JSONObject) SuppressLint(android.annotation.SuppressLint)

Example 42 with DUE

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

the class AdvancedStatistics method calculateDueAsMetaInfo.

/**
 * Determine forecast statistics based on a computation or simulation of future reviews.
 * Returns all information required by stats.java to plot the 'forecast' chart based on these statistics.
 * The chart will display:
 * - The forecasted number of reviews per review type (relearn, mature, young, learn) as bars
 * - The forecasted number of cards in each state (new, young, mature) as lines
 * @param metaInfo Object which will be filled with all information required by stats.java to plot the 'forecast' chart and returned by this method.
 * @param type Type of 'forecast' chart for which to determine forecast statistics. Accepted values:
 *             Stats.TYPE_MONTH: Determine forecast statistics for next 30 days with 1-day chunks
 *             Stats.TYPE_YEAR:  Determine forecast statistics for next year with 7-day chunks
 *             Stats.TYPE_LIFE:  Determine forecast statistics for next 2 years with 30-day chunks
 * @param context Contains The collection which contains the decks to be simulated.
 *             Also used for access to the database and access to the creation time of the collection.
 *             The creation time of the collection is needed since due times of cards are relative to the creation time of the collection.
 *             So we could pass mCol here.
 * @param dids Deck id's
 * @return @see #metaInfo
 */
public StatsMetaInfo calculateDueAsMetaInfo(StatsMetaInfo metaInfo, Stats.AxisType type, Context context, String dids) {
    if (!AnkiDroidApp.getSharedPrefs(context).getBoolean("advanced_statistics_enabled", false)) {
        return metaInfo;
    }
    // To indicate that we calculated the statistics so that Stats.java knows that it shouldn't display the standard Forecast chart.
    mSettings = new Settings(context);
    metaInfo.setStatsCalculated(true);
    Collection col = CollectionHelper.getInstance().getCol(context);
    int maxCards = 0;
    double lastElement = 0;
    int zeroIndex = 0;
    int[] valueLabels = { R.string.statistics_relearn, R.string.statistics_mature, R.string.statistics_young, R.string.statistics_learn };
    int[] colors = { R.attr.stats_relearn, R.attr.stats_mature, R.attr.stats_young, R.attr.stats_learn };
    int[] axisTitles = { type.ordinal(), R.string.stats_cards, R.string.stats_cumulative_cards };
    PlottableSimulationResult simuationResult = calculateDueAsPlottableSimulationResult(type, col, dids);
    ArrayList<int[]> dues = simuationResult.getNReviews();
    double[][] seriesList = new double[REVIEW_TYPE_COUNT_PLUS_1][dues.size()];
    for (int t = 0; t < dues.size(); t++) {
        int[] data = dues.get(t);
        int nReviews = data[REVIEW_TYPE_LEARN_PLUS_1] + data[REVIEW_TYPE_YOUNG_PLUS_1] + data[REVIEW_TYPE_MATURE_PLUS_1] + data[REVIEW_TYPE_RELEARN_PLUS_1];
        if (nReviews > maxCards)
            // Y-Axis: Max. value
            maxCards = nReviews;
        // In the bar-chart, the bars will be stacked on top of each other.
        // For the i^{th} bar counting from the bottom we therefore have to
        // provide the sum of the heights of the i^{th} bar and all bars below it.
        // X-Axis: Day / Week / Month
        seriesList[TIME][t] = data[TIME];
        seriesList[REVIEW_TYPE_LEARN_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1] + data[REVIEW_TYPE_YOUNG_PLUS_1] + data[REVIEW_TYPE_MATURE_PLUS_1] + // Y-Axis: # Cards
        data[REVIEW_TYPE_RELEARN_PLUS_1];
        seriesList[REVIEW_TYPE_YOUNG_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1] + data[REVIEW_TYPE_YOUNG_PLUS_1] + // Y-Axis: # Mature cards
        data[REVIEW_TYPE_MATURE_PLUS_1];
        seriesList[REVIEW_TYPE_MATURE_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1] + // Y-Axis: # Young
        data[REVIEW_TYPE_YOUNG_PLUS_1];
        // Y-Axis: # Learn
        seriesList[REVIEW_TYPE_RELEARN_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1];
        if (data[TIME] > lastElement)
            // X-Axis: Max. value (only for TYPE_LIFE)
            lastElement = data[TIME];
        if (data[TIME] == 0) {
            // Because we retrieve dues in the past and we should not cumulate them
            zeroIndex = t;
        }
    }
    // # X values
    int maxElements = dues.size() - 1;
    switch(type) {
        case TYPE_MONTH:
            // X-Axis: Max. value
            lastElement = 31;
            break;
        case TYPE_YEAR:
            // X-Axis: Max. value
            lastElement = 52;
            break;
        default:
    }
    // X-Axis: Min. value
    double firstElement = 0;
    // Day starting at zeroIndex, Cumulative # cards
    double[][] cumulative = simuationResult.getNInState();
    double count = // Y-Axis: Max. cumulative value
    cumulative[CARD_TYPE_NEW_PLUS_1][cumulative[CARD_TYPE_NEW_PLUS_1].length - 1] + cumulative[CARD_TYPE_YOUNG_PLUS_1][cumulative[CARD_TYPE_YOUNG_PLUS_1].length - 1] + cumulative[CARD_TYPE_MATURE_PLUS_1][cumulative[CARD_TYPE_MATURE_PLUS_1].length - 1];
    // some adjustments to not crash the chartbuilding with empty data
    if (maxElements == 0) {
        maxElements = 10;
    }
    if (count == 0) {
        count = 10;
    }
    if (firstElement == lastElement) {
        firstElement = 0;
        lastElement = 6;
    }
    if (maxCards == 0)
        maxCards = 10;
    metaInfo.setmDynamicAxis(true);
    metaInfo.setmHasColoredCumulative(true);
    metaInfo.setmType(type);
    metaInfo.setmTitle(R.string.stats_forecast);
    metaInfo.setmBackwards(true);
    metaInfo.setmValueLabels(valueLabels);
    metaInfo.setmColors(colors);
    metaInfo.setmAxisTitles(axisTitles);
    metaInfo.setmMaxCards(maxCards);
    metaInfo.setmMaxElements(maxElements);
    metaInfo.setmFirstElement(firstElement);
    metaInfo.setmLastElement(lastElement);
    metaInfo.setmZeroIndex(zeroIndex);
    metaInfo.setmCumulative(cumulative);
    metaInfo.setmMcount(count);
    metaInfo.setmSeriesList(seriesList);
    metaInfo.setDataAvailable(!dues.isEmpty());
    return metaInfo;
}
Also used : Collection(com.ichi2.libanki.Collection)

Example 43 with DUE

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

the class SchedV2 method _checkLeech.

/*
      Leeches ****************************************************************** *****************************
     */
/**
 * Leech handler. True if card was a leech.
 *        Overridden: in V1, due and did are changed
 */
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) {
            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 44 with DUE

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

the class SchedV2 method quickDeckDueTree.

/**
 * Similar to deck due tree, but ignore the number of cards.
 *
 *     It may takes a lot of time to compute the number of card, it
 *     requires multiple database access by deck.  Ignoring this number
 *     lead to the creation of a tree more quickly.
 */
@Override
@NonNull
public List<DeckTreeNode> quickDeckDueTree() {
    // Similar to deckDueTree, ignoring the numbers
    List<Deck> decks = mCol.getDecks().allSorted();
    // Similar to deckDueList
    ArrayList<DeckTreeNode> data = new ArrayList<>();
    for (JSONObject deck : decks) {
        DeckTreeNode g = new DeckTreeNode(mCol, deck.getString("name"), deck.getLong("id"));
        data.add(g);
    }
    return _groupChildren(data, false);
}
Also used : JSONObject(com.ichi2.utils.JSONObject) ArrayList(java.util.ArrayList) Deck(com.ichi2.libanki.Deck) NonNull(androidx.annotation.NonNull)

Example 45 with DUE

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

the class Sched method _getCard.

/*
      Getting the next card ****************************************************
      *******************************************
     */
/**
 * Return the next due card, or null.
 */
@Override
@Nullable
protected Card _getCard() {
    // learning card due?
    @Nullable Card c = _getLrnCard(false);
    if (c != null) {
        return c;
    }
    // new first, or time for one?
    if (_timeForNewCard()) {
        c = _getNewCard();
        if (c != null) {
            return c;
        }
    }
    // Card due for review?
    c = _getRevCard();
    if (c != null) {
        return c;
    }
    // day learning card due?
    c = _getLrnDayCard();
    if (c != null) {
        return c;
    }
    // New cards left?
    c = _getNewCard();
    if (c != null) {
        return c;
    }
    // collapse or finish
    return _getLrnCard(true);
}
Also used : Nullable(androidx.annotation.Nullable) Card(com.ichi2.libanki.Card) Nullable(androidx.annotation.Nullable)

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