use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
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(QUEUE_TYPE_REV);
c.setType(CARD_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();
assertEquals(new Counts(0, 0, 0), col.getSched().counts());
Card cardcopy = c.clone();
// create a dynamic deck and refresh it
long did = addDynamicDeck("Cram");
col.getSched().rebuildDyn(did);
col.reset();
// should appear as new in the deck list
// todo: which sort
// and should appear in the counts
assertEquals(new Counts(1, 0, 0), col.getSched().counts());
// grab it and check estimates
c = getCard();
assertEquals(2, col.getSched().answerButtons(c));
assertEquals(600, col.getSched().nextIvl(c, BUTTON_ONE));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, BUTTON_TWO));
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, BUTTON_ONE));
assertEquals(600, col.getSched().nextIvl(c, BUTTON_TWO));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, BUTTON_THREE));
col.getSched().answerCard(c, BUTTON_TWO);
// 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, BUTTON_ONE));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, BUTTON_TWO));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, BUTTON_THREE));
// when it graduates, due is updated
c = getCard();
col.getSched().answerCard(c, BUTTON_TWO);
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 = getCard();
// check ivls again - passing should be idempotent
assertEquals(60, col.getSched().nextIvl(c, BUTTON_ONE));
assertEquals(600, col.getSched().nextIvl(c, BUTTON_TWO));
assertEquals(138 * 60 * 60 * 24, col.getSched().nextIvl(c, BUTTON_THREE));
col.getSched().answerCard(c, BUTTON_TWO);
assertEquals(138, c.getIvl());
assertEquals(138, c.getODue());
// fail
col.getSched().answerCard(c, BUTTON_ONE);
assertEquals(60, col.getSched().nextIvl(c, BUTTON_ONE));
assertEquals(600, col.getSched().nextIvl(c, BUTTON_TWO));
assertEquals(SECONDS_PER_DAY, col.getSched().nextIvl(c, BUTTON_THREE));
// 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();
assertEquals(new Counts(0, 0, 0), col.getSched().counts());
c.setDue(-5);
c.setIvl(100);
c.flush();
col.reset();
assertEquals(new Counts(0, 0, 1), col.getSched().counts());
// cram again
did = addDynamicDeck("Cram");
col.getSched().rebuildDyn(did);
col.reset();
assertEquals(new Counts(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 = getCard();
col.getSched().answerCard(c, BUTTON_FOUR);
// it should have been moved back to the original deck
assertEquals(1, c.getDid());
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class SchedTest method test_counts_idxV1.
@Test
public void test_counts_idxV1() throws Exception {
Collection col = getColV1();
Note note = col.newNote();
note.setItem("Front", "one");
note.setItem("Back", "two");
col.addNote(note);
col.reset();
assertEquals(new Counts(1, 0, 0), col.getSched().counts());
Card c = getCard();
// counter's been decremented but idx indicates 1
assertEquals(new Counts(0, 0, 0), col.getSched().counts());
assertEquals(NEW, col.getSched().countIdx(c));
// answer to move to learn queue
col.getSched().answerCard(c, BUTTON_ONE);
assertEquals(new Counts(0, 2, 0), col.getSched().counts());
// fetching again will decrement the count
c = getCard();
assertEquals(new Counts(0, 0, 0), col.getSched().counts());
assertEquals(LRN, col.getSched().countIdx(c));
// answering should add it back again
col.getSched().answerCard(c, BUTTON_ONE);
assertEquals(new Counts(0, 2, 0), col.getSched().counts());
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class UndoTest method test_review.
@Test
public void test_review() throws Exception {
Collection col = getColV2();
col.set_config("counts", COUNT_REMAINING);
Note note = col.newNote();
note.setItem("Front", "one");
col.addNote(note);
col.reset();
/* TODO: undo after reset ?
assertNotNull(col.undoType());
*/
// answer
assertEquals(new Counts(1, 0, 0), col.getSched().counts());
Card c = col.getSched().getCard();
assertEquals(QUEUE_TYPE_NEW, c.getQueue());
col.getSched().answerCard(c, Consts.BUTTON_THREE);
assertEquals(1001, c.getLeft());
assertEquals(new Counts(0, 1, 0), col.getSched().counts());
assertEquals(QUEUE_TYPE_LRN, c.getQueue());
// undo
assertNotNull(col.undoType());
col.undo();
col.reset();
assertEquals(new Counts(1, 0, 0), col.getSched().counts());
c.load();
assertEquals(QUEUE_TYPE_NEW, c.getQueue());
assertNotEquals(1001, c.getLeft());
assertNull(col.undoType());
// we should be able to undo multiple answers too
note = col.newNote();
note.setItem("Front", "two");
col.addNote(note);
col.reset();
assertEquals(new Counts(2, 0, 0), col.getSched().counts());
c = col.getSched().getCard();
col.getSched().answerCard(c, Consts.BUTTON_THREE);
c = col.getSched().getCard();
col.getSched().answerCard(c, Consts.BUTTON_THREE);
assertEquals(new Counts(0, 2, 0), col.getSched().counts());
col.undo();
col.reset();
assertEquals(new Counts(1, 1, 0), col.getSched().counts());
col.undo();
col.reset();
assertEquals(new Counts(2, 0, 0), col.getSched().counts());
// performing a normal op will clear the review queue
c = col.getSched().getCard();
col.getSched().answerCard(c, Consts.BUTTON_THREE);
assertThat(col.undoType(), is(instanceOf(Collection.UndoReview.class)));
col.save("foo");
// Upstream, "save" can be undone. This test fails here because it's not the case in AnkiDroid
assumeThat(col.undoName(getTargetContext().getResources()), is("foo"));
col.undo();
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class CardBrowser method onCollectionLoaded.
// Finish initializing the activity after the collection has been correctly loaded
@Override
protected void onCollectionLoaded(Collection col) {
super.onCollectionLoaded(col);
Timber.d("onCollectionLoaded()");
registerExternalStorageListener();
SharedPreferences preferences = AnkiDroidApp.getSharedPrefs(getBaseContext());
// Load reference to action bar title
mActionBarTitle = findViewById(R.id.toolbar_title);
mOrder = CARD_ORDER_NONE;
String colOrder = getCol().get_config_string("sortType");
for (int c = 0; c < fSortTypes.length; ++c) {
if (fSortTypes[c].equals(colOrder)) {
mOrder = c;
break;
}
}
if (mOrder == 1 && preferences.getBoolean("cardBrowserNoSorting", false)) {
mOrder = 0;
}
// This upgrade should already have been done during
// setConf. However older version of AnkiDroid didn't call
// upgradeJSONIfNecessary during setConf, which means the
// conf saved may still have this bug.
mOrderAsc = Upgrade.upgradeJSONIfNecessary(getCol(), "sortBackwards", false);
mCards.reset();
mCardsListView = findViewById(R.id.card_browser_list);
// Create a spinner for column1
Spinner cardsColumn1Spinner = findViewById(R.id.browser_column1_spinner);
ArrayAdapter<CharSequence> column1Adapter = ArrayAdapter.createFromResource(this, R.array.browser_column1_headings, android.R.layout.simple_spinner_item);
column1Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cardsColumn1Spinner.setAdapter(column1Adapter);
mColumn1Index = AnkiDroidApp.getSharedPrefs(getBaseContext()).getInt("cardBrowserColumn1", 0);
cardsColumn1Spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// If a new column was selected then change the key used to map from mCards to the column TextView
if (pos != mColumn1Index) {
mColumn1Index = pos;
AnkiDroidApp.getSharedPrefs(AnkiDroidApp.getInstance().getBaseContext()).edit().putInt("cardBrowserColumn1", mColumn1Index).apply();
Column[] fromMap = mCardsAdapter.getFromMapping();
fromMap[0] = COLUMN1_KEYS[mColumn1Index];
mCardsAdapter.setFromMapping(fromMap);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Do Nothing
}
});
// Load default value for column2 selection
mColumn2Index = AnkiDroidApp.getSharedPrefs(getBaseContext()).getInt("cardBrowserColumn2", 0);
// Setup the column 2 heading as a spinner so that users can easily change the column type
Spinner cardsColumn2Spinner = findViewById(R.id.browser_column2_spinner);
ArrayAdapter<CharSequence> column2Adapter = ArrayAdapter.createFromResource(this, R.array.browser_column2_headings, android.R.layout.simple_spinner_item);
column2Adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
cardsColumn2Spinner.setAdapter(column2Adapter);
// Create a new list adapter with updated column map any time the user changes the column
cardsColumn2Spinner.setOnItemSelectedListener(new OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int pos, long id) {
// If a new column was selected then change the key used to map from mCards to the column TextView
if (pos != mColumn2Index) {
mColumn2Index = pos;
AnkiDroidApp.getSharedPrefs(AnkiDroidApp.getInstance().getBaseContext()).edit().putInt("cardBrowserColumn2", mColumn2Index).apply();
Column[] fromMap = mCardsAdapter.getFromMapping();
fromMap[1] = COLUMN2_KEYS[mColumn2Index];
mCardsAdapter.setFromMapping(fromMap);
}
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
// Do Nothing
}
});
// get the font and font size from the preferences
int sflRelativeFontSize = preferences.getInt("relativeCardBrowserFontSize", DEFAULT_FONT_SIZE_RATIO);
String sflCustomFont = preferences.getString("browserEditorFont", "");
Column[] columnsContent = { COLUMN1_KEYS[mColumn1Index], COLUMN2_KEYS[mColumn2Index] };
// make a new list adapter mapping the data in mCards to column1 and column2 of R.layout.card_item_browser
mCardsAdapter = new MultiColumnListAdapter(this, R.layout.card_item_browser, columnsContent, new int[] { R.id.card_sfld, R.id.card_column2 }, sflRelativeFontSize, sflCustomFont);
// link the adapter to the main mCardsListView
mCardsListView.setAdapter(mCardsAdapter);
// make the items (e.g. question & answer) render dynamically when scrolling
mCardsListView.setOnScrollListener(new RenderOnScroll());
// set the spinner index
cardsColumn1Spinner.setSelection(mColumn1Index);
cardsColumn2Spinner.setSelection(mColumn2Index);
mCardsListView.setOnItemClickListener((parent, view, position, id) -> {
if (mInMultiSelectMode) {
// click on whole cell triggers select
CheckBox cb = view.findViewById(R.id.card_checkbox);
cb.toggle();
onCheck(position, view);
} else {
// load up the card selected on the list
long clickedCardId = getCards().get(position).getId();
saveScrollingState(position);
openNoteEditorForCard(clickedCardId);
}
});
mCardsListView.setOnItemLongClickListener((adapterView, view, position, id) -> {
if (mInMultiSelectMode) {
boolean hasChanged = false;
for (int i = Math.min(mLastSelectedPosition, position); i <= Math.max(mLastSelectedPosition, position); i++) {
CardCache card = (CardCache) mCardsListView.getItemAtPosition(i);
// Add to the set of checked cards
hasChanged |= mCheckedCards.add(card);
}
if (hasChanged) {
onSelectionChanged();
}
} else {
mLastSelectedPosition = position;
saveScrollingState(position);
loadMultiSelectMode();
// click on whole cell triggers select
CheckBox cb = view.findViewById(R.id.card_checkbox);
cb.toggle();
onCheck(position, view);
recenterListView(view);
mCardsAdapter.notifyDataSetChanged();
}
return true;
});
getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
long deckId = getCol().getDecks().selected();
mDeckSpinnerSelection = new DeckSpinnerSelection(this, col, this.findViewById(R.id.toolbar_spinner), true, false);
mDeckSpinnerSelection.initializeActionBarDeckSpinner(this.getSupportActionBar());
selectDeckAndSave(deckId);
// If a valid value for last deck exists then use it, otherwise use libanki selected deck
if (getLastDeckId() != null && getLastDeckId() == ALL_DECKS_ID) {
selectAllDecks();
} else if (getLastDeckId() != null && getCol().getDecks().get(getLastDeckId(), false) != null) {
mDeckSpinnerSelection.selectDeckById(getLastDeckId(), false);
} else {
mDeckSpinnerSelection.selectDeckById(getCol().getDecks().selected(), false);
}
}
use of com.ichi2.anki.CardBrowser.Column.ANSWER in project Anki-Android by ankidroid.
the class AbstractFlashcardViewer method initLayout.
// Set the content view to the one provided and initialize accessors.
protected void initLayout() {
FrameLayout cardContainer = findViewById(R.id.flashcard_frame);
mTopBarLayout = findViewById(R.id.top_bar);
mCardFrame = findViewById(R.id.flashcard);
mCardFrameParent = (ViewGroup) mCardFrame.getParent();
mTouchLayer = findViewById(R.id.touch_layer);
mTouchLayer.setOnTouchListener(mGestureListener);
mCardFrame.removeAllViews();
// Initialize swipe
mGestureDetectorImpl = new LinkDetectingGestureDetector();
mGestureDetector = new GestureDetector(this, mGestureDetectorImpl);
mEaseButtonsLayout = findViewById(R.id.ease_buttons);
mEaseButton1 = new EaseButton(EASE_1, findViewById(R.id.flashcard_layout_ease1), findViewById(R.id.ease1), findViewById(R.id.nextTime1));
mEaseButton1.setListeners(mEaseHandler);
mEaseButton2 = new EaseButton(EASE_2, findViewById(R.id.flashcard_layout_ease2), findViewById(R.id.ease2), findViewById(R.id.nextTime2));
mEaseButton2.setListeners(mEaseHandler);
mEaseButton3 = new EaseButton(EASE_3, findViewById(R.id.flashcard_layout_ease3), findViewById(R.id.ease3), findViewById(R.id.nextTime3));
mEaseButton3.setListeners(mEaseHandler);
mEaseButton4 = new EaseButton(EASE_4, findViewById(R.id.flashcard_layout_ease4), findViewById(R.id.ease4), findViewById(R.id.nextTime4));
mEaseButton4.setListeners(mEaseHandler);
if (!mShowNextReviewTime) {
mEaseButton1.hideNextReviewTime();
mEaseButton2.hideNextReviewTime();
mEaseButton3.hideNextReviewTime();
mEaseButton4.hideNextReviewTime();
}
Button flipCard = findViewById(R.id.flip_card);
mFlipCardLayout = findViewById(R.id.flashcard_layout_flip);
mFlipCardLayout.setOnClickListener(mFlipCardListener);
if (animationEnabled()) {
flipCard.setBackgroundResource(Themes.getResFromAttr(this, R.attr.hardButtonRippleRef));
}
if (!mButtonHeightSet && mRelativeButtonSize != 100) {
ViewGroup.LayoutParams params = mFlipCardLayout.getLayoutParams();
params.height = params.height * mRelativeButtonSize / 100;
mEaseButton1.setButtonScale(mRelativeButtonSize);
mEaseButton2.setButtonScale(mRelativeButtonSize);
mEaseButton3.setButtonScale(mRelativeButtonSize);
mEaseButton4.setButtonScale(mRelativeButtonSize);
mButtonHeightSet = true;
}
mInitialFlipCardHeight = mFlipCardLayout.getLayoutParams().height;
if (mLargeAnswerButtons) {
ViewGroup.LayoutParams params = mFlipCardLayout.getLayoutParams();
params.height = mInitialFlipCardHeight * 2;
}
mAnswerField = findViewById(R.id.answer_field);
initControls();
// Position answer buttons
String answerButtonsPosition = AnkiDroidApp.getSharedPrefs(this).getString(getString(R.string.answer_buttons_position_preference), "bottom");
LinearLayout answerArea = findViewById(R.id.bottom_area_layout);
RelativeLayout.LayoutParams answerAreaParams = (RelativeLayout.LayoutParams) answerArea.getLayoutParams();
RelativeLayout.LayoutParams cardContainerParams = (RelativeLayout.LayoutParams) cardContainer.getLayoutParams();
switch(answerButtonsPosition) {
case "top":
cardContainerParams.addRule(RelativeLayout.BELOW, R.id.bottom_area_layout);
answerAreaParams.addRule(RelativeLayout.BELOW, R.id.mic_tool_bar_layer);
answerArea.removeView(mAnswerField);
answerArea.addView(mAnswerField, 1);
answerArea.setVisibility(View.VISIBLE);
break;
case "bottom":
cardContainerParams.addRule(RelativeLayout.ABOVE, R.id.bottom_area_layout);
cardContainerParams.addRule(RelativeLayout.BELOW, R.id.mic_tool_bar_layer);
answerAreaParams.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
answerArea.setVisibility(View.VISIBLE);
break;
case "none":
answerArea.setVisibility(View.GONE);
break;
default:
Timber.w("Unknown answerButtonsPosition: %s", answerButtonsPosition);
break;
}
answerArea.setLayoutParams(answerAreaParams);
cardContainer.setLayoutParams(cardContainerParams);
}
Aggregations