use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class DeckPickerTest method notEnoughSpaceToBackupBeforeDowngradeShowsError.
@Test
public void notEnoughSpaceToBackupBeforeDowngradeShowsError() {
Class<DeckPickerNoSpaceForBackup> clazz = DeckPickerNoSpaceForBackup.class;
try (MockedStatic<InitialActivity> initialActivityMock = mockStatic(InitialActivity.class, Mockito.CALLS_REAL_METHODS)) {
initialActivityMock.when(() -> InitialActivity.getStartupFailureType(any())).thenAnswer((Answer<InitialActivity.StartupFailure>) invocation -> InitialActivity.StartupFailure.DATABASE_DOWNGRADE_REQUIRED);
InitialActivityWithConflictTest.setupForValid(getTargetContext());
DeckPickerNoSpaceForBackup deckPicker = super.startActivityNormallyOpenCollectionWithIntent(clazz, new Intent());
assertThat("A downgrade failed dialog should be shown", deckPicker.mDisplayedDowngradeFailed, is(true));
} finally {
InitialActivityWithConflictTest.setupForDefault();
}
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class CardContentProvider method insert.
@Override
public Uri insert(@NonNull Uri uri, ContentValues values) {
if (!hasReadWritePermission() && shouldEnforceQueryOrInsertSecurity()) {
throwSecurityException("insert", uri);
}
Collection col = CollectionHelper.getInstance().getCol(mContext);
if (col == null) {
throw new IllegalStateException(COL_NULL_ERROR_MSG);
}
col.log(getLogMessage("insert", uri));
// Find out what data the user is requesting
int match = sUriMatcher.match(uri);
switch(match) {
case NOTES:
{
/* Insert new note with specified fields and tags
*/
Long modelId = values.getAsLong(FlashCardsContract.Note.MID);
String flds = values.getAsString(FlashCardsContract.Note.FLDS);
String tags = values.getAsString(FlashCardsContract.Note.TAGS);
Models.AllowEmpty allowEmpty = Models.AllowEmpty.fromBoolean(values.getAsBoolean(FlashCardsContract.Note.ALLOW_EMPTY));
// Create empty note
com.ichi2.libanki.Note newNote = new com.ichi2.libanki.Note(col, col.getModels().get(modelId));
// Set fields
String[] fldsArray = Utils.splitFields(flds);
// Check that correct number of flds specified
if (fldsArray.length != newNote.getFields().length) {
throw new IllegalArgumentException("Incorrect flds argument : " + flds);
}
for (int idx = 0; idx < fldsArray.length; idx++) {
newNote.setField(idx, fldsArray[idx]);
}
// Set tags
if (tags != null) {
newNote.setTagsFromStr(tags);
}
// Add to collection
col.addNote(newNote, allowEmpty);
col.save();
return Uri.withAppendedPath(FlashCardsContract.Note.CONTENT_URI, Long.toString(newNote.getId()));
}
case NOTES_ID:
// Note ID is generated automatically by libanki
throw new IllegalArgumentException("Not possible to insert note with specific ID");
case NOTES_ID_CARDS:
case NOTES_ID_CARDS_ORD:
// Cards are generated automatically by libanki
throw new IllegalArgumentException("Not possible to insert cards directly (only through NOTES)");
case MODELS:
// Get input arguments
String modelName = values.getAsString(FlashCardsContract.Model.NAME);
String css = values.getAsString(FlashCardsContract.Model.CSS);
Long did = values.getAsLong(FlashCardsContract.Model.DECK_ID);
String fieldNames = values.getAsString(FlashCardsContract.Model.FIELD_NAMES);
Integer numCards = values.getAsInteger(FlashCardsContract.Model.NUM_CARDS);
Integer sortf = values.getAsInteger(FlashCardsContract.Model.SORT_FIELD_INDEX);
Integer type = values.getAsInteger(FlashCardsContract.Model.TYPE);
String latexPost = values.getAsString(FlashCardsContract.Model.LATEX_POST);
String latexPre = values.getAsString(FlashCardsContract.Model.LATEX_PRE);
// Throw exception if required fields empty
if (modelName == null || fieldNames == null || numCards == null) {
throw new IllegalArgumentException("Model name, field_names, and num_cards can't be empty");
}
if (did != null && col.getDecks().isDyn(did)) {
throw new IllegalArgumentException("Cannot set a filtered deck as default deck for a model");
}
// Create a new model
ModelManager mm = col.getModels();
Model newModel = mm.newModel(modelName);
try {
// Add the fields
String[] allFields = Utils.splitFields(fieldNames);
for (String f : allFields) {
mm.addFieldInNewModel(newModel, mm.newField(f));
}
// Add some empty card templates
for (int idx = 0; idx < numCards; idx++) {
String card_name = mContext.getResources().getString(R.string.card_n_name, idx + 1);
JSONObject t = Models.newTemplate(card_name);
t.put("qfmt", String.format("{{%s}}", allFields[0]));
String answerField = allFields[0];
if (allFields.length > 1) {
answerField = allFields[1];
}
t.put("afmt", String.format("{{FrontSide}}\\n\\n<hr id=answer>\\n\\n{{%s}}", answerField));
mm.addTemplateInNewModel(newModel, t);
}
// Add the CSS if specified
if (css != null) {
newModel.put("css", css);
}
// Add the did if specified
if (did != null) {
newModel.put("did", did);
}
if (sortf != null && sortf < allFields.length) {
newModel.put("sortf", sortf);
}
if (type != null) {
newModel.put("type", type);
}
if (latexPost != null) {
newModel.put("latexPost", latexPost);
}
if (latexPre != null) {
newModel.put("latexPre", latexPre);
}
// Add the model to collection (from this point on edits will require a full-sync)
mm.add(newModel);
col.save();
// Get the mid and return a URI
String mid = Long.toString(newModel.getLong("id"));
return Uri.withAppendedPath(FlashCardsContract.Model.CONTENT_URI, mid);
} catch (JSONException e) {
Timber.e(e, "Could not set a field of new model %s", modelName);
return null;
}
case MODELS_ID:
// Model ID is generated automatically by libanki
throw new IllegalArgumentException("Not possible to insert model with specific ID");
case MODELS_ID_TEMPLATES:
{
ModelManager models = col.getModels();
Long mid = getModelIdFromUri(uri, col);
Model existingModel = models.get(mid);
if (existingModel == null) {
throw new IllegalArgumentException("model missing: " + mid);
}
String name = values.getAsString(CardTemplate.NAME);
String qfmt = values.getAsString(CardTemplate.QUESTION_FORMAT);
String afmt = values.getAsString(CardTemplate.ANSWER_FORMAT);
String bqfmt = values.getAsString(CardTemplate.BROWSER_QUESTION_FORMAT);
String bafmt = values.getAsString(CardTemplate.BROWSER_ANSWER_FORMAT);
try {
JSONObject t = Models.newTemplate(name);
t.put("qfmt", qfmt);
t.put("afmt", afmt);
t.put("bqfmt", bqfmt);
t.put("bafmt", bafmt);
models.addTemplate(existingModel, t);
models.save(existingModel);
col.save();
return ContentUris.withAppendedId(uri, t.getInt("ord"));
} catch (ConfirmModSchemaException e) {
throw new IllegalArgumentException("Unable to add template without user requesting/accepting full-sync", e);
} catch (JSONException e) {
throw new IllegalArgumentException("Unable to get ord from new template", e);
}
}
case MODELS_ID_TEMPLATES_ID:
throw new IllegalArgumentException("Not possible to insert template with specific ORD");
case MODELS_ID_FIELDS:
{
ModelManager models = col.getModels();
long mid = getModelIdFromUri(uri, col);
Model existingModel = models.get(mid);
if (existingModel == null) {
throw new IllegalArgumentException("model missing: " + mid);
}
String name = values.getAsString(FlashCardsContract.Model.FIELD_NAME);
if (name == null) {
throw new IllegalArgumentException("field name missing for model: " + mid);
}
JSONObject field = models.newField(name);
try {
models.addField(existingModel, field);
col.save();
JSONArray flds = existingModel.getJSONArray("flds");
return ContentUris.withAppendedId(uri, flds.length() - 1);
} catch (ConfirmModSchemaException e) {
throw new IllegalArgumentException("Unable to insert field: " + name, e);
} catch (JSONException e) {
throw new IllegalArgumentException("Unable to get newly created field: " + name, e);
}
}
case SCHEDULE:
// Doesn't make sense to insert an object into the schedule table
throw new IllegalArgumentException("Not possible to perform insert operation on schedule");
case DECKS:
// Insert new deck with specified name
String deckName = values.getAsString(FlashCardsContract.Deck.DECK_NAME);
did = col.getDecks().id_for_name(deckName);
if (did != null) {
throw new IllegalArgumentException("Deck name already exists: " + deckName);
}
if (!Decks.isValidDeckName(deckName)) {
throw new IllegalArgumentException("Invalid deck name '" + deckName + "'");
}
try {
did = col.getDecks().id(deckName);
} catch (DeckRenameException filteredSubdeck) {
throw new IllegalArgumentException(filteredSubdeck.getMessage());
}
Deck deck = col.getDecks().get(did);
if (deck != null) {
try {
String deckDesc = values.getAsString(FlashCardsContract.Deck.DECK_DESC);
if (deckDesc != null) {
deck.put("desc", deckDesc);
}
} catch (JSONException e) {
Timber.e(e, "Could not set a field of new deck %s", deckName);
return null;
}
}
col.getDecks().flush();
return Uri.withAppendedPath(FlashCardsContract.Deck.CONTENT_ALL_URI, Long.toString(did));
case DECK_SELECTED:
// Can't have more than one selected deck
throw new IllegalArgumentException("Selected deck can only be queried and updated");
case DECKS_ID:
// Deck ID is generated automatically by libanki
throw new IllegalArgumentException("Not possible to insert deck with specific ID");
case MEDIA:
// contentvalue should have data and preferredFileName values
return insertMediaFile(values, col);
default:
// Unknown URI type
throw new IllegalArgumentException("uri " + uri + " is not supported");
}
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class ReviewerTest method jsTime4ShouldBeBlankIfButtonUnavailable.
@Test
public void jsTime4ShouldBeBlankIfButtonUnavailable() {
// #6623 - easy should be blank when displaying a card with 3 buttons (after displaying a review)
Note firstNote = addNoteUsingBasicModel("Hello", "World");
moveToReviewQueue(firstNote.firstCard());
addNoteUsingBasicModel("Hello", "World2");
Reviewer reviewer = startReviewer();
AnkiDroidJsAPI javaScriptFunction = reviewer.javaScriptFunction();
// The answer needs to be displayed to be able to get the time.
displayAnswer(reviewer);
assertThat("4 buttons should be displayed", reviewer.getAnswerButtonCount(), is(4));
String nextTime = javaScriptFunction.ankiGetNextTime4();
assertThat(nextTime, not(emptyString()));
// Display the next answer
reviewer.answerCard(Consts.BUTTON_FOUR);
displayAnswer(reviewer);
if (schedVersion == 1) {
assertThat("The 4th button should not be visible", reviewer.getAnswerButtonCount(), is(3));
String learnTime = javaScriptFunction.ankiGetNextTime4();
assertThat("If the 4th button is not visible, there should be no time4 in JS", learnTime, emptyString());
}
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class OverviewStatsBuilderTest method testInfoHtmlStringMonth.
@Test
@Config(qualifiers = "en")
public void testInfoHtmlStringMonth() {
OverviewStatsBuilder statsTester = new OverviewStatsBuilder(new WebView(getTargetContext()), getCol(), 42L, Stats.AxisType.TYPE_MONTH);
String HTML = statsTester.createInfoHtmlString();
assertEquals(HTML, "<center><style>\n" + "h1, h3 { margin-bottom: 0; margin-top: 1em; text-transform: capitalize; }\n" + ".pielabel { text-align:center; padding:0px; color:white; }\n" + "body {color:#FFFFFF;}\n" + "</style><h1>Today</h1>Studied <b>0 cards</b> in <b>0 minutes</b> today<br>Again count: <b>0</b><br>Learn: <b>0</b>, review: <b>0</b>, relearn: <b>0</b>, filtered: <b>0</b><br>No mature cards were studied today<h1>1 month</h1><h3>FORECAST</h3>Total: <b>0</b> reviews<br>Average: <b>0.0</b> reviews/day<br>Due tomorrow: <b>0</b><br><h3>REVIEW COUNT</h3>Days studied: <b>0%</b> (0 of 30)<br>Total: <b>0</b> reviews<br>Average for days studied: <b>0.0</b> reviews/day<br>If you studied every day: <b>0.0</b> reviews/day<br><h3>REVIEW TIME</h3>Days studied: <b>0%</b> (0 of 30)<br>Total: <b>0</b> minutes<br>Average for days studied: <b>0.0</b> minutes/day<br>If you studied every day: <b>0.0</b> minutes/day<br>Average answer time: <b>0.0s</b> (<b>0.00</b> cards/minute)<br><h3>ADDED</h3>Total: <b>0</b> cards<br>Average: <b>0.0</b> cards/day<br><h3>INTERVALS</h3>Average interval: <b>0.0</b> hours<br>Longest interval: <b>0.0</b> hours<h3>ANSWER BUTTONS</h3>Learning: <b>0.00%</b> correct (0 of 0)<br>Young: <b>0.00%</b> correct (0 of 0)<br>Mature: <b>0.00%</b> correct (0 of 0)<h3>CARD TYPES</h3>Total cards: <b>0</b><br>Total notes: <b>0</b><br>Lowest ease: <b>0%</b><br>Average ease: <b>0%</b><br>Highest ease: <b>0%</b></center>");
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class ModelTest method test_req.
@Test
public void test_req() {
Collection col = getCol();
ModelManager 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[] { REQ_ANY, REQ_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[] { REQ_ANY, REQ_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[] { REQ_ANY, REQ_ALL }).contains(r.getString(1)));
if (col.getModels() instanceof ModelsV16) {
assertEquals(new JSONArray("[0, 1]"), r.getJSONArray(2));
} else {
// TODO: Port anki@4e33775ed4346ef136ece6ef5efec5ba46057c6b
assertEquals(new JSONArray("[0]"), r.getJSONArray(2));
}
}
Aggregations