Search in sources :

Example 36 with Template

use of com.ichi2.libanki.template.Template 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 37 with Template

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

the class CollectionTest method test_noteAddDelete.

/**
 *****************
 ** autogenerated from https://github.com/ankitects/anki/blob/2c73dcb2e547c44d9e02c20a00f3c52419dc277b/pylib/tests/test_cards.py *
 ******************
 */
/*TODO
      @Test
      public void test_create_open(){
      (fd, path) = tempfile.mkstemp(suffix=".anki2", prefix="test_attachNew");
      try {
      os.close(fd);
      os.unlink(path);
      } catch (OSError) {
      }
      Collection col = aopen(path);
      // for open()
      String newPath = col.getPath();
      long newMod = col.getMod();
      col.close();

      // reopen
      col = aopen(newPath);
      assertEquals(newMod, col.getMod());
      col.close();

      // non-writeable dir
      if (isWin) {
      String dir = "c:\root.anki2";
      } else {
      String dir = "/attachroot.anki2";
      }
      assertException(Exception, lambda: aopen(dir));
      // reuse tmp file from before, test non-writeable file
      os.chmod(newPath, 0);
      assertException(Exception, lambda: aopen(newPath));
      os.chmod(newPath, 0o666);
      os.unlink(newPath);
      } */
@Test
public void test_noteAddDelete() {
    Collection col = getCol();
    // add a note
    Note note = col.newNote();
    note.setItem("Front", "one");
    note.setItem("Back", "two");
    int n = col.addNote(note);
    assertEquals(1, n);
    // test multiple cards - add another template
    Model m = col.getModels().current();
    ModelManager mm = col.getModels();
    JSONObject t = Models.newTemplate("Reverse");
    t.put("qfmt", "{{Back}}");
    t.put("afmt", "{{Front}}");
    mm.addTemplateModChanged(m, t);
    // todo: remove true which is not upstream
    mm.save(m, true);
    assertEquals(2, col.cardCount());
    // creating new notes should use both cards
    note = col.newNote();
    note.setItem("Front", "three");
    note.setItem("Back", "four");
    n = col.addNote(note);
    assertEquals(2, n);
    assertEquals(4, col.cardCount());
    // check q/a generation
    Card c0 = note.cards().get(0);
    assertThat(c0.q(), containsString("three"));
    // it should not be a duplicate
    assertEquals(note.dupeOrEmpty(), Note.DupeOrEmpty.CORRECT);
    // now let's make a duplicate
    Note note2 = col.newNote();
    note2.setItem("Front", "one");
    note2.setItem("Back", "");
    assertNotEquals(note2.dupeOrEmpty(), Note.DupeOrEmpty.CORRECT);
    // empty first field should not be permitted either
    note2.setItem("Front", " ");
    assertNotEquals(note2.dupeOrEmpty(), Note.DupeOrEmpty.CORRECT);
}
Also used : JSONObject(com.ichi2.utils.JSONObject) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 38 with Template

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

the class TemporaryModelTest method testAddDeleteTracking.

