Search in sources :

Example 61 with Models

use of com.ichi2.libanki.Models in project AnkiChinaAndroid by ankichinateam.

the class ModelTest method test_req.

@Test
public void test_req() {
    Collection col = getCol();
    Models mm = col.getModels();
    Model basic = mm.byName("Basic");
    assertTrue(basic.has("req"));
    reqSize(basic);
    JSONArray r = basic.getJSONArray("req").getJSONArray(0);
    assertEquals(0, r.getInt(0));
    assertTrue(Arrays.asList(new String[] { "any", "all" }).contains(r.getString(1)));
    assertEquals(1, r.getJSONArray(2).length());
    assertEquals(0, r.getJSONArray(2).getInt(0));
    Model opt = mm.byName("Basic (optional reversed card)");
    reqSize(opt);
    r = opt.getJSONArray("req").getJSONArray(0);
    assertTrue(Arrays.asList(new String[] { "any", "all" }).contains(r.getString(1)));
    assertEquals(1, r.getJSONArray(2).length());
    assertEquals(0, r.getJSONArray(2).getInt(0));
    assertEquals(new JSONArray("[1,\"all\",[1,2]]"), opt.getJSONArray("req").getJSONArray(1));
    // testing any
    opt.getJSONArray("tmpls").getJSONObject(1).put("qfmt", "{{Back}}{{Add Reverse}}");
    mm.save(opt, true);
    assertEquals(new JSONArray("[1, \"any\", [1, 2]]"), opt.getJSONArray("req").getJSONArray(1));
    // testing null
    opt.getJSONArray("tmpls").getJSONObject(1).put("qfmt", "{{^Add Reverse}}{{/Add Reverse}}");
    mm.save(opt, true);
    assertEquals(new JSONArray("[1, \"none\", []]"), opt.getJSONArray("req").getJSONArray(1));
    opt = mm.byName("Basic (type in the answer)");
    reqSize(opt);
    r = opt.getJSONArray("req").getJSONArray(0);
    assertTrue(Arrays.asList(new String[] { "any", "all" }).contains(r.getString(1)));
    // TODO: Port anki@4e33775ed4346ef136ece6ef5efec5ba46057c6b
    assertEquals(new JSONArray("[0]"), r.getJSONArray(2));
}
Also used : JSONArray(com.ichi2.utils.JSONArray) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 62 with Models

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

the class ContentProviderTest method testInsertTemplate.

/**
 * Check that inserting and removing a note into default deck works as expected
 */
@Test
public void testInsertTemplate() throws Exception {
    // Get required objects for test
    final ContentResolver cr = getContentResolver();
    Collection col = getCol();
    // Add a new basic model that we use for testing purposes (existing models could potentially be corrupted)
    Model model = StdModels.BASIC_MODEL.add(col, BASIC_MODEL_NAME);
    long modelId = model.getLong("id");
    // Add the note
    Uri modelUri = ContentUris.withAppendedId(FlashCardsContract.Model.CONTENT_URI, modelId);
    // choose the last one because not the same as the basic model template
    int testIndex = TEST_MODEL_CARDS.length - 1;
    int expectedOrd = model.getJSONArray("tmpls").length();
    ContentValues cv = new ContentValues();
    cv.put(FlashCardsContract.CardTemplate.NAME, TEST_MODEL_CARDS[testIndex]);
    cv.put(FlashCardsContract.CardTemplate.QUESTION_FORMAT, TEST_MODEL_QFMT[testIndex]);
    cv.put(FlashCardsContract.CardTemplate.ANSWER_FORMAT, TEST_MODEL_AFMT[testIndex]);
    cv.put(FlashCardsContract.CardTemplate.BROWSER_QUESTION_FORMAT, TEST_MODEL_QFMT[testIndex]);
    cv.put(FlashCardsContract.CardTemplate.BROWSER_ANSWER_FORMAT, TEST_MODEL_AFMT[testIndex]);
    Uri templatesUri = Uri.withAppendedPath(modelUri, "templates");
    Uri templateUri = cr.insert(templatesUri, cv);
    // test that the changes are physically saved to the DB
    col = reopenCol();
    assertNotNull("Check template uri", templateUri);
    assertEquals("Check template uri ord", expectedOrd, ContentUris.parseId(templateUri));
    model = col.getModels().get(modelId);
    assertNotNull("Check model", model);
    JSONObject template = model.getJSONArray("tmpls").getJSONObject(expectedOrd);
    assertEquals("Check template JSONObject ord", expectedOrd, template.getInt("ord"));
    assertEquals("Check template name", TEST_MODEL_CARDS[testIndex], template.getString("name"));
    assertEquals("Check qfmt", TEST_MODEL_QFMT[testIndex], template.getString("qfmt"));
    assertEquals("Check afmt", TEST_MODEL_AFMT[testIndex], template.getString("afmt"));
    assertEquals("Check bqfmt", TEST_MODEL_QFMT[testIndex], template.getString("bqfmt"));
    assertEquals("Check bafmt", TEST_MODEL_AFMT[testIndex], template.getString("bafmt"));
    col.getModels().rem(model);
}
Also used : ContentValues(android.content.ContentValues) JSONObject(com.ichi2.utils.JSONObject) Model(com.ichi2.libanki.Model) Collection(com.ichi2.libanki.Collection) Uri(android.net.Uri) ContentResolver(android.content.ContentResolver) Test(org.junit.Test)

