use of com.ichi2.anki.reviewer.AnswerButtons in project Anki-Android by ankidroid.
the class AbstractFlashcardViewer method answerCard.
protected void answerCard(@Consts.BUTTON_TYPE int ease) {
if (mInAnswer) {
return;
}
mIsSelecting = false;
int buttonNumber = getCol().getSched().answerButtons(mCurrentCard);
// Detect invalid ease for current card (e.g. by using keyboard shortcut or gesture).
if (buttonNumber < ease) {
return;
}
// Temporarily sets the answer indicator dots appearing below the toolbar
mPreviousAnswerIndicator.displayAnswerIndicator(ease, buttonNumber);
mSoundPlayer.stopSounds();
mCurrentEase = ease;
new SchedulerService.AnswerAndGetCard(mCurrentCard, mCurrentEase).runWithHandler(answerCardHandler(true));
}
use of com.ichi2.anki.reviewer.AnswerButtons in project Anki-Android by ankidroid.
the class Reviewer method setFullScreen.
// #9332: UI Visibility -> Insets
@SuppressWarnings("deprecation")
private void setFullScreen(final AbstractFlashcardViewer a) {
// Set appropriate flags to enable Sticky Immersive mode.
a.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_STABLE | // | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION // temporarily disabled due to #5245
View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_LOW_PROFILE | View.SYSTEM_UI_FLAG_IMMERSIVE);
// Show / hide the Action bar together with the status bar
SharedPreferences prefs = AnkiDroidApp.getSharedPrefs(a);
FullScreenMode fullscreenMode = FullScreenMode.fromPreference(prefs);
a.getWindow().setStatusBarColor(Themes.getColorFromAttr(a, R.attr.colorPrimaryDark));
View decorView = a.getWindow().getDecorView();
decorView.setOnSystemUiVisibilityChangeListener(flags -> {
final View toolbar = a.findViewById(R.id.toolbar);
final View answerButtons = a.findViewById(R.id.answer_options_layout);
final View topbar = a.findViewById(R.id.top_bar);
if (toolbar == null || topbar == null || answerButtons == null) {
return;
}
// Note that system bars will only be "visible" if none of the
// LOW_PROFILE, HIDE_NAVIGATION, or FULLSCREEN flags are set.
boolean visible = (flags & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
Timber.d("System UI visibility change. Visible: %b", visible);
if (visible) {
showViewWithAnimation(toolbar);
if (fullscreenMode.equals(FullScreenMode.FULLSCREEN_ALL_GONE)) {
showViewWithAnimation(topbar);
showViewWithAnimation(answerButtons);
}
} else {
hideViewWithAnimation(toolbar);
if (fullscreenMode.equals(FullScreenMode.FULLSCREEN_ALL_GONE)) {
hideViewWithAnimation(topbar);
hideViewWithAnimation(answerButtons);
}
}
});
}
use of com.ichi2.anki.reviewer.AnswerButtons in project AnkiChinaAndroid by ankichinateam.
the class CardContentProvider method query.
@Override
public Cursor query(Uri uri, String[] projection, String selection, String[] selectionArgs, String order) {
if (!hasReadWritePermission() && shouldEnforceQueryOrInsertSecurity()) {
throwSecurityException("query", uri);
}
Collection col = CollectionHelper.getInstance().getCol(mContext);
if (col == null) {
throw new IllegalStateException(COL_NULL_ERROR_MSG);
}
Timber.d(getLogMessage("query", uri));
// Find out what data the user is requesting
int match = sUriMatcher.match(uri);
switch(match) {
case NOTES_V2:
{
/* Search for notes using direct SQL query */
String[] proj = sanitizeNoteProjection(projection);
String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, selection, null, null, order, null);
return col.getDb().getDatabase().query(sql, selectionArgs);
}
case NOTES:
{
/* Search for notes using the libanki browser syntax */
String[] proj = sanitizeNoteProjection(projection);
String query = (selection != null) ? selection : "";
List<Long> noteIds = col.findNotes(query);
if ((noteIds != null) && (!noteIds.isEmpty())) {
String sel = String.format("id in (%s)", TextUtils.join(",", noteIds));
String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, sel, null, null, order, null);
return col.getDb().getDatabase().query(sql);
} else {
return null;
}
}
case NOTES_ID:
{
/* Direct access note with specific ID*/
String noteId = uri.getPathSegments().get(1);
String[] proj = sanitizeNoteProjection(projection);
String sql = SQLiteQueryBuilder.buildQueryString(false, "notes", proj, "id=?", null, null, order, null);
return col.getDb().getDatabase().query(sql, new String[] { noteId });
}
case NOTES_ID_CARDS:
{
Note currentNote = getNoteFromUri(uri, col);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
for (Card currentCard : currentNote.cards()) {
addCardToCursor(currentCard, rv, col, columns);
}
return rv;
}
case NOTES_ID_CARDS_ORD:
{
Card currentCard = getCardFromUri(uri, col);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Card.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
addCardToCursor(currentCard, rv, col, columns);
return rv;
}
case MODELS:
{
Models models = col.getModels();
String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
for (Long modelId : models.getModels().keySet()) {
addModelToCursor(modelId, models, rv, columns);
}
return rv;
}
case MODELS_ID:
{
long modelId = getModelIdFromUri(uri, col);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Model.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
addModelToCursor(modelId, col.getModels(), rv, columns);
return rv;
}
case MODELS_ID_TEMPLATES:
{
/* Direct access model templates */
Models models = col.getModels();
Model currentModel = models.get(getModelIdFromUri(uri, col));
String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
try {
JSONArray templates = currentModel.getJSONArray("tmpls");
for (int idx = 0; idx < templates.length(); idx++) {
JSONObject template = templates.getJSONObject(idx);
addTemplateToCursor(template, currentModel, idx + 1, models, rv, columns);
}
} catch (JSONException e) {
throw new IllegalArgumentException("Model is malformed", e);
}
return rv;
}
case MODELS_ID_TEMPLATES_ID:
{
/* Direct access model template with specific ID */
Models models = col.getModels();
int ord = Integer.parseInt(uri.getLastPathSegment());
Model currentModel = models.get(getModelIdFromUri(uri, col));
String[] columns = ((projection != null) ? projection : CardTemplate.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
try {
JSONObject template = getTemplateFromUri(uri, col);
addTemplateToCursor(template, currentModel, ord + 1, models, rv, columns);
} catch (JSONException e) {
throw new IllegalArgumentException("Model is malformed", e);
}
return rv;
}
case SCHEDULE:
{
String[] columns = ((projection != null) ? projection : FlashCardsContract.ReviewInfo.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
long selectedDeckBeforeQuery = col.getDecks().selected();
long deckIdOfTemporarilySelectedDeck = -1;
// the number of scheduled cards to return
int limit = 1;
int selectionArgIndex = 0;
// parsing the selection arguments
if (selection != null) {
// split selection to get arguments like "limit=?"
String[] args = selection.split(",");
for (String arg : args) {
// split arguments into key ("limit") and value ("?")
String[] keyAndValue = arg.split("=");
try {
// check if value is a placeholder ("?"), if so replace with the next value of selectionArgs
String value = "?".equals(keyAndValue[1].trim()) ? selectionArgs[selectionArgIndex++] : keyAndValue[1];
if ("limit".equals(keyAndValue[0].trim())) {
limit = Integer.valueOf(value);
} else if ("deckID".equals(keyAndValue[0].trim())) {
deckIdOfTemporarilySelectedDeck = Long.valueOf(value);
if (!selectDeckWithCheck(col, deckIdOfTemporarilySelectedDeck)) {
// if the provided deckID is wrong, return empty cursor.
return rv;
}
}
} catch (NumberFormatException nfe) {
nfe.printStackTrace();
}
}
}
// retrieve the number of cards provided by the selection parameter "limit"
col.getSched().deferReset();
for (int k = 0; k < limit; k++) {
Card currentCard = col.getSched().getCard();
if (currentCard == null) {
break;
}
int buttonCount = col.getSched().answerButtons(currentCard);
JSONArray buttonTexts = new JSONArray();
for (int i = 0; i < buttonCount; i++) {
buttonTexts.put(col.getSched().nextIvlStr(mContext, currentCard, i + 1));
}
addReviewInfoToCursor(currentCard, buttonTexts, buttonCount, rv, col, columns);
}
if (deckIdOfTemporarilySelectedDeck != -1) {
// if the selected deck was changed
// change the selected deck back to the one it was before the query
col.getDecks().select(selectedDeckBeforeQuery);
}
return rv;
}
case DECKS:
{
List<DeckDueTreeNode> allDecks = col.getSched().deckDueList();
String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, allDecks.size());
for (DeckDueTreeNode deck : allDecks) {
long id = deck.getDid();
String name = deck.getFullDeckName();
addDeckToCursor(id, name, getDeckCountsFromDueTreeNode(deck), rv, col, columns);
}
return rv;
}
case DECKS_ID:
{
/* Direct access deck */
String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
List<DeckDueTreeNode> allDecks = col.getSched().deckDueList();
long deckId;
deckId = Long.parseLong(uri.getPathSegments().get(1));
for (DeckDueTreeNode deck : allDecks) {
if (deck.getDid() == deckId) {
addDeckToCursor(deckId, deck.getFullDeckName(), getDeckCountsFromDueTreeNode(deck), rv, col, columns);
return rv;
}
}
return rv;
}
case DECK_SELECTED:
{
long id = col.getDecks().selected();
String name = col.getDecks().name(id);
String[] columns = ((projection != null) ? projection : FlashCardsContract.Deck.DEFAULT_PROJECTION);
MatrixCursor rv = new MatrixCursor(columns, 1);
JSONArray counts = new JSONArray(Arrays.asList(col.getSched().counts()));
addDeckToCursor(id, name, counts, rv, col, columns);
return rv;
}
default:
// Unknown URI type
throw new IllegalArgumentException("uri " + uri + " is not supported");
}
}
use of com.ichi2.anki.reviewer.AnswerButtons in project AnkiChinaAndroid by ankichinateam.
the class SchedTest method test_cram.
@Test
public void test_cram() throws Exception {
Collection col = getColV1();
Note note = col.newNote();
note.setItem("Front", "one");
col.addNote(note);
Card c = note.cards().get(0);
c.setIvl(100);
c.setQueue(CARD_TYPE_REV);
c.setType(QUEUE_TYPE_REV);
// due in 25 days, so it's been waiting 75 days
c.setDue(col.getSched().getToday() + 25);
c.setMod(1);
c.setFactor(STARTING_FACTOR);
c.startTimer();
c.flush();
col.reset();
assertArrayEquals(new int[] { 0, 0, 0 }, col.getSched().counts());
Card cardcopy = c.clone();
// create a dynamic deck and refresh it
long did = col.getDecks().newDyn("Cram");
col.getSched().rebuildDyn(did);
col.reset();
// should appear as new in the deck list
// todo: which sort
// and should appear in the counts
assertArrayEquals(new int[] { 1, 0, 0 }, col.getSched().counts());
// grab it and check estimates
c = col.getSched().getCard();
assertEquals(2, col.getSched().answerButtons(c));
assertEquals(600, col.getSched().nextIvl(c, 1));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, 2));
Deck cram = col.getDecks().get(did);
cram.put("delays", new JSONArray(new double[] { 1, 10 }));
col.getDecks().save(cram);
assertEquals(3, col.getSched().answerButtons(c));
assertEquals(60, col.getSched().nextIvl(c, 1));
assertEquals(600, col.getSched().nextIvl(c, 2));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, 3));
col.getSched().answerCard(c, 2);
// elapsed time was 75 days
// factor = 2.5+1.2/2 = 1.85
// int(75*1.85) = 138
assertEquals(138, c.getIvl());
assertEquals(138, c.getODue());
assertEquals(QUEUE_TYPE_LRN, c.getQueue());
// should be logged as a cram rep
assertEquals(3, col.getDb().queryLongScalar("select type from revlog order by id desc limit 1"));
// check ivls again
assertEquals(60, col.getSched().nextIvl(c, 1));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, 2));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, 3));
// when it graduates, due is updated
c = col.getSched().getCard();
col.getSched().answerCard(c, 2);
assertEquals(138, c.getIvl());
assertEquals(138, c.getDue());
assertEquals(QUEUE_TYPE_REV, c.getQueue());
// and it will have moved back to the previous deck
assertEquals(1, c.getDid());
// cram the deck again
col.getSched().rebuildDyn(did);
col.reset();
c = col.getSched().getCard();
// check ivls again - passing should be idempotent
assertEquals(60, col.getSched().nextIvl(c, 1));
assertEquals(600, col.getSched().nextIvl(c, 2));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, 3));
col.getSched().answerCard(c, 2);
assertEquals(138, c.getIvl());
assertEquals(138, c.getODue());
// fail
col.getSched().answerCard(c, 1);
assertEquals(60, col.getSched().nextIvl(c, 1));
assertEquals(600, col.getSched().nextIvl(c, 2));
assertEquals(SECONDS_PER_DAY, col.getSched().nextIvl(c, 3));
// delete the deck, returning the card mid-study
col.getDecks().rem(col.getDecks().selected());
assertEquals(1, col.getSched().deckDueTree().size());
c.load();
assertEquals(1, c.getIvl());
assertEquals(col.getSched().getToday() + 1, c.getDue());
// make it due
col.reset();
assertArrayEquals(new int[] { 0, 0, 0 }, col.getSched().counts());
c.setDue(-5);
c.setIvl(100);
c.flush();
col.reset();
assertArrayEquals(new int[] { 0, 0, 1 }, col.getSched().counts());
// cram again
did = col.getDecks().newDyn("Cram");
col.getSched().rebuildDyn(did);
col.reset();
assertArrayEquals(new int[] { 0, 0, 1 }, col.getSched().counts());
c.load();
assertEquals(4, col.getSched().answerButtons(c));
// add a sibling so we can test minSpace, etc
Card c2 = c.clone();
c2.setId(0);
c2.setOrd(1);
c2.setDue(325);
c2.flush();
// should be able to answer it
c = col.getSched().getCard();
col.getSched().answerCard(c, 4);
// it should have been moved back to the original deck
assertEquals(1, c.getDid());
}
use of com.ichi2.anki.reviewer.AnswerButtons in project Anki-Android by ankidroid.
the class SchedV2Test method test_preview.
@Test
public void test_preview() throws Exception {
// add cards
Collection col = getColV2();
Note note = col.newNote();
note.setItem("Front", "one");
col.addNote(note);
Card c = note.cards().get(0);
Card orig = c.clone();
Note note2 = col.newNote();
note2.setItem("Front", "two");
col.addNote(note2);
// cram deck
long did = addDynamicDeck("Cram");
Deck cram = col.getDecks().get(did);
cram.put("resched", false);
col.getDecks().save(cram);
col.getSched().rebuildDyn(did);
col.reset();
// grab the first card
c = getCard();
assertEquals(2, col.getSched().answerButtons(c));
assertEquals(600, col.getSched().nextIvl(c, BUTTON_ONE));
assertEquals(0, col.getSched().nextIvl(c, BUTTON_TWO));
// failing it will push its due time back
long due = c.getDue();
col.getSched().answerCard(c, BUTTON_ONE);
assertNotEquals(c.getDue(), due);
// the other card should come next
Card c2 = getCard();
assertNotEquals(c2.getId(), c.getId());
// passing it will remove it
col.getSched().answerCard(c2, BUTTON_TWO);
assertEquals(QUEUE_TYPE_NEW, c2.getQueue());
assertEquals(0, c2.getReps());
assertEquals(CARD_TYPE_NEW, c2.getType());
// the other card should appear again
c = getCard();
assertEquals(orig.getId(), c.getId());
// emptying the filtered deck should restore card
col.getSched().emptyDyn(did);
c.load();
assertEquals(QUEUE_TYPE_NEW, c.getQueue());
assertEquals(0, c.getReps());
assertEquals(CARD_TYPE_NEW, c.getType());
}
Aggregations