@Test
public void testAddDeleteTracking() {
    // Assume you start with a 2 template model (like "Basic (and reversed)")
    // Add a 3rd new template, remove the 2nd, remove the 1st, add a new now-2nd, remove 1st again
    // ...and it should reduce to just removing the original 1st/2nd and adding the final as first
    TemporaryModel tempModel = new TemporaryModel(new Model("{ \"foo\": \"bar\" }"));
    tempModel.addTemplateChange(ADD, 3);
    Object[][] expected1 = { { 3, ADD } };
    // 3 templates and one change now
    assertTemplateChangesEqual(expected1, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(expected1, tempModel.getAdjustedTemplateChanges());
    Assert.assertArrayEquals(new int[] { 3 }, tempModel.getDeleteDbOrds(3));
    tempModel.addTemplateChange(DELETE, 2);
    // 2 templates and two changes now
    Object[][] expected2 = { { 3, ADD }, { 2, DELETE } };
    Object[][] adjExpected2 = { { 2, ADD }, { 2, DELETE } };
    assertTemplateChangesEqual(expected2, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(adjExpected2, tempModel.getAdjustedTemplateChanges());
    Assert.assertArrayEquals(new int[] { 2, 4 }, tempModel.getDeleteDbOrds(3));
    tempModel.addTemplateChange(DELETE, 1);
    // 1 template and three changes now
    Assert.assertArrayEquals(new int[] { 2, 1, 5 }, tempModel.getDeleteDbOrds(3));
    Object[][] expected3 = { { 3, ADD }, { 2, DELETE }, { 1, DELETE } };
    Object[][] adjExpected3 = { { 1, ADD }, { 2, DELETE }, { 1, DELETE } };
    assertTemplateChangesEqual(expected3, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(adjExpected3, tempModel.getAdjustedTemplateChanges());
    tempModel.addTemplateChange(ADD, 2);
    // 2 templates and 4 changes now
    Assert.assertArrayEquals(new int[] { 2, 1, 5 }, tempModel.getDeleteDbOrds(3));
    Object[][] expected4 = { { 3, ADD }, { 2, DELETE }, { 1, DELETE }, { 2, ADD } };
    Object[][] adjExpected4 = { { 1, ADD }, { 2, DELETE }, { 1, DELETE }, { 2, ADD } };
    assertTemplateChangesEqual(expected4, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(adjExpected4, tempModel.getAdjustedTemplateChanges());
    // Make sure we can resurrect these changes across lifecycle
    Bundle outBundle = tempModel.toBundle();
    assertTemplateChangesEqual(expected4, outBundle.getSerializable("mTemplateChanges"));
    // This is the hard part. We will delete a template we added so everything shifts.
    // The template currently at ordinal 1 was added as template 3 at the start before it slid down on the deletes
    // So the first template add should be negated by this delete, and the second template add should slide down to 1
    tempModel.addTemplateChange(DELETE, 1);
    // 1 template and 3 changes now (the delete just cancelled out one of the adds)
    Assert.assertArrayEquals(new int[] { 2, 1, 5 }, tempModel.getDeleteDbOrds(3));
    Object[][] expected5 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD } };
    Object[][] adjExpected5 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD } };
    assertTemplateChangesEqual(expected5, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(adjExpected5, tempModel.getAdjustedTemplateChanges());
    tempModel.addTemplateChange(ADD, 2);
    // 2 template and 4 changes now (the delete just cancelled out one of the adds)
    Assert.assertArrayEquals(new int[] { 2, 1, 5 }, tempModel.getDeleteDbOrds(3));
    Object[][] expected6 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD }, { 2, ADD } };
    Object[][] adjExpected6 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD }, { 2, ADD } };
    assertTemplateChangesEqual(expected6, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(adjExpected6, tempModel.getAdjustedTemplateChanges());
    tempModel.addTemplateChange(ADD, 3);
    // 2 template and 4 changes now (the delete just cancelled out one of the adds)
    Assert.assertArrayEquals(new int[] { 2, 1, 5 }, tempModel.getDeleteDbOrds(3));
    Object[][] expected7 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD }, { 2, ADD }, { 3, ADD } };
    Object[][] adjExpected7 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD }, { 2, ADD }, { 3, ADD } };
    assertTemplateChangesEqual(expected7, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(adjExpected7, tempModel.getAdjustedTemplateChanges());
    tempModel.addTemplateChange(DELETE, 3);
    // 1 template and 3 changes now (two deletes cancelled out adds)
    Assert.assertArrayEquals(new int[] { 2, 1, 5 }, tempModel.getDeleteDbOrds(3));
    Object[][] expected8 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD }, { 2, ADD } };
    Object[][] adjExpected8 = { { 2, DELETE }, { 1, DELETE }, { 1, ADD }, { 2, ADD } };
    assertTemplateChangesEqual(expected8, tempModel.getTemplateChanges());
    assertTemplateChangesEqual(adjExpected8, tempModel.getAdjustedTemplateChanges());
}
Also used : Bundle(android.os.Bundle) Model(com.ichi2.libanki.Model) Test(org.junit.Test)

Example 39 with Template

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

the class ModelTest method test_cloze_ordinals.

@Test
public void test_cloze_ordinals() throws ConfirmModSchemaException {
    Collection col = getCol();
    col.getModels().setCurrent(col.getModels().byName("Cloze"));
    Model m = col.getModels().current();
    ModelManager mm = col.getModels();
    // We replace the default Cloze template
    JSONObject t = Models.newTemplate("ChainedCloze");
    t.put("qfmt", "{{text:cloze:Text}}");
    t.put("afmt", "{{text:cloze:Text}}");
    mm.addTemplateModChanged(m, t);
    mm.save(m);
    col.getModels().remTemplate(m, m.getJSONArray("tmpls").getJSONObject(0));
    Note note = col.newNote();
    note.setItem("Text", "{{c1::firstQ::firstA}}{{c2::secondQ::secondA}}");
    col.addNote(note);
    assertEquals(2, col.cardCount());
    List<Card> cards = note.cards();
    assertEquals(2, cards.size());
    Card c = cards.get(0);
    Card c2 = cards.get(1);
    // first card should have first ord
    assertEquals(0, c.getOrd());
    assertEquals(1, c2.getOrd());
}
Also used : JSONObject(com.ichi2.utils.JSONObject) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Example 40 with Template

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

the class ModelTest method test_modelChange.

