use of com.ichi2.libanki.sched.DeckDueTreeNode in project Anki-Android by ankidroid.
the class SchedTest method test_deckDueV1.
@Test
public void test_deckDueV1() throws Exception {
Collection col = getColV1();
// add a note with default deck
Note note = col.newNote();
note.setItem("Front", "one");
col.addNote(note);
// and one that's a child
note = col.newNote();
note.setItem("Front", "two");
long default1 = addDeck("Default::1");
note.model().put("did", default1);
col.addNote(note);
// make it a review card
Card c = note.cards().get(0);
c.setQueue(QUEUE_TYPE_REV);
c.setDue(0);
c.flush();
// add one more with a new deck
note = col.newNote();
note.setItem("Front", "two");
JSONObject foobar = note.model().put("did", addDeck("foo::bar"));
col.addNote(note);
// and one that's a sibling
note = col.newNote();
note.setItem("Front", "three");
JSONObject foobaz = note.model().put("did", addDeck("foo::baz"));
col.addNote(note);
col.reset();
assertEquals(5, col.getDecks().allSortedNames().size());
DeckDueTreeNode tree = col.getSched().deckDueTree().get(0);
assertEquals("Default", tree.getLastDeckNameComponent());
// sum of child and parent
assertEquals(1, tree.getDid());
assertEquals(1, tree.getRevCount());
assertEquals(1, tree.getNewCount());
// child count is just review
DeckDueTreeNode child = tree.getChildren().get(0);
assertEquals("1", child.getLastDeckNameComponent());
assertEquals(default1, child.getDid());
assertEquals(1, child.getRevCount());
assertEquals(0, child.getNewCount());
// code should not fail if a card has an invalid deck
c.setDid(12345);
c.flush();
col.getSched().deckDueTree();
}
use of com.ichi2.libanki.sched.DeckDueTreeNode in project Anki-Android by ankidroid.
the class SchedTest method ensureDeckTree.
@Test
public void ensureDeckTree() {
for (String deckName : TEST_DECKS) {
addDeck(deckName);
}
getCol().getSched().deckDueTree();
AbstractSched sched = getCol().getSched();
List<DeckDueTreeNode> tree = sched.deckDueTree();
Assert.assertEquals("Tree has not the expected structure", SchedV2Test.expectedTree(getCol(), false), tree);
}
use of com.ichi2.libanki.sched.DeckDueTreeNode in project Anki-Android by ankidroid.
the class Sched method deckDueList.
/*
Deck list **************************************************************** *******************************
*/
/**
* Returns [deckname, did, rev, lrn, new]
*/
@Override
@Nullable
public List<DeckDueTreeNode> deckDueList(@Nullable CancelListener cancelListener) {
_checkDay();
mCol.getDecks().checkIntegrity();
List<Deck> decks = mCol.getDecks().allSorted();
HashMap<String, Integer[]> lims = HashUtil.HashMapInit(decks.size());
ArrayList<DeckDueTreeNode> deckNodes = new ArrayList<>(decks.size());
for (Deck deck : decks) {
if (isCancelled(cancelListener)) {
return null;
}
String deckName = deck.getString("name");
String p = Decks.parent(deckName);
// new
int nlim = _deckNewLimitSingle(deck, false);
int rlim = _deckRevLimitSingle(deck, false);
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]);
}
int _new = _newForDeck(deck.getLong("id"), nlim);
// learning
int lrn = _lrnForDeck(deck.getLong("id"));
// reviews
int rev = _revForDeck(deck.getLong("id"), rlim);
// save to list
deckNodes.add(new DeckDueTreeNode(mCol, deck.getString("name"), deck.getLong("id"), rev, lrn, _new));
// add deck as a parent
lims.put(Decks.normalizeName(deck.getString("name")), new Integer[] { nlim, rlim });
}
return deckNodes;
}
use of com.ichi2.libanki.sched.DeckDueTreeNode in project Anki-Android by ankidroid.
the class SchedV2 method deckDueList.
// Overridden
@Nullable
public List<DeckDueTreeNode> deckDueList(@Nullable CancelListener collectionTask) {
_checkDay();
mCol.getDecks().checkIntegrity();
List<Deck> decks = mCol.getDecks().allSorted();
HashMap<String, Integer[]> lims = HashUtil.HashMapInit(decks.size());
ArrayList<DeckDueTreeNode> deckNodes = new ArrayList<>(decks.size());
Decks.Node childMap = mCol.getDecks().childMap();
for (Deck deck : decks) {
if (isCancelled(collectionTask)) {
return null;
}
String deckName = deck.getString("name");
String p = Decks.parent(deckName);
// new
int nlim = _deckNewLimitSingle(deck, false);
Integer plim = null;
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]);
// reviews
plim = parentLims[1];
}
int _new = _newForDeck(deck.getLong("id"), nlim);
// learning
int lrn = _lrnForDeck(deck.getLong("id"));
// reviews
int rlim = _deckRevLimitSingle(deck, plim, false);
int rev = _revForDeck(deck.getLong("id"), rlim, childMap);
// save to list
deckNodes.add(new DeckDueTreeNode(mCol, deck.getString("name"), deck.getLong("id"), rev, lrn, _new));
// add deck as a parent
lims.put(Decks.normalizeName(deck.getString("name")), new Integer[] { nlim, rlim });
}
return deckNodes;
}
use of com.ichi2.libanki.sched.DeckDueTreeNode in project Anki-Android by ankidroid.
the class CardContentProvider method query.
@Override
public Cursor query(@NonNull 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);
// Needed for varargs of query
return col.getDb().query(sql, (Object[]) 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().query(sql, 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:
{
ModelManager 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 */
ModelManager 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 */
ModelManager 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.parseInt(value);
} else if ("deckID".equals(keyAndValue[0].trim())) {
deckIdOfTemporarilySelectedDeck = Long.parseLong(value);
if (!selectDeckWithCheck(col, deckIdOfTemporarilySelectedDeck)) {
// if the provided deckID is wrong, return empty cursor.
return rv;
}
}
} catch (NumberFormatException nfe) {
Timber.w(nfe);
}
}
}
// 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 = 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(Collections.singletonList(col.getSched().counts()));
addDeckToCursor(id, name, counts, rv, col, columns);
return rv;
}
default:
// Unknown URI type
throw new IllegalArgumentException("uri " + uri + " is not supported");
}
}
Aggregations