Search in sources :

Example 91 with Model

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

the class Models method load.

/**
 * {@inheritDoc}
 */
@Override
public void load(@NonNull String json) {
    mChanged = false;
    mModels = new HashMap<>();
    JSONObject modelarray = new JSONObject(json);
    JSONArray ids = modelarray.names();
    if (ids != null) {
        for (String id : ids.stringIterable()) {
            Model o = new Model(modelarray.getJSONObject(id));
            mModels.put(o.getLong("id"), o);
        }
    }
}
Also used : JSONObject(com.ichi2.utils.JSONObject) JSONArray(com.ichi2.utils.JSONArray)

Example 92 with Model

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

the class Models method scmhash.

/*
      Schema hash ***********************************************************************************************
     */
@NonNull
@Override
public String scmhash(Model m) {
    StringBuilder s = new StringBuilder();
    JSONArray flds = m.getJSONArray("flds");
    for (JSONObject fld : flds.jsonObjectIterable()) {
        s.append(fld.getString("name"));
    }
    JSONArray tmpls = m.getJSONArray("tmpls");
    for (JSONObject t : tmpls.jsonObjectIterable()) {
        s.append(t.getString("name"));
    }
    return Utils.checksum(s.toString());
}
Also used : JSONObject(com.ichi2.utils.JSONObject) JSONArray(com.ichi2.utils.JSONArray) NonNull(androidx.annotation.NonNull)

Example 93 with Model

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

the class Storage method _upgradeClozeModel.

private static void _upgradeClozeModel(Collection col, Model m) throws ConfirmModSchemaException {
    m.put("type", Consts.MODEL_CLOZE);
    // convert first template
    JSONObject t = m.getJSONArray("tmpls").getJSONObject(0);
    for (String type : new String[] { "qfmt", "afmt" }) {
        // noinspection RegExpRedundantEscape            // In Android, } should be escaped
        t.put(type, t.getString(type).replaceAll("\\{\\{cloze:1:(.+?)\\}\\}", "{{cloze:$1}}"));
    }
    t.put("name", "Cloze");
    // delete non-cloze cards for the model
    JSONArray tmpls = m.getJSONArray("tmpls");
    ArrayList<JSONObject> rem = new ArrayList<>();
    for (JSONObject ta : tmpls.jsonObjectIterable()) {
        if (!ta.getString("afmt").contains("{{cloze:")) {
            rem.add(ta);
        }
    }
    for (JSONObject r : rem) {
        col.getModels().remTemplate(m, r);
    }
    JSONArray newTmpls = new JSONArray();
    newTmpls.put(tmpls.getJSONObject(0));
    m.put("tmpls", newTmpls);
    Models._updateTemplOrds(m);
    col.getModels().save(m);
}
Also used : JSONObject(com.ichi2.utils.JSONObject) JSONArray(com.ichi2.utils.JSONArray) ArrayList(java.util.ArrayList)

Example 94 with Model

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

the class Syncer method sanityCheck.