@Test
public void test_modelChange() throws ConfirmModSchemaException {
    Collection col = getCol();
    Model cloze = col.getModels().byName("Cloze");
    // enable second template and add a note
    Model basic = col.getModels().current();
    ModelManager mm = col.getModels();
    JSONObject t = Models.newTemplate("Reverse");
    t.put("qfmt", "{{Back}}");
    t.put("afmt", "{{Front}}");
    mm.addTemplateModChanged(basic, t);
    mm.save(basic);
    Note note = col.newNote();
    note.setItem("Front", "note");
    note.setItem("Back", "b123");
    col.addNote(note);
    // switch fields
    Map<Integer, Integer> map = new HashMap<>();
    map.put(0, 1);
    map.put(1, 0);
    col.getModels().change(basic, note.getId(), basic, map, null);
    note.load();
    assertEquals("b123", note.getItem("Front"));
    assertEquals("note", note.getItem("Back"));
    // switch cards
    Card c0 = note.cards().get(0);
    Card c1 = note.cards().get(1);
    assertThat(c0.q(), containsString("b123"));
    assertThat(c1.q(), containsString("note"));
    assertEquals(0, c0.getOrd());
    assertEquals(1, c1.getOrd());
    col.getModels().change(basic, note.getId(), basic, null, map);
    note.load();
    c0.load();
    c1.load();
    assertThat(c0.q(), containsString("note"));
    assertThat(c1.q(), containsString("b123"));
    assertEquals(1, c0.getOrd());
    assertEquals(0, c1.getOrd());
    // .cards() returns cards in order
    assertEquals(c1.getId(), note.cards().get(0).getId());
    // delete first card
    map = new HashMap<>();
    map.put(0, null);
    map.put(1, 1);
    // if (isWin) {
    // // The low precision timer on Windows reveals a race condition
    // time.sleep(0.05);
    // }
    col.getModels().change(basic, note.getId(), basic, null, map);
    note.load();
    c0.load();
    // the card was deleted
    // but we have two cards, as a new one was generated
    assertEquals(2, note.numberOfCards());
    // an unmapped field becomes blank
    assertEquals("b123", note.getItem("Front"));
    assertEquals("note", note.getItem("Back"));
    col.getModels().change(basic, note.getId(), basic, map, null);
    note.load();
    assertEquals("", note.getItem("Front"));
    assertEquals("note", note.getItem("Back"));
    // another note to try model conversion
    note = col.newNote();
    note.setItem("Front", "f2");
    note.setItem("Back", "b2");
    col.addNote(note);
    // counts = col.getModels().all_use_counts();
    // Using older version of the test
    assertEquals(2, col.getModels().useCount(basic));
    assertEquals(0, col.getModels().useCount(cloze));
    // Identity map
    map = new HashMap<>();
    map.put(0, 0);
    map.put(1, 1);
    col.getModels().change(basic, note.getId(), cloze, map, map);
    note.load();
    assertEquals("f2", note.getItem("Text"));
    assertEquals(2, note.numberOfCards());
    // back the other way, with deletion of second ord
    col.getModels().remTemplate(basic, basic.getJSONArray("tmpls").getJSONObject(1));
    assertEquals(2, col.getDb().queryScalar("select count() from cards where nid = ?", note.getId()));
    map = new HashMap<>();
    map.put(0, 0);
    col.getModels().change(cloze, note.getId(), basic, map, map);
    assertEquals(1, col.getDb().queryScalar("select count() from cards where nid = ?", note.getId()));
}
Also used : JSONObject(com.ichi2.utils.JSONObject) HashMap(java.util.HashMap) RobolectricTest(com.ichi2.anki.RobolectricTest) Test(org.junit.Test)

Aggregations

JSONObject (com.ichi2.utils.JSONObject)53 Test (org.junit.Test)35 JSONArray (com.ichi2.utils.JSONArray)28 Model (com.ichi2.libanki.Model)24 ArrayList (java.util.ArrayList)16 Intent (android.content.Intent)14 RobolectricTest (com.ichi2.anki.RobolectricTest)14 Collection (com.ichi2.libanki.Collection)12 Note (com.ichi2.libanki.Note)12 SuppressLint (android.annotation.SuppressLint)9 HashMap (java.util.HashMap)8 Bundle (android.os.Bundle)7 JSONException (com.ichi2.utils.JSONException)7 ConfirmModSchemaException (com.ichi2.anki.exception.ConfirmModSchemaException)6 Card (com.ichi2.libanki.Card)6 ShadowActivity (org.robolectric.shadows.ShadowActivity)6 ShadowIntent (org.robolectric.shadows.ShadowIntent)6 View (android.view.View)5 ContentResolver (android.content.ContentResolver)4 ContentValues (android.content.ContentValues)4