Search in sources :

Example 76 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class Decks method update.

/**
 * {@inheritDoc}
 */
@Override
public void update(@NonNull Deck g) {
    long id = g.getLong("id");
    JSONObject oldDeck = get(id, false);
    if (oldDeck != null) {
        // In case where another update got the name
        // `oldName`, it would be a mistake to remove it from nameMap
        mNameMap.remove(oldDeck.getString("name"), oldDeck);
    }
    mNameMap.add(g);
    mDecks.put(g.getLong("id"), g);
    maybeAddToActive();
    // mark registry changed, but don't bump mod time
    save();
}
Also used : JSONObject(com.ichi2.utils.JSONObject)

Example 77 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class Anki2Importer method _importCards.

/**
 * Cards
 * ***********************************************************
 */
private void _importCards() {
    if (mMustResetLearning) {
        try {
            mSrc.changeSchedulerVer(2);
        } catch (ConfirmModSchemaException e) {
            throw new RuntimeException("Changing the scheduler of an import should not cause schema modification", e);
        }
    }
    // build map of guid -> (ord -> cid) and used id cache
    /*
         * Since we can't use a tuple as a key in Java, we resort to indexing twice with nested maps.
         * Python: (guid, ord) -> cid
         * Java: guid -> ord -> cid
         */
    int nbCard = mDst.cardCount();
    Map<String, Map<Integer, Long>> cardsByGuid = HashUtil.HashMapInit(nbCard);
    Set<Long> existing = HashUtil.HashSetInit(nbCard);
    try (Cursor cur = mDst.getDb().query("select f.guid, c.ord, c.id from cards c, notes f " + "where c.nid = f.id")) {
        while (cur.moveToNext()) {
            String guid = cur.getString(0);
            int ord = cur.getInt(1);
            long cid = cur.getLong(2);
            existing.add(cid);
            if (cardsByGuid.containsKey(guid)) {
                cardsByGuid.get(guid).put(ord, cid);
            } else {
                // The size is at most the number of card type in the note type.
                Map<Integer, Long> map = new HashMap<>();
                map.put(ord, cid);
                cardsByGuid.put(guid, map);
            }
        }
    }
    // loop through src
    int nbCardsToImport = mSrc.cardCount();
    List<Object[]> cards = new ArrayList<>(nbCardsToImport);
    int totalCardCount = 0;
    final int thresExecCards = 1000;
    List<Object[]> revlog = new ArrayList<>(mSrc.getSched().logCount());
    int totalRevlogCount = 0;
    final int thresExecRevlog = 1000;
    int usn = mDst.usn();
    long aheadBy = mSrc.getSched().getToday() - mDst.getSched().getToday();
    mDst.getDb().getDatabase().beginTransaction();
    try (Cursor cur = mSrc.getDb().query("select f.guid, c.id, c.did, c.ord, c.type, c.queue, c.due, c.ivl, c.factor, c.reps, c.lapses, c.left, c.odue, c.odid, c.flags, c.data from cards c, notes f " + "where c.nid = f.id")) {
        // Counters for progress updates
        int total = cur.getCount();
        boolean largeCollection = total > 200;
        int onePercent = total / 100;
        int i = 0;
        while (cur.moveToNext()) {
            String guid = cur.getString(0);
            long cid = cur.getLong(1);
            // To keep track of card id in source
            long scid = cid;
            long did = cur.getLong(2);
            int ord = cur.getInt(3);
            @Consts.CARD_TYPE int type = cur.getInt(4);
            @Consts.CARD_QUEUE int queue = cur.getInt(5);
            long due = cur.getLong(6);
            long ivl = cur.getLong(7);
            long factor = cur.getLong(8);
            int reps = cur.getInt(9);
            int lapses = cur.getInt(10);
            int left = cur.getInt(11);
            long odue = cur.getLong(12);
            long odid = cur.getLong(13);
            int flags = cur.getInt(14);
            String data = cur.getString(15);
            if (mIgnoredGuids.contains(guid)) {
                continue;
            }
            // does the card's note exist in dst col?
            if (!mNotes.containsKey(guid)) {
                continue;
            }
            NoteTriple dnid = mNotes.get(guid);
            // does the card already exist in the dst col?
            if (cardsByGuid.containsKey(guid) && cardsByGuid.get(guid).containsKey(ord)) {
                // fixme: in future, could update if newer mod time
                continue;
            }
            // ensure the card id is unique
            while (existing.contains(cid)) {
                cid += 999;
            }
            existing.add(cid);
            // update cid, nid, etc
            long nid = mNotes.get(guid).mNid;
            did = _did(did);
            long mod = mCol.getTime().intTime();
            // review cards have a due date relative to collection
            if (queue == QUEUE_TYPE_REV || queue == QUEUE_TYPE_DAY_LEARN_RELEARN || type == CARD_TYPE_REV) {
                due -= aheadBy;
            }
            // odue needs updating too
            if (odue != 0) {
                odue -= aheadBy;
            }
            // if odid true, convert card from filtered to normal
            if (odid != 0) {
                // odid
                odid = 0;
                // odue
                due = odue;
                odue = 0;
                // queue
                if (type == CARD_TYPE_LRN) {
                    // type
                    queue = QUEUE_TYPE_NEW;
                } else {
                    queue = type;
                }
                // type
                if (type == CARD_TYPE_LRN) {
                    type = CARD_TYPE_NEW;
                }
            }
            cards.add(new Object[] { cid, nid, did, ord, mod, usn, type, queue, due, ivl, factor, reps, lapses, left, odue, odid, flags, data });
            // we need to import revlog, rewriting card ids and bumping usn
            try (Cursor cur2 = mSrc.getDb().query("select * from revlog where cid = " + scid)) {
                while (cur2.moveToNext()) {
                    Object[] rev = new Object[] { cur2.getLong(0), cur2.getLong(1), cur2.getInt(2), cur2.getInt(3), cur2.getLong(4), cur2.getLong(5), cur2.getLong(6), cur2.getLong(7), cur2.getInt(8) };
                    rev[1] = cid;
                    rev[2] = mDst.usn();
                    revlog.add(rev);
                }
            }
            i++;
            // apply card changes partially
            if (cards.size() >= thresExecCards) {
                totalCardCount += cards.size();
                insertCards(cards);
                cards.clear();
                Timber.d("add cards: %d", totalCardCount);
            }
            // apply revlog changes partially
            if (revlog.size() >= thresExecRevlog) {
                totalRevlogCount += revlog.size();
                insertRevlog(revlog);
                revlog.clear();
                Timber.d("add revlog: %d", totalRevlogCount);
            }
            if (total != 0 && (!largeCollection || i % onePercent == 0)) {
                publishProgress(100, i * 100 / total, 0);
            }
        }
        publishProgress(100, 100, 0);
        // count total values
        totalCardCount += cards.size();
        totalRevlogCount += revlog.size();
        Timber.d("add cards total:  %d", totalCardCount);
        Timber.d("add revlog total: %d", totalRevlogCount);
        // apply (for last chunk)
        insertCards(cards);
        cards.clear();
        insertRevlog(revlog);
        revlog.clear();
        mLog.add(getRes().getString(R.string.import_complete_count, totalCardCount));
        mDst.getDb().getDatabase().setTransactionSuccessful();
    } finally {
        DB.safeEndInTransaction(mDst.getDb());
    }
}
Also used : HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) Cursor(android.database.Cursor) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) HashMap(java.util.HashMap) Map(java.util.Map)