public JSONObject sanityCheck() {
    JSONObject result = new JSONObject();
    try {
        if (mCol.getDb().queryScalar("SELECT count() FROM cards WHERE nid NOT IN (SELECT id FROM notes)") != 0) {
            Timber.e("Sync - SanityCheck: there are cards without mother notes");
            result.put("client", "missing notes");
            return result;
        }
        if (mCol.getDb().queryScalar("SELECT count() FROM notes WHERE id NOT IN (SELECT DISTINCT nid FROM cards)") != 0) {
            Timber.e("Sync - SanityCheck: there are notes without cards");
            result.put("client", "missing cards");
            return result;
        }
        if (mCol.getDb().queryScalar("SELECT count() FROM cards WHERE usn = -1") != 0) {
            Timber.e("Sync - SanityCheck: there are unsynced cards");
            result.put("client", "cards had usn = -1");
            return result;
        }
        if (mCol.getDb().queryScalar("SELECT count() FROM notes WHERE usn = -1") != 0) {
            Timber.e("Sync - SanityCheck: there are unsynced notes");
            result.put("client", "notes had usn = -1");
            return result;
        }
        if (mCol.getDb().queryScalar("SELECT count() FROM revlog WHERE usn = -1") != 0) {
            Timber.e("Sync - SanityCheck: there are unsynced revlogs");
            result.put("client", "revlog had usn = -1");
            return result;
        }
        if (mCol.getDb().queryScalar("SELECT count() FROM graves WHERE usn = -1") != 0) {
            Timber.e("Sync - SanityCheck: there are unsynced graves");
            result.put("client", "graves had usn = -1");
            return result;
        }
        for (Deck g : mCol.getDecks().all()) {
            if (g.getInt("usn") == -1) {
                Timber.e("Sync - SanityCheck: unsynced deck: %s", g.getString("name"));
                result.put("client", "deck had usn = -1");
                return result;
            }
        }
        if (mCol.getTags().minusOneValue()) {
            Timber.e("Sync - SanityCheck: there are unsynced tags");
            result.put("client", "tag had usn = -1");
            return result;
        }
        boolean found = false;
        for (JSONObject m : mCol.getModels().all()) {
            if (mCol.getServer()) {
                // the web upgrade was mistakenly setting usn
                if (m.getInt("usn") < 0) {
                    m.put("usn", 0);
                    found = true;
                }
            } else {
                if (m.getInt("usn") == -1) {
                    Timber.e("Sync - SanityCheck: unsynced model: %s", m.getString("name"));
                    result.put("client", "model had usn = -1");
                    return result;
                }
            }
        }
        if (found) {
            mCol.getModels().save();
        }
        // check for missing parent decks
        mCol.getSched().deckDueList();
        // return summary of deck
        JSONArray check = new JSONArray();
        JSONArray counts = new JSONArray();
        // #5666 - not in libAnki
        // We modified mReportLimit inside the scheduler, and this causes issues syncing dynamic decks.
        AbstractSched syncScheduler = mCol.createScheduler(SYNC_SCHEDULER_REPORT_LIMIT);
        syncScheduler.resetCounts();
        Counts counts_ = syncScheduler.counts();
        counts.put(counts_.getNew());
        counts.put(counts_.getLrn());
        counts.put(counts_.getRev());
        check.put(counts);
        check.put(mCol.getDb().queryScalar("SELECT count() FROM cards"));
        check.put(mCol.getDb().queryScalar("SELECT count() FROM notes"));
        check.put(mCol.getDb().queryScalar("SELECT count() FROM revlog"));
        check.put(mCol.getDb().queryScalar("SELECT count() FROM graves"));
        check.put(mCol.getModels().all().size());
        check.put(mCol.getDecks().all().size());
        check.put(mCol.getDecks().allConf().size());
        result.put("client", check);
        return result;
    } catch (JSONException e) {
        Timber.e(e, "Syncer.sanityCheck()");
        throw new RuntimeException(e);
    }
}
Also used : Counts(com.ichi2.libanki.sched.Counts) JSONObject(com.ichi2.utils.JSONObject) AbstractSched(com.ichi2.libanki.sched.AbstractSched) JSONArray(com.ichi2.utils.JSONArray) Deck(com.ichi2.libanki.Deck) JSONException(com.ichi2.utils.JSONException)

Example 95 with Model

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

the class CollectionTest method test_furigana.

@Test
@Ignore("Pending port of media search from Rust code")
public void test_furigana() {
    Collection col = getCol();
    ModelManager mm = col.getModels();
    Model m = mm.current();
    // filter should work
    m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:Front}}");
    mm.save(m);
    Note n = col.newNote();
    n.setItem("Front", "foo[abc]");
    col.addNote(n);
    Card c = n.cards().get(0);
    assertTrue(c.q().endsWith("abc"));
    // and should avoid sound
    n.setItem("Front", "foo[sound:abc.mp3]");
    n.flush();
    String question = c.q(true);
    assertThat("Question «" + question + "» does not contains «anki:play».", question, containsString("anki:play"));
    // it shouldn't throw an error while people are editing
    m.getJSONArray("tmpls").getJSONObject(0).put("qfmt", "{{kana:}}");
    mm.save(m);
    c.q(true);
}
Also used : Matchers.containsString(org.hamcrest.Matchers.containsString) Ignore(org.junit.Ignore) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Aggregations

JSONObject (com.ichi2.utils.JSONObject)124 Model (com.ichi2.libanki.Model)95 Test (org.junit.Test)82 JSONArray (com.ichi2.utils.JSONArray)79 Collection (com.ichi2.libanki.Collection)53 ArrayList (java.util.ArrayList)48 Note (com.ichi2.libanki.Note)40 RobolectricTest (com.ichi2.anki.RobolectricTest)38 JSONException (com.ichi2.utils.JSONException)32 Intent (android.content.Intent)30 Card (com.ichi2.libanki.Card)27 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)26 HashMap (java.util.HashMap)22 Bundle (android.os.Bundle)20 NonNull (androidx.annotation.NonNull)20 SuppressLint (android.annotation.SuppressLint)16 View (android.view.View)16 ConfirmationDialog (com.ichi2.anki.dialogs.ConfirmationDialog)15 IOException (java.io.IOException)15 Nullable (androidx.annotation.Nullable)14