use of com.ichi2.anki.CardBrowser.Column.DECK 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.DECK 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.DECK 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;
}
use of com.ichi2.anki.CardBrowser.Column.DECK in project AnkiChinaAndroid by ankichinateam.
the class Sched method _newConf.
/**
* Tools ******************************************************************** ***************************
*/
@Override
@NonNull
protected JSONObject _newConf(@NonNull Card card) {
DeckConfig conf = _cardConf(card);
// normal deck
if (card.getODid() == 0) {
return conf.getJSONObject("new");
}
// 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("new").getJSONArray("delays");
}
JSONObject dict = new JSONObject();
// original deck
dict.put("ints", oconf.getJSONObject("new").getJSONArray("ints"));
dict.put("initialFactor", oconf.getJSONObject("new").getInt("initialFactor"));
dict.put("bury", oconf.getJSONObject("new").optBoolean("bury", true));
// overrides
dict.put("delays", delays);
dict.put("separate", conf.getBoolean("separate"));
dict.put("order", Consts.NEW_CARDS_DUE);
dict.put("perDay", mReportLimit);
return dict;
}
use of com.ichi2.anki.CardBrowser.Column.DECK in project AnkiChinaAndroid by ankichinateam.
the class Sched method deckDueList.
/**
* Returns [deckname, did, rev, lrn, new]
*/
@Override
@Nullable
public List<DeckDueTreeNode> deckDueList(@Nullable CollectionTask collectionTask, long did) {
_checkDay();
mCol.getDecks().checkIntegrity();
ArrayList<Deck> decks = deckLimitWithParent(did, mCol);
// ArrayList<Deck> decks = mCol.getDecks().allSorted();
Timber.i("show decks" + did + " size:" + decks.size());
HashMap<String, Integer[]> lims = new HashMap<>();
ArrayList<DeckDueTreeNode> data = new ArrayList<>();
long time = SystemClock.elapsedRealtime();
for (Deck deck : decks) {
if (collectionTask != null && collectionTask.isCancelled()) {
return null;
}
String deckName = deck.getString("name");
String p = Decks.parent(deckName);
// new
int nlim = _deckNewLimitSingle(deck);
int rlim = _deckRevLimitSingle(deck);
if (!TextUtils.isEmpty(p)) {
Integer[] parentLims = lims.get(Decks.normalizeName(p));
// 'temporary for diagnosis of bug #6383'
Assert.that(parentLims != null, "Deck %s is supposed to have parent %s. It has not be found.", deckName, p);
nlim = Math.min(nlim, parentLims[0]);
// review
rlim = Math.min(rlim, parentLims[1]);
}
// long time = SystemClock.elapsedRealtime();
int _new = _newForDeck(deck.getLong("id"), nlim);
// Timber.i("cost time for new:"+(SystemClock.elapsedRealtime()-time));
// learning
int lrn = _lrnForDeck(deck.getLong("id"));
// Timber.i("cost time for lrn:"+(SystemClock.elapsedRealtime()-time));
// reviews
int rev = _revForDeck(deck.getLong("id"), rlim);
// Timber.i("cost time for rev:"+(SystemClock.elapsedRealtime()-time));
// save to list
double[] datas = did == ALL_DECKS_ID ? _getCardDataCount(deck.getLong("id")) : new double[] { 0, 0, 0 };
// Timber.i("cost time for datas:"+(SystemClock.elapsedRealtime()-time));
// Timber.i("add deck in tree:%s", deckName);
data.add(new DeckDueTreeNode(mCol, deck.getString("name"), deck.getLong("id"), rev, lrn, _new, datas));
// add deck as a parent
lims.put(Decks.normalizeName(deck.getString("name")), new Integer[] { nlim, rlim });
}
Timber.i("cost time for datas:" + (SystemClock.elapsedRealtime() - time));
return data;
}
Aggregations