Example 78 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class Storage method Collection.

public static Collection Collection(Context context, @NonNull String path, boolean server, boolean log, @NonNull Time time) {
    assert (path.endsWith(".anki2") || path.endsWith(".anki21"));
    File dbFile = new File(path);
    boolean create = !dbFile.exists();
    DroidBackend backend = DroidBackendFactory.getInstance(useBackend());
    DB db = backend.openCollectionDatabase(sUseInMemory ? ":memory:" : path);
    try {
        // initialize
        int ver;
        if (create) {
            ver = _createDB(db, time, backend);
        } else {
            ver = _upgradeSchema(db, time);
        }
        db.execute("PRAGMA temp_store = memory");
        // add db to col and do any remaining upgrades
        Collection col = backend.createCollection(context, db, path, server, log, time);
        if (ver < Consts.SCHEMA_VERSION) {
            _upgrade(col, ver);
        } else if (ver > Consts.SCHEMA_VERSION) {
            throw new RuntimeException("This file requires a newer version of Anki.");
        } else if (create) {
            addNoteTypes(col, backend);
            col.onCreate();
            col.save();
        }
        return col;
    } catch (Exception e) {
        Timber.e(e, "Error opening collection; closing database");
        db.close();
        throw e;
    }
}
Also used : DroidBackend(com.ichi2.libanki.backend.DroidBackend) File(java.io.File) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) FileNotFoundException(java.io.FileNotFoundException) JSONException(com.ichi2.utils.JSONException) UnknownDatabaseVersionException(com.ichi2.libanki.exception.UnknownDatabaseVersionException)

