use of com.ichi2.libanki.sched.Counts.Queue in project Anki-Android by ankidroid.
the class SchedV2 method currentCardIsInQueueWithDeck.
protected boolean currentCardIsInQueueWithDeck(@Consts.CARD_QUEUE int queue, long did) {
// mCurrentCard may be set to null when the reviewer gets closed. So we copy it to be sure to avoid NullPointerException
Card currentCard = mCurrentCard;
List<Long> currentCardParentsDid = mCurrentCardParentsDid;
return currentCard != null && currentCard.getQueue() == queue && currentCardParentsDid != null && currentCardParentsDid.contains(did);
}
use of com.ichi2.libanki.sched.Counts.Queue in project Anki-Android by ankidroid.
the class SchedV2 method _rescheduleLapse.
// Overriden
protected int _rescheduleLapse(@NonNull Card card) {
JSONObject conf = _lapseConf(card);
card.setLapses(card.getLapses() + 1);
card.setFactor(Math.max(1300, card.getFactor() - 200));
int delay;
boolean suspended = _checkLeech(card, conf) && card.getQueue() == Consts.QUEUE_TYPE_SUSPENDED;
if (conf.getJSONArray("delays").length() != 0 && !suspended) {
card.setType(Consts.CARD_TYPE_RELEARNING);
delay = _moveToFirstStep(card, conf);
} else {
// no relearning steps
_updateRevIvlOnFail(card, conf);
_rescheduleAsRev(card, conf, false);
// need to reset the queue after rescheduling
if (suspended) {
card.setQueue(Consts.QUEUE_TYPE_SUSPENDED);
}
delay = 0;
}
return delay;
}
use of com.ichi2.libanki.sched.Counts.Queue in project Anki-Android by ankidroid.
the class FinderTest method test_findCards.
@Test
public void test_findCards() {
Collection col = getCol();
Note note = col.newNote();
note.setItem("Front", "dog");
note.setItem("Back", "cat");
note.addTag("monkey animal_1 * %");
col.addNote(note);
long n1id = note.getId();
long firstCardId = note.cards().get(0).getId();
note = col.newNote();
note.setItem("Front", "goats are fun");
note.setItem("Back", "sheep");
note.addTag("sheep goat horse animal11");
col.addNote(note);
long n2id = note.getId();
note = col.newNote();
note.setItem("Front", "cat");
note.setItem("Back", "sheep");
col.addNote(note);
Card catCard = note.cards().get(0);
Model m = col.getModels().current();
m = col.getModels().copy(m);
ModelManager mm = col.getModels();
JSONObject t = Models.newTemplate("Reverse");
t.put("qfmt", "{{Back}}");
t.put("afmt", "{{Front}}");
mm.addTemplateModChanged(m, t);
mm.save(m);
note = col.newNote();
note.setItem("Front", "test");
note.setItem("Back", "foo bar");
col.addNote(note);
col.save();
List<Long> latestCardIds = note.cids();
// tag searches
assertEquals(5, col.findCards("tag:*").size());
assertEquals(1, col.findCards("tag:\\*").size());
assertEquals(5, col.findCards("tag:%").size());
assertEquals(1, col.findCards("tag:\\%").size());
assertEquals(2, col.findCards("tag:animal_1").size());
assertEquals(1, col.findCards("tag:animal\\_1").size());
assertEquals(0, col.findCards("tag:donkey").size());
assertEquals(1, col.findCards("tag:sheep").size());
assertEquals(1, col.findCards("tag:sheep tag:goat").size());
assertEquals(0, col.findCards("tag:sheep tag:monkey").size());
assertEquals(1, col.findCards("tag:monkey").size());
assertEquals(1, col.findCards("tag:sheep -tag:monkey").size());
assertEquals(4, col.findCards("-tag:sheep").size());
col.getTags().bulkAdd(col.getDb().queryLongList("select id from notes"), "foo bar");
assertEquals(5, col.findCards("tag:foo").size());
assertEquals(5, col.findCards("tag:bar").size());
col.getTags().bulkRem(col.getDb().queryLongList("select id from notes"), "foo");
assertEquals(0, col.findCards("tag:foo").size());
assertEquals(5, col.findCards("tag:bar").size());
// text searches
assertEquals(2, col.findCards("cat").size());
assertEquals(1, col.findCards("cat -dog").size());
assertEquals(1, col.findCards("cat -dog").size());
assertEquals(1, col.findCards("are goats").size());
assertEquals(0, col.findCards("\"are goats\"").size());
assertEquals(1, col.findCards("\"goats are\"").size());
// card states
Card c = note.cards().get(0);
c.setQueue(QUEUE_TYPE_REV);
c.setType(CARD_TYPE_REV);
assertEquals(0, col.findCards("is:review").size());
c.flush();
assertEqualsArrayList((new Long[] { c.getId() }), col.findCards("is:review"));
assertEquals(0, col.findCards("is:due").size());
c.setDue(0);
c.setQueue(QUEUE_TYPE_REV);
c.flush();
assertEqualsArrayList((new Long[] { c.getId() }), col.findCards("is:due"));
assertEquals(4, col.findCards("-is:due").size());
c.setQueue(QUEUE_TYPE_SUSPENDED);
// ensure this card gets a later mod time
c.flush();
col.getDb().execute("update cards set mod = mod + 1 where id = ?", c.getId());
assertEqualsArrayList((new Long[] { c.getId() }), col.findCards("is:suspended"));
// nids
assertEquals(0, col.findCards("nid:54321").size());
assertEquals(2, col.findCards("nid:" + note.getId()).size());
assertEquals(2, col.findCards("nid:" + n1id + "," + n2id).size());
// templates
assertEquals(0, col.findCards("card:foo").size());
assertEquals(4, col.findCards("\"card:card 1\"").size());
assertEquals(1, col.findCards("card:reverse").size());
assertEquals(4, col.findCards("card:1").size());
assertEquals(1, col.findCards("card:2").size());
// fields
assertEquals(1, col.findCards("front:dog").size());
assertEquals(4, col.findCards("-front:dog").size());
assertEquals(0, col.findCards("front:sheep").size());
assertEquals(2, col.findCards("back:sheep").size());
assertEquals(3, col.findCards("-back:sheep").size());
assertEquals(0, col.findCards("front:do").size());
assertEquals(5, col.findCards("front:*").size());
// ordering
col.set_config("sortType", "noteCrt");
col.flush();
assertTrue(latestCardIds.contains(getLastListElement(col.findCards("front:*", new SortOrder.UseCollectionOrdering()))));
assertTrue(latestCardIds.contains(getLastListElement(col.findCards("", new SortOrder.UseCollectionOrdering()))));
col.set_config("sortType", "noteFld");
col.flush();
assertEquals(catCard.getId(), (long) col.findCards("", new SortOrder.UseCollectionOrdering()).get(0));
assertTrue(latestCardIds.contains(getLastListElement(col.findCards("", new SortOrder.UseCollectionOrdering()))));
col.set_config("sortType", "cardMod");
col.flush();
assertTrue(latestCardIds.contains(getLastListElement(col.findCards("", new SortOrder.UseCollectionOrdering()))));
assertEquals(firstCardId, (long) col.findCards("", new SortOrder.UseCollectionOrdering()).get(0));
col.set_config("sortBackwards", true);
col.flush();
assertTrue(latestCardIds.contains(col.findCards("", new SortOrder.UseCollectionOrdering()).get(0)));
/* TODO: Port BuiltinSortKind
assertEquals(firstCardId,
col.findCards("", BuiltinSortKind.CARD_DUE, reverse=false).get(0)
);
assertNotEquals(firstCardId,
col.findCards("", BuiltinSortKind.CARD_DUE, reverse=true).get(0));
*/
// model
assertEquals(3, col.findCards("note:basic").size());
assertEquals(2, col.findCards("-note:basic").size());
assertEquals(5, col.findCards("-note:foo").size());
// col
assertEquals(5, col.findCards("deck:default").size());
assertEquals(0, col.findCards("-deck:default").size());
assertEquals(5, col.findCards("-deck:foo").size());
assertEquals(5, col.findCards("deck:def*").size());
assertEquals(5, col.findCards("deck:*EFAULT").size());
assertEquals(0, col.findCards("deck:*cefault").size());
// full search
note = col.newNote();
note.setItem("Front", "hello<b>world</b>");
note.setItem("Back", "abc");
col.addNote(note);
// as it's the sort field, it matches
assertEquals(2, col.findCards("helloworld").size());
// assertEquals(, col.findCards("helloworld", full=true).size())2 This is commented upstream
// if we put it on the back, it won't
String note_front = note.getItem("Front");
String note_back = note.getItem("Back");
note.setItem("Front", note_back);
note.setItem("Back", note_front);
note.flush();
assertEquals(0, col.findCards("helloworld").size());
// Those lines are commented above
// assertEquals(, col.findCards("helloworld", full=true).size())2
// assertEquals(, col.findCards("back:helloworld", full=true).size())2
// searching for an invalid special tag should not error
// TODO: ensure the search fail
// assertThrows(Exception.class, () -> col.findCards("is:invalid").size());
// should be able to limit to parent col, no children
long id = col.getDb().queryLongScalar("select id from cards limit 1");
col.getDb().execute("update cards set did = ? where id = ?", addDeck("Default::Child"), id);
col.save();
assertEquals(7, col.findCards("deck:default").size());
assertEquals(1, col.findCards("deck:default::child").size());
assertEquals(6, col.findCards("deck:default -deck:default::*").size());
// properties
id = col.getDb().queryLongScalar("select id from cards limit 1");
col.getDb().execute("update cards set queue=2, ivl=10, reps=20, due=30, factor=2200 where id = ?", id);
assertEquals(1, col.findCards("prop:ivl>5").size());
assertThat(col.findCards("prop:ivl<5").size(), greaterThan(1));
assertEquals(1, col.findCards("prop:ivl>=5").size());
assertEquals(0, col.findCards("prop:ivl=9").size());
assertEquals(1, col.findCards("prop:ivl=10").size());
assertThat(col.findCards("prop:ivl!=10").size(), greaterThan(1));
assertEquals(1, col.findCards("prop:due>0").size());
// due dates should work
assertEquals(0, col.findCards("prop:due=29").size());
assertEquals(1, col.findCards("prop:due=30").size());
// ease factors
assertEquals(0, col.findCards("prop:ease=2.3").size());
assertEquals(1, col.findCards("prop:ease=2.2").size());
assertEquals(1, col.findCards("prop:ease>2").size());
assertThat(col.findCards("-prop:ease>2").size(), greaterThan(1));
// recently failed
if (!isNearCutoff(col)) {
assertEquals(0, col.findCards("rated:1:1").size());
assertEquals(0, col.findCards("rated:1:2").size());
c = getCard();
col.getSched().answerCard(c, Consts.BUTTON_TWO);
assertEquals(0, col.findCards("rated:1:1").size());
assertEquals(1, col.findCards("rated:1:2").size());
c = getCard();
col.getSched().answerCard(c, Consts.BUTTON_ONE);
assertEquals(1, col.findCards("rated:1:1").size());
assertEquals(1, col.findCards("rated:1:2").size());
assertEquals(2, col.findCards("rated:1").size());
assertEquals(0, col.findCards("rated:0:2").size());
assertEquals(1, col.findCards("rated:2:2").size());
// added
assertEquals(0, col.findCards("added:0").size());
col.getDb().execute("update cards set id = id - " + SECONDS_PER_DAY * 1000 + " where id = ?", id);
assertEquals(col.cardCount() - 1, col.findCards("added:1").size());
assertEquals(col.cardCount(), col.findCards("added:2").size());
} else {
Timber.w("some find tests disabled near cutoff");
}
// empty field
assertEquals(0, col.findCards("front:").size());
note = col.newNote();
note.setItem("Front", "");
note.setItem("Back", "abc2");
assertEquals(1, col.addNote(note));
assertEquals(1, col.findCards("front:").size());
// OR searches and nesting
assertEquals(2, col.findCards("tag:monkey or tag:sheep").size());
assertEquals(2, col.findCards("(tag:monkey OR tag:sheep)").size());
assertEquals(6, col.findCards("-(tag:monkey OR tag:sheep)").size());
assertEquals(2, col.findCards("tag:monkey or (tag:sheep sheep)").size());
assertEquals(1, col.findCards("tag:monkey or (tag:sheep octopus)").size());
// flag
// Todo: ensure it fails
// assertThrows(Exception.class, () -> col.findCards("flag:12"));
}
use of com.ichi2.libanki.sched.Counts.Queue in project AnkiChinaAndroid by ankichinateam.
the class AnkiChinaSyncer method handleServerData.
// 35%+25%
private void handleServerData(JSONObject item) {
mCol = CollectionHelper.getInstance().getColSafe(AnkiDroidApp.getInstance());
CollectionHelper.getInstance().lockCollection();
updateDialogProgress(SYNCING_DATA, "更新全局配置中", mCurrentProgress + 1);
DB db = mCol.getDb();
try {
JSONObject remoteCol = item.getJSONObject("col").getJSONObject("replace");
// db.execute("update col set id ="+remoteCol.getInt("id")+","+"set crt =\"+remoteCol.getLong(\"crt\")");
// db.execute("update col set crt ="+remoteCol.getLong("crt"));
// db.execute("update col set mod ="+remoteCol.getLong("mod"));
// db.execute("update col set scm ="+remoteCol.getLong("scm"));
// db.execute("update col set ver ="+remoteCol.getInt("ver"));
// db.execute("update col set dty ="+remoteCol.getInt("dty"));
// db.execute("update col set usn ="+remoteCol.getInt("usn"));
// db.execute("update col set ls ="+remoteCol.getLong("ls"));
// db.execute("update col set conf ="+remoteCol.getString("conf"));
// db.execute("update col set tags ="+remoteCol.getString("tags"));
// db.execute("update col set tags ="+remoteCol.getString("tags"));
// db.execute("update col set id = %d,");
Timber.i("remote col config:%s", remoteCol.toString());
@SuppressLint("DefaultLocale") String sql = String.format("update col set id = %d,crt = %d,mod=%d,scm=%d,ver=%d,dty=%d,usn=%d,ls=%d,conf='%s',tags='%s'", remoteCol.getInt("id"), remoteCol.getLong("crt"), remoteCol.getLong("mod"), remoteCol.getLong("scm"), remoteCol.getInt("ver"), remoteCol.getInt("dty"), remoteCol.getInt("usn"), remoteCol.getLong("ls"), remoteCol.getString("conf"), remoteCol.getString("tags") == null || !remoteCol.getString("tags").startsWith("{") ? "{}" : remoteCol.getString("tags"));
db.execute(sql);
mCol.load();
} catch (Exception e) {
e.printStackTrace();
}
Decks currentDecks = mCol.getDecks();
// 删除多余的内容
try {
JSONArray deletedDecks = item.getJSONObject("decks").getJSONArray("delete");
if (deletedDecks.length() > 0) {
double percent = 2.0 / deletedDecks.length();
for (int i = 0; i < deletedDecks.length(); i++) {
String deckID = deletedDecks.getString(i);
currentDecks.rem(Long.parseLong(deckID));
updateDialogProgress(SYNCING_DATA, "删除多余牌组中", mCurrentProgress + percent);
}
mCol.save();
}
} catch (Exception e) {
// e.printStackTrace();
}
try {
JSONArray deletedDConf = item.getJSONObject("dconf").getJSONArray("delete");
if (deletedDConf.length() > 0) {
double percent = 2.0 / deletedDConf.length();
for (int i = 0; i < deletedDConf.length(); i++) {
String id = deletedDConf.getString(i);
mCol.getDecks().remConf(Long.parseLong(id));
updateDialogProgress(SYNCING_DATA, "删除多余牌组配置中", mCurrentProgress + percent);
}
mCol.save();
}
} catch (Exception e) {
// e.printStackTrace();
}
try {
JSONArray deletedModel = item.getJSONObject("models").getJSONArray("delete");
if (deletedModel.length() > 0) {
double percent = 2.0 / deletedModel.length();
for (int i = 0; i < deletedModel.length(); i++) {
String id = deletedModel.getString(i);
mCol.getModels().rem(mCol.getModels().get(Long.parseLong(id)));
updateDialogProgress(SYNCING_DATA, "删除多余模板中", mCurrentProgress + percent);
}
mCol.save();
}
} catch (Exception e) {
e.printStackTrace();
}
updateDialogProgress(SYNCING_DATA, "删除多余卡牌中", mCurrentProgress + 2);
try {
JSONArray deletedCards = item.getJSONObject("cards").getJSONArray("delete");
List<Long> sids = ids2longList(deletedCards);
Timber.e("need delete cards num:%s", sids.size());
// db.execute("DELETE FROM cards WHERE id IN " + sids);
mCol.remCards(sids);
mCol.save();
} catch (Exception e) {
e.printStackTrace();
}
updateDialogProgress(SYNCING_DATA, "删除多余笔记中", mCurrentProgress + 2);
try {
JSONArray deletedNotes = item.getJSONObject("notes").getJSONArray("delete");
long[] sids = ids2longArray(deletedNotes);
// db.execute("DELETE FROM notes WHERE id IN " + sids);
mCol.remNotes(sids);
mCol.save();
} catch (Exception e) {
e.printStackTrace();
}
try {
JSONObject replaceDecks = item.getJSONObject("decks").getJSONObject("replace");
if (replaceDecks.length() > 0) {
double percent = 2.0 / replaceDecks.length();
Iterator<String> it = replaceDecks.keys();
while (it.hasNext()) {
String next = it.next();
try {
// mCol.getDecks().getDecks().put(Long.parseLong(next), new Deck(replaceDecks.getJSONObject(next)));
mCol.getDecks().update(new Deck(replaceDecks.getJSONObject(next)));
updateDialogProgress(SYNCING_DATA, "同步牌组数据中", mCurrentProgress + percent);
} catch (Exception e) {
// 只遍历model id
}
}
mCol.save();
}
} catch (Exception e) {
// e.printStackTrace();
}
db.getDatabase().beginTransaction();
try {
JSONArray replace = item.getJSONObject("revlog").getJSONArray("replace");
if (replace.length() > 0) {
for (int i = 0; i < replace.length(); i++) {
log(replace.getJSONArray(i).get(0), replace.getJSONArray(i).get(1), replace.getJSONArray(i).get(2), replace.getJSONArray(i).get(3), replace.getJSONArray(i).get(4), replace.getJSONArray(i).get(5), replace.getJSONArray(i).get(6), replace.getJSONArray(i).get(7), replace.getJSONArray(i).get(8));
}
db.getDatabase().setTransactionSuccessful();
mCol.save();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
db.getDatabase().endTransaction();
}
// Timber.e("看看是null还是null:%s,%s", (item.getJSONObject("dconf").get("replace")==JSONObject.NULL), (item.getJSONObject("dconf").getString("replace").equals("null")));
try {
JSONObject replaceDConf = item.getJSONObject("dconf").getJSONObject("replace");
if (replaceDConf.length() > 0) {
double percent = 2.0 / replaceDConf.length();
Iterator<String> it = replaceDConf.keys();
while (it.hasNext()) {
String next = it.next();
try {
Long.parseLong(next);
mCol.getDecks().updateConf(new DeckConfig(replaceDConf.getJSONObject(next)));
updateDialogProgress(SYNCING_DATA, "同步牌组配置数据中", mCurrentProgress + percent);
} catch (Exception e) {
// 只遍历model id
}
}
mCol.save();
}
} catch (Exception e) {
e.printStackTrace();
}
try {
JSONObject replaceModels = item.getJSONObject("models").getJSONObject("replace");
if (replaceModels.length() > 0) {
double percent = 5.0 / replaceModels.length();
Iterator<String> it = replaceModels.keys();
while (it.hasNext()) {
String next = it.next();
try {
Long.parseLong(next);
mCol.getModels().update(new Model(replaceModels.getJSONObject(next)));
updateDialogProgress(SYNCING_DATA, "同步模板数据中", mCurrentProgress + percent);
} catch (Exception e) {
// 只遍历model id
}
}
mCol.save();
}
} catch (Exception e) {
e.printStackTrace();
}
db.getDatabase().beginTransaction();
try {
JSONArray replace = item.getJSONObject("notes").getJSONArray("replace");
if (replace.length() > 0) {
double percent = mPullNotesPerPercent / replace.length();
for (int i = 0; i < replace.length(); i++) {
// String values = replace.getJSONArray(i).toString().replace("[", "").replace("]", "").replaceAll("\"","'").replaceAll("\u001f","\u001f");
// String sql = "replace into notes(id,guid,mid,mod,usn,tags,flds,sfld,csum,flags,data) values ( " + values + ")";
//
db.execute("insert or replace into notes values (?,?,?,?,?,?,?,?,?,?,?)", replace.getJSONArray(i).get(0), replace.getJSONArray(i).get(1), replace.getJSONArray(i).get(2), replace.getJSONArray(i).get(3), replace.getJSONArray(i).get(4), replace.getJSONArray(i).get(5), replace.getJSONArray(i).get(6), replace.getJSONArray(i).get(7), replace.getJSONArray(i).get(8), replace.getJSONArray(i).get(9), replace.getJSONArray(i).get(10));
updateDialogProgress(SYNCING_DATA, "同步笔记数据中", mCurrentProgress + percent);
}
db.getDatabase().setTransactionSuccessful();
mCol.save();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
db.getDatabase().endTransaction();
}
db.getDatabase().beginTransaction();
try {
JSONArray replace = item.getJSONObject("cards").getJSONArray("replace");
if (replace.length() > 0) {
double percent = 5.0 / replace.length();
for (int i = 0; i < replace.length(); i++) {
// String values = replace.getJSONArray(i).toString().replace("[", "").replace("]", "").replaceAll("\"","'").replaceAll("\u001f","\u001f");
// String sql = "replace into cards(id,nid,did,ord,mod,usn,type,queue,due,ivl,factor,reps,lapses,left,odue,odid,flags,data) values ( " + values + ")";
// Timber.i("update dialog progress:%d", percent);
db.execute("insert or replace into cards values (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)", replace.getJSONArray(i).get(0), replace.getJSONArray(i).get(1), replace.getJSONArray(i).get(2), replace.getJSONArray(i).get(3), replace.getJSONArray(i).get(4), replace.getJSONArray(i).get(5), replace.getJSONArray(i).get(6), replace.getJSONArray(i).get(7), replace.getJSONArray(i).get(8), replace.getJSONArray(i).get(9), replace.getJSONArray(i).get(10), replace.getJSONArray(i).get(11), replace.getJSONArray(i).get(12), replace.getJSONArray(i).get(13), replace.getJSONArray(i).get(14), replace.getJSONArray(i).get(15), replace.getJSONArray(i).get(16), replace.getJSONArray(i).get(17));
updateDialogProgress(SYNCING_DATA, "同步卡牌数据中", mCurrentProgress + percent);
}
db.getDatabase().setTransactionSuccessful();
mCol.save();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
db.getDatabase().endTransaction();
}
CollectionHelper.getInstance().unlockCollection();
}
use of com.ichi2.libanki.sched.Counts.Queue in project AnkiChinaAndroid by ankichinateam.
the class Sched method _fillLrn.
// sub-day learning
@Override
protected boolean _fillLrn() {
if (mLrnCount == 0) {
return false;
}
if (!mLrnQueue.isEmpty()) {
return true;
}
Cursor cur = null;
mLrnQueue.clear();
SupportSQLiteDatabase db = mCol.getDb().getDatabase();
try {
/* Difference with upstream:
* Current card can't come in the queue.
*
* In standard usage, a card is not requested before the previous card is marked as reviewed. However, if we
* decide to query a second card sooner, we don't want to get the same card a second time. This simulate
* _getLrnCard which did remove the card from the queue. _sortIntoLrn will add the card back to the queue if
* required when the card is reviewed.
*/
cur = db.query("SELECT due, id FROM cards WHERE did IN " + _deckLimit() + " AND queue = " + Consts.QUEUE_TYPE_LRN + " AND due < ? AND id != ? LIMIT ?", new Object[] { mDayCutoff, currentCardId(), mReportLimit });
while (cur.moveToNext()) {
mLrnQueue.add(cur.getLong(0), cur.getLong(1));
}
// as it arrives sorted by did first, we need to sort it
mLrnQueue.sort();
return !mLrnQueue.isEmpty();
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
}
Aggregations