Search in sources :

Example 26 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class SchedTest method test_reviewsV1.

@Test
public void test_reviewsV1() throws Exception {
    Collection col = getColV1();
    // add a note
    Note note = col.newNote();
    note.setItem("Front", "one");
    note.setItem("Back", "two");
    col.addNote(note);
    // set the card up as a review card, due 8 days ago
    Card c = note.cards().get(0);
    c.setType(CARD_TYPE_REV);
    c.setQueue(QUEUE_TYPE_REV);
    c.setDue(col.getSched().getToday() - 8);
    c.setFactor(STARTING_FACTOR);
    c.setReps(3);
    c.setLapses(1);
    c.setIvl(100);
    c.startTimer();
    c.flush();
    // save it for later use as well
    Card cardcopy = c.clone();
    // failing it should put it in the learn queue with the default options
    // //////////////////////////////////////////////////////////////////////////////////////////////////
    // different delay to new
    col.reset();
    DeckConfig conf = col.getSched()._cardConf(c);
    conf.getJSONObject("lapse").put("delays", new JSONArray(new double[] { 2, 20 }));
    col.getDecks().save(conf);
    col.getSched().answerCard(c, BUTTON_ONE);
    assertEquals(QUEUE_TYPE_LRN, c.getQueue());
    // it should be due tomorrow, with an interval of 1
    assertEquals(col.getSched().getToday() + 1, c.getODue());
    assertEquals(1, c.getIvl());
    // but because it's in the learn queue, its current due time should be in
    // the future
    assertThat(c.getDue(), is(greaterThanOrEqualTo(col.getTime().intTime())));
    assertThat(c.getDue() - col.getTime().intTime(), is(greaterThan(118L)));
    // factor should have been decremented
    assertEquals(2300, c.getFactor());
    // check counters
    assertEquals(2, c.getLapses());
    assertEquals(4, c.getReps());
    // check ests.
    assertEquals(120, col.getSched().nextIvl(c, BUTTON_ONE));
    assertEquals(20 * 60, col.getSched().nextIvl(c, BUTTON_TWO));
    // try again with an ease of 2 instead
    // //////////////////////////////////////////////////////////////////////////////////////////////////
    c = cardcopy.clone();
    c.flush();
    col.getSched().answerCard(c, BUTTON_TWO);
    assertEquals(QUEUE_TYPE_REV, c.getQueue());
    // the new interval should be (100 + 8/4) * 1.2 = 122
    assertTrue(checkRevIvl(col, c, 122));
    assertEquals(col.getSched().getToday() + c.getIvl(), c.getDue());
    // factor should have been decremented
    assertEquals(2350, c.getFactor());
    // check counters
    assertEquals(1, c.getLapses());
    assertEquals(4, c.getReps());
    // ease 3
    // //////////////////////////////////////////////////////////////////////////////////////////////////
    c = cardcopy.clone();
    c.flush();
    col.getSched().answerCard(c, BUTTON_THREE);
    // the new interval should be (100 + 8/2) * 2.5 = 260
    assertTrue(checkRevIvl(col, c, 260));
    assertEquals(col.getSched().getToday() + c.getIvl(), c.getDue());
    // factor should have been left alone
    assertEquals(STARTING_FACTOR, c.getFactor());
    // ease 4
    // //////////////////////////////////////////////////////////////////////////////////////////////////
    c = cardcopy.clone();
    c.flush();
    col.getSched().answerCard(c, BUTTON_FOUR);
    // the new interval should be (100 + 8) * 2.5 * 1.3 = 351
    assertTrue(checkRevIvl(col, c, 351));
    assertEquals(col.getSched().getToday() + c.getIvl(), c.getDue());
    // factor should have been increased
    assertEquals(2650, c.getFactor());
}
Also used : Note(com.ichi2.libanki.Note) JSONArray(com.ichi2.utils.JSONArray) Collection(com.ichi2.libanki.Collection) DeckConfig(com.ichi2.libanki.DeckConfig) Card(com.ichi2.libanki.Card) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 27 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class ModelFieldEditor method renameFieldDialog.

/*
     * Creates a dialog to rename the currently selected field
     * Processing time is constant
     */
private void renameFieldDialog() {
    mFieldNameInput = new FixedEditText(this);
    mFieldNameInput.setSingleLine(true);
    mFieldNameInput.setText(mFieldLabels.get(mCurrentPos));
    mFieldNameInput.setSelection(mFieldNameInput.getText().length());
    new MaterialEditTextDialog.Builder(this, mFieldNameInput).title(R.string.model_field_editor_rename).positiveText(R.string.rename).onPositive((dialog, which) -> {
        String fieldName = _uniqueName(mFieldNameInput);
        if (fieldName == null) {
            return;
        }
        // Field is valid, now rename
        try {
            renameField();
        } catch (ConfirmModSchemaException e) {
            e.log();
            // Handler mod schema confirmation
            ConfirmationDialog c = new ConfirmationDialog();
            c.setArgs(getResources().getString(R.string.full_sync_confirmation));
            Runnable confirm = () -> {
                mCol.modSchemaNoCheck();
                try {
                    renameField();
                } catch (ConfirmModSchemaException e1) {
                    e1.log();
                // This should never be thrown
                }
                dismissContextMenu();
            };
            c.setConfirm(confirm);
            c.setCancel(mConfirmDialogCancel);
            ModelFieldEditor.this.showDialogFragment(c);
        }
    }).negativeText(R.string.dialog_cancel).show();
}
Also used : ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) FixedEditText(com.ichi2.ui.FixedEditText) ConfirmationDialog(com.ichi2.anki.dialogs.ConfirmationDialog)

Example 28 with Time

use of com.ichi2.libanki.utils.Time 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 29 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class Utils method markAsUploaded.

/**
 *       Set usn to 0 in every object.
 *
 *       This method is called during full sync, before uploading, so
 *       during an instant, the value will be zero while the object is
 *       not actually online. This is not a problem because if the sync
 *       fails, a full sync will occur again next time.
 *
 *       @return whether there was a non-zero usn; in this case the list
 *       should be saved before the upload.
 */
public static boolean markAsUploaded(List<? extends JSONObject> ar) {
    boolean changed = false;
    for (JSONObject obj : ar) {
        if (obj.optInt("usn", 1) != 0) {
            obj.put("usn", 0);
            changed = true;
        }
    }
    return changed;
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Example 30 with Time

use of com.ichi2.libanki.utils.Time 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)

Aggregations

Test (org.junit.Test)27 Collection (com.ichi2.libanki.Collection)26 JSONObject (com.ichi2.utils.JSONObject)26 RobolectricTest (com.ichi2.anki.RobolectricTest)19 Card (com.ichi2.libanki.Card)19 Note (com.ichi2.libanki.Note)15 JSONArray (com.ichi2.utils.JSONArray)15 Deck (com.ichi2.libanki.Deck)11 ArrayList (java.util.ArrayList)11 DeckConfig (com.ichi2.libanki.DeckConfig)10 IOException (java.io.IOException)10 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)9 HashMap (java.util.HashMap)9 Cursor (android.database.Cursor)8 Nullable (androidx.annotation.Nullable)8 JSONException (com.ichi2.utils.JSONException)8 SharedPreferences (android.content.SharedPreferences)7 Resources (android.content.res.Resources)7 File (java.io.File)7 View (android.view.View)5