Example 79 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class Storage method _setColVars.

private static void _setColVars(DB db, @NonNull Time time) {
    JSONObject g = new JSONObject(Decks.DEFAULT_DECK);
    g.put("id", 1);
    g.put("name", "Default");
    g.put("conf", 1);
    g.put("mod", time.intTime());
    JSONObject gc = new JSONObject(Decks.DEFAULT_CONF);
    gc.put("id", 1);
    JSONObject ag = new JSONObject();
    ag.put("1", g);
    JSONObject agc = new JSONObject();
    agc.put("1", gc);
    ContentValues values = new ContentValues();
    values.put("conf", Collection.DEFAULT_CONF);
    values.put("decks", Utils.jsonToString(ag));
    values.put("dconf", Utils.jsonToString(agc));
    db.update("col", values);
}
Also used : ContentValues(android.content.ContentValues) JSONObject(com.ichi2.utils.JSONObject)

Example 80 with Time

use of com.ichi2.libanki.utils.Time in project Anki-Android by ankidroid.

the class ModelFieldEditor method repositionFieldDialog.

/*
     * Allows the user to select a number less than the number of fields in the current model to
     * reposition the current field to
     * Processing time is scales with number of items
     */
private void repositionFieldDialog() {
    mFieldNameInput = new FixedEditText(this);
    mFieldNameInput.setRawInputType(InputType.TYPE_CLASS_NUMBER);
    new MaterialEditTextDialog.Builder(this, mFieldNameInput).title(String.format(getResources().getString(R.string.model_field_editor_reposition), 1, mFieldLabels.size())).positiveText(R.string.dialog_ok).onPositive((dialog, which) -> {
        String newPosition = mFieldNameInput.getText().toString();
        int pos;
        try {
            pos = Integer.parseInt(newPosition);
        } catch (NumberFormatException n) {
            Timber.w(n);
            UIUtils.showThemedToast(this, getResources().getString(R.string.toast_out_of_range), true);
            return;
        }
        if (pos < 1 || pos > mFieldLabels.size()) {
            UIUtils.showThemedToast(this, getResources().getString(R.string.toast_out_of_range), true);
        } else {
            changeHandler listener = changeFieldHandler();
            // Input is valid, now attempt to modify
            try {
                mCol.modSchema();
                TaskManager.launchCollectionTask(new CollectionTask.RepositionField(mMod, mNoteFields.getJSONObject(mCurrentPos), pos - 1), listener);
            } catch (ConfirmModSchemaException e) {
                e.log();
                // Handle mod schema confirmation
                ConfirmationDialog c = new ConfirmationDialog();
                c.setArgs(getResources().getString(R.string.full_sync_confirmation));
                Runnable confirm = () -> {
                    try {
                        mCol.modSchemaNoCheck();
                        TaskManager.launchCollectionTask(new CollectionTask.RepositionField(mMod, mNoteFields.getJSONObject(mCurrentPos), pos - 1), listener);
                        dismissContextMenu();
                    } catch (JSONException e1) {
                        throw new RuntimeException(e1);
                    }
                };
                c.setConfirm(confirm);
                c.setCancel(mConfirmDialogCancel);
                ModelFieldEditor.this.showDialogFragment(c);
            }
        }
    }).negativeText(R.string.dialog_cancel).show();
}
Also used : JSONException(com.ichi2.utils.JSONException) CollectionTask(com.ichi2.async.CollectionTask) ConfirmationDialog(com.ichi2.anki.dialogs.ConfirmationDialog) ConfirmModSchemaException(com.ichi2.anki.exception.ConfirmModSchemaException) FixedEditText(com.ichi2.ui.FixedEditText)

Aggregations

Test (org.junit.Test)27 Collection (com.ichi2.libanki.Collection)26 JSONObject (com.ichi2.utils.JSONObject)26 RobolectricTest (com.ichi2.anki.RobolectricTest)19 Card (com.ichi2.libanki.Card)19 Note (com.ichi2.libanki.Note)15 JSONArray (com.ichi2.utils.JSONArray)15 Deck (com.ichi2.libanki.Deck)11 ArrayList (java.util.ArrayList)11 DeckConfig (com.ichi2.libanki.DeckConfig)10 IOException (java.io.IOException)10 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)9 HashMap (java.util.HashMap)9 Cursor (android.database.Cursor)8 Nullable (androidx.annotation.Nullable)8 JSONException (com.ichi2.utils.JSONException)8 SharedPreferences (android.content.SharedPreferences)7 Resources (android.content.res.Resources)7 File (java.io.File)7 View (android.view.View)5