use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class Sched method _checkLeech.
/**
* Leeches ****************************************************************** *****************************
*/
/**
* Leech handler. True if card was a leech.
*/
@Override
protected boolean _checkLeech(@NonNull Card card, @NonNull JSONObject conf) {
int lf;
lf = conf.getInt("leechFails");
if (lf == 0) {
return false;
}
// if over threshold or every half threshold reps after that
if (card.getLapses() >= lf && (card.getLapses() - lf) % Math.max(lf / 2, 1) == 0) {
// add a leech tag
Note n = card.note();
n.addTag("leech");
n.flush();
// handle
if (conf.getInt("leechAction") == Consts.LEECH_SUSPEND) {
// if it has an old due, remove it from cram/relearning
if (card.getODue() != 0) {
card.setDue(card.getODue());
}
if (card.getODid() != 0) {
card.setDid(card.getODid());
}
card.setODue(0);
card.setODid(0);
card.setQueue(Consts.QUEUE_TYPE_SUSPENDED);
}
// notify UI
if (mContextReference != null) {
Activity context = mContextReference.get();
leech(card, context);
}
return true;
}
return false;
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class Sched method _updateRevIvl.
@Override
protected void _updateRevIvl(@NonNull Card card, @Consts.BUTTON_TYPE int ease) {
try {
int idealIvl = _nextRevIvl(card, ease);
JSONObject conf = _revConf(card);
card.setIvl(Math.min(Math.max(_adjRevIvl(card, idealIvl), card.getIvl() + 1), conf.getInt("maxIvl")));
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class Sched method _fillRev.
@Override
protected boolean _fillRev(boolean allowSibling) {
if (!mRevQueue.isEmpty()) {
return true;
}
if (mRevCount == 0) {
return false;
}
SupportSQLiteDatabase db = mCol.getDb().getDatabase();
while (!mRevDids.isEmpty()) {
long did = mRevDids.getFirst();
int lim = Math.min(mQueueLimit, _deckRevLimit(did));
Cursor cur = null;
if (lim != 0) {
mRevQueue.clear();
// fill the queue with the current did
try {
/* Difference with upstream: we take current card into account.
*
* When current card is answered, the card is not due anymore, so does not belong to the queue.
* Furthermore, _burySiblings ensure that the siblings of the current cards are removed from the
* queue to ensure same day spacing. We simulate this action by ensuring that those siblings are not
* filled, except if we know there are cards and we didn't find any non-sibling card. This way, the
* queue is not empty if it should not be empty (important for the conditional belows), but the
* front of the queue contains distinct card.
*/
String idName = (allowSibling) ? "id" : "nid";
long id = (allowSibling) ? currentCardId() : currentCardNid();
cur = db.query("SELECT id FROM cards WHERE did = ? AND queue = " + Consts.QUEUE_TYPE_REV + " AND due <= ?" + " AND " + idName + " != ? LIMIT ?", new Object[] { did, mToday, id, lim });
while (cur.moveToNext()) {
mRevQueue.add(cur.getLong(0));
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
if (!mRevQueue.isEmpty()) {
// ordering
if (mCol.getDecks().get(did).getInt("dyn") != 0) {
// dynamic decks need due order preserved
// Note: libanki reverses mRevQueue and returns the last element in _getRevCard().
// AnkiDroid differs by leaving the queue intact and returning the *first* element
// in _getRevCard().
} else {
Random r = new Random();
r.setSeed(mToday);
mRevQueue.shuffle(r);
}
// is the current did empty?
if (mRevQueue.size() < lim) {
mRevDids.remove();
}
return true;
}
}
// nothing left in the deck; move to next
mRevDids.remove();
}
// Since we didn't get a card and the count is non-zero, we
// need to check again for any cards that were removed from
// the queue but not buried
_resetRev();
return _fillRev(true);
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class Sched method _deckRevLimitSingle.
/**
* Maximal number of rev card still to see today in deck d. It's computed as:
* the number of rev card to see by day according
* minus the number of rev cards seen today in deck d or a descendant
* plus the number of extra cards to see today in deck d, a parent or a descendant.
*
* Limits of its ancestors are not applied. Current card is treated the same way as other cards.
*/
@Override
protected int _deckRevLimitSingle(@NonNull Deck d) {
if (d.getInt("dyn") != 0) {
return mReportLimit;
}
long did = d.getLong("id");
DeckConfig c = mCol.getDecks().confForDid(did);
int lim = Math.max(0, c.getJSONObject("rev").getInt("perDay") - d.getJSONArray("revToday").getInt(1));
if (currentCardIsInQueueWithDeck(Consts.QUEUE_TYPE_REV, did)) {
lim--;
}
// So currentCard does not have to be taken into consideration in this method
return lim;
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class Sched method _lapseConf.
@Override
@NonNull
protected JSONObject _lapseConf(@NonNull Card card) {
DeckConfig conf = _cardConf(card);
// normal deck
if (card.getODid() == 0) {
return conf.getJSONObject("lapse");
}
// dynamic deck; override some attributes, use original deck for others
DeckConfig oconf = mCol.getDecks().confForDid(card.getODid());
JSONArray delays = conf.optJSONArray("delays");
if (delays == null) {
delays = oconf.getJSONObject("lapse").getJSONArray("delays");
}
JSONObject dict = new JSONObject();
// original deck
dict.put("minInt", oconf.getJSONObject("lapse").getInt("minInt"));
dict.put("leechFails", oconf.getJSONObject("lapse").getInt("leechFails"));
dict.put("leechAction", oconf.getJSONObject("lapse").getInt("leechAction"));
dict.put("mult", oconf.getJSONObject("lapse").getDouble("mult"));
// overrides
dict.put("delays", delays);
dict.put("resched", conf.getBoolean("resched"));
return dict;
}
Aggregations