Example 63 with Models

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

the class Syncer method getModels.

/**
 * Models ********************************************************************
 */
private JSONArray getModels() {
    JSONArray result = new JSONArray();
    if (mCol.getServer()) {
        for (JSONObject m : mCol.getModels().all()) {
            if (m.getInt("usn") >= mMinUsn) {
                result.put(m);
            }
        }
    } else {
        for (JSONObject m : mCol.getModels().all()) {
            if (m.getInt("usn") == -1) {
                m.put("usn", mMaxUsn);
                result.put(m);
            }
        }
        mCol.getModels().save();
    }
    return result;
}
Also used : JSONObject(com.ichi2.utils.JSONObject) JSONArray(com.ichi2.utils.JSONArray)

Example 64 with Models

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

the class SchedV2Test method test_new_v2.

@Test
public void test_new_v2() throws Exception {
    Collection col = getColV2();
    col.reset();
    assertEquals(0, col.getSched().newCount());
    // add a note
    Note note = col.newNote();
    note.setItem("Front", "one");
    note.setItem("Back", "two");
    col.addNote(note);
    col.reset();
    assertEquals(1, col.getSched().newCount());
    // fetch it
    Card c = getCard();
    assertNotNull(c);
    assertEquals(QUEUE_TYPE_NEW, c.getQueue());
    assertEquals(CARD_TYPE_NEW, c.getType());
    // if we answer it, it should become a learn card
    long t = col.getTime().intTime();
    col.getSched().answerCard(c, BUTTON_ONE);
    assertEquals(QUEUE_TYPE_LRN, c.getQueue());
    assertEquals(CARD_TYPE_LRN, c.getType());
    assertThat(c.getDue(), is(greaterThanOrEqualTo(t)));
// disabled for now, as the learn fudging makes this randomly fail
// // the default order should ensure siblings are not seen together, and
// // should show all cards
// Model m = col.getModels().current(); Models mm = col.getModels()
// JSONObject t = mm.newTemplate("Reverse")
// t['qfmt'] = "{{Back}}"
// t['afmt'] = "{{Front}}"
// mm.addTemplateModChanged(m, t)
// mm.save(m)
// note = col.newNote()
// note['Front'] = u"2"; note['Back'] = u"2"
// col.addNote(note)
// note = col.newNote()
// note['Front'] = u"3"; note['Back'] = u"3"
// col.addNote(note)
// col.reset()
// qs = ("2", "3", "2", "3")
// for (int n = 0; n < 4; n++) {
// c = getCard()
// assertTrue(qs[n] in c.q())
// col.getSched().answerCard(c, BUTTON_TWO)
// }
}
Also used : Note(com.ichi2.libanki.Note) Collection(com.ichi2.libanki.Collection) Card(com.ichi2.libanki.Card) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 65 with Models

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

the class Collection method fixIntegrity.

/**
 * Fix possible problems and rebuild caches.
 */
