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));
}
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);
}
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;
}
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)
// }
}
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;
}
Aggregations