public CheckDatabaseResult fixIntegrity(TaskManager.ProgressCallback<String> progressCallback) {
    File file = new File(mPath);
    CheckDatabaseResult result = new CheckDatabaseResult(file.length());
    final int[] currentTask = { 1 };
    // a few fixes are in all-models loops, the rest are one-offs
    int totalTasks = (getModels().all().size() * 4) + 27;
    Runnable notifyProgress = () -> fixIntegrityProgress(progressCallback, currentTask[0]++, totalTasks);
    Consumer<FunctionalInterfaces.FunctionThrowable<Runnable, List<String>, JSONException>> executeIntegrityTask = function -> {
        // DEFECT: notifyProgress will lag if an exception is thrown.
        try {
            mDb.getDatabase().beginTransaction();
            result.addAll(function.apply(notifyProgress));
            mDb.getDatabase().setTransactionSuccessful();
        } catch (Exception e) {
            Timber.e(e, "Failed to execute integrity check");
            AnkiDroidApp.sendExceptionReport(e, "fixIntegrity");
        } finally {
            try {
                mDb.getDatabase().endTransaction();
            } catch (Exception e) {
                Timber.e(e, "Failed to end integrity check transaction");
                AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - endTransaction");
            }
        }
    };
    try {
        mDb.getDatabase().beginTransaction();
        save();
        notifyProgress.run();
        if (!mDb.getDatabase().isDatabaseIntegrityOk()) {
            return result.markAsFailed();
        }
        mDb.getDatabase().setTransactionSuccessful();
    } catch (SQLiteDatabaseLockedException ex) {
        Timber.w(ex, "doInBackgroundCheckDatabase - Database locked");
        return result.markAsLocked();
    } catch (RuntimeException e) {
        Timber.e(e, "doInBackgroundCheckDatabase - RuntimeException on marking card");
        AnkiDroidApp.sendExceptionReport(e, "doInBackgroundCheckDatabase");
        return result.markAsFailed();
    } finally {
        // if the database was locked, we never got the transaction.
        if (mDb.getDatabase().inTransaction()) {
            mDb.getDatabase().endTransaction();
        }
    }
    executeIntegrityTask.accept(this::deleteNotesWithMissingModel);
    // for each model
    for (Model m : getModels().all()) {
        executeIntegrityTask.accept((callback) -> deleteCardsWithInvalidModelOrdinals(callback, m));
        executeIntegrityTask.accept((callback) -> deleteNotesWithWrongFieldCounts(callback, m));
    }
    executeIntegrityTask.accept(this::deleteNotesWithMissingCards);
    executeIntegrityTask.accept(this::deleteCardsWithMissingNotes);
    executeIntegrityTask.accept(this::removeOriginalDuePropertyWhereInvalid);
    executeIntegrityTask.accept(this::removeDynamicPropertyFromNonDynamicDecks);
    executeIntegrityTask.accept(this::removeDeckOptionsFromDynamicDecks);
    executeIntegrityTask.accept(this::resetInvalidDeckOptions);
    executeIntegrityTask.accept(this::rebuildTags);
    executeIntegrityTask.accept(this::updateFieldCache);
    executeIntegrityTask.accept(this::fixNewCardDuePositionOverflow);
    executeIntegrityTask.accept(this::resetNewCardInsertionPosition);
    executeIntegrityTask.accept(this::fixExcessiveReviewDueDates);
    // v2 sched had a bug that could create decimal intervals
    executeIntegrityTask.accept(this::fixDecimalCardsData);
    executeIntegrityTask.accept(this::fixDecimalRevLogData);
    executeIntegrityTask.accept(this::restoreMissingDatabaseIndices);
    executeIntegrityTask.accept(this::ensureModelsAreNotEmpty);
    executeIntegrityTask.accept((progressNotifier) -> this.ensureCardsHaveHomeDeck(progressNotifier, result));
    // and finally, optimize (unable to be done inside transaction).
    try {
        optimize(notifyProgress);
    } catch (Exception e) {
        Timber.e(e, "optimize");
        AnkiDroidApp.sendExceptionReport(e, "fixIntegrity - optimize");
    }
    file = new File(mPath);
    long newSize = file.length();
    result.setNewSize(newSize);
    // if any problems were found, force a full sync
    if (result.hasProblems()) {
        modSchemaNoCheck();
    }
    logProblems(result.getProblems());
    return result;
}
Also used : TemplateRenderOutput(com.ichi2.libanki.TemplateManager.TemplateRenderContext.TemplateRenderOutput) Arrays(java.util.Arrays) TaskManager(com.ichi2.async.TaskManager) NonNull(androidx.annotation.NonNull) UsageAnalytics(com.ichi2.anki.analytics.UsageAnalytics) AbstractSched(com.ichi2.libanki.sched.AbstractSched) Random(java.util.Random) DroidBackend(com.ichi2.libanki.backend.DroidBackend) Time(com.ichi2.libanki.utils.Time) FunctionalInterfaces(com.ichi2.utils.FunctionalInterfaces) ParsedNode(com.ichi2.libanki.template.ParsedNode) KotlinCleanup(com.ichi2.utils.KotlinCleanup) SupportSQLiteDatabase(androidx.sqlite.db.SupportSQLiteDatabase) Locale(java.util.Locale) UIUtils(com.ichi2.anki.UIUtils) Map(java.util.Map) CancelListener.isCancelled(com.ichi2.async.CancelListener.isCancelled) JSONException(com.ichi2.utils.JSONException) SQLiteDatabaseLockedException(android.database.sqlite.SQLiteDatabaseLockedException) PrintWriter(java.io.PrintWriter) Upgrade(com.ichi2.upgrade.Upgrade) HashUtil(com.ichi2.utils.HashUtil) GregorianCalendar(java.util.GregorianCalendar) Set(java.util.Set) JSONObject(com.ichi2.utils.JSONObject) Timber(timber.log.Timber) CancelListener(com.ichi2.async.CancelListener) Contract(org.jetbrains.annotations.Contract) List(java.util.List) BackendNotSupportedException(com.ichi2.libanki.backend.exception.BackendNotSupportedException) Nullable(androidx.annotation.Nullable) AnkiDroidApp(com.ichi2.anki.AnkiDroidApp) ContentValues(android.content.ContentValues) UnknownDatabaseVersionException(com.ichi2.libanki.exception.UnknownDatabaseVersionException) Pattern(java.util.regex.Pattern) VersionUtils(com.ichi2.utils.VersionUtils) RustCleanup(net.ankiweb.rsdroid.RustCleanup) Context(android.content.Context) Pair(android.util.Pair) R(com.ichi2.anki.R) HashMap(java.util.HashMap) Sched(com.ichi2.libanki.sched.Sched) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) SuppressLint(android.annotation.SuppressLint) JSONArray(com.ichi2.utils.JSONArray) Calendar(java.util.Calendar) ProgressSender(com.ichi2.async.ProgressSender) ChessFilter(com.ichi2.libanki.hooks.ChessFilter) SupportSQLiteStatement(androidx.sqlite.db.SupportSQLiteStatement) Cursor(android.database.Cursor) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) CheckResult(androidx.annotation.CheckResult) BufferedWriter(java.io.BufferedWriter) FileWriter(java.io.FileWriter) SchedV2(com.ichi2.libanki.sched.SchedV2) TextUtils(android.text.TextUtils) CollectionTask(com.ichi2.async.CollectionTask) TemplateError(com.ichi2.libanki.template.TemplateError) IOException(java.io.IOException) File(java.io.File) Consumer(java.util.function.Consumer) NoSuchDeckException(com.ichi2.libanki.exception.NoSuchDeckException) LinkedBlockingDeque(java.util.concurrent.LinkedBlockingDeque) Collections(java.util.Collections) VisibleForTesting(androidx.annotation.VisibleForTesting) Resources(android.content.res.Resources) SQLiteDatabaseLockedException(android.database.sqlite.SQLiteDatabaseLockedException) SuppressLint(android.annotation.SuppressLint) JSONException(com.ichi2.utils.JSONException) SQLiteDatabaseLockedException(android.database.sqlite.SQLiteDatabaseLockedException) BackendNotSupportedException(com.ichi2.libanki.backend.exception.BackendNotSupportedException) UnknownDatabaseVersionException(com.ichi2.libanki.exception.UnknownDatabaseVersionException) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) IOException(java.io.IOException) NoSuchDeckException(com.ichi2.libanki.exception.NoSuchDeckException) File(java.io.File)

Aggregations

JSONObject (com.ichi2.utils.JSONObject)48 Model (com.ichi2.libanki.Model)28 JSONArray (com.ichi2.utils.JSONArray)26 Test (org.junit.Test)26 Collection (com.ichi2.libanki.Collection)25 RobolectricTest (com.ichi2.anki.RobolectricTest)16 Note (com.ichi2.libanki.Note)16 JSONException (com.ichi2.utils.JSONException)13 ArrayList (java.util.ArrayList)13 Card (com.ichi2.libanki.Card)11 Models (com.ichi2.libanki.Models)11 SuppressLint (android.annotation.SuppressLint)10 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)7 ModelManager (com.ichi2.libanki.ModelManager)7 File (java.io.File)6 HashMap (java.util.HashMap)6 List (java.util.List)6 Map (java.util.Map)6 ContentValues (android.content.ContentValues)5 NonNull (androidx.annotation.NonNull)5