use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Finder method ordForMid.
/**
* Find duplicates
* ***********************************************************
*/
public static Integer ordForMid(Collection col, Map<Long, Integer> fields, long mid, String fieldName) {
if (!fields.containsKey(mid)) {
JSONObject model = col.getModels().get(mid);
JSONArray flds = model.getJSONArray("flds");
for (int c = 0; c < flds.length(); c++) {
JSONObject f = flds.getJSONObject(c);
if (f.getString("name").equalsIgnoreCase(fieldName)) {
fields.put(mid, c);
break;
}
}
}
return fields.get(mid);
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Media method filesInStr.
/**
* Extract media filenames from an HTML string.
*
* @param string The string to scan for media filenames ([sound:...] or <img...>).
* @param includeRemote If true will also include external http/https/ftp urls.
* @return A list containing all the sound and image filenames found in the input string.
*/
public static List<String> filesInStr(Collection mCol, Long mid, String string, boolean includeRemote) {
List<String> l = new ArrayList<>();
JSONObject model = mCol.getModels().get(mid);
List<String> strings = new ArrayList<>();
if (model.getInt("type") == Consts.MODEL_CLOZE && string.contains("{{c")) {
// if the field has clozes in it, we'll need to expand the
// possibilities so we can render latex
strings = _expandClozes(string);
} else {
strings.add(string);
}
for (String s : strings) {
// handle latex
s = LaTeX.mungeQA(s, mCol, model);
// extract filenames
Matcher m;
for (Pattern p : mRegexps) {
// NOTE: python uses the named group 'fname'. Java doesn't have named groups, so we have to determine
// the index based on which pattern we are using
int fnameIdx = p.equals(fSoundRegexps) ? 2 : p.equals(fImgRegExpU) ? 2 : 3;
m = p.matcher(s);
while (m.find()) {
String fname = m.group(fnameIdx);
boolean isLocal = !fRemotePattern.matcher(fname.toLowerCase(Locale.US)).find();
if (isLocal || includeRemote) {
l.add(fname);
}
}
}
}
return l;
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Collection method basicCheck.
/**
* DB maintenance *********************************************************** ************************************
*/
/*
* Basic integrity check for syncing. True if ok.
*/
public boolean basicCheck() {
// cards without notes
if (mDb.queryScalar("select 1 from cards where nid not in (select id from notes) limit 1") > 0) {
return false;
}
boolean badNotes = mDb.queryScalar("select 1 from notes where id not in (select distinct nid from cards) " + "or mid not in " + Utils.ids2str(getModels().ids()) + " limit 1") > 0;
// notes without cards or models
if (badNotes) {
return false;
}
// invalid ords
for (JSONObject m : getModels().all()) {
// ignore clozes
if (m.getInt("type") != Consts.MODEL_STD) {
continue;
}
// Make a list of valid ords for this model
JSONArray tmpls = m.getJSONArray("tmpls");
boolean badOrd = mDb.queryScalar("select 1 from cards where (ord < 0 or ord >= ?) and nid in ( " + "select id from notes where mid = ?) limit 1", tmpls.length(), m.getLong("id")) > 0;
if (badOrd) {
return false;
}
}
return true;
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Collection method genCards.
public ArrayList<Long> genCards(long[] nids) {
// build map of (nid,ord) so we don't create dupes
String snids = Utils.ids2str(nids);
HashMap<Long, HashMap<Integer, Long>> have = new HashMap<>();
HashMap<Long, Long> dids = new HashMap<>();
HashMap<Long, Long> dues = new HashMap<>();
Cursor cur = null;
try {
cur = mDb.getDatabase().query("select id, nid, ord, did, due, odue, odid, type from cards where nid in " + snids, null);
while (cur.moveToNext()) {
long id = cur.getLong(0);
long nid = cur.getLong(1);
int ord = cur.getInt(2);
long did = cur.getLong(3);
long due = cur.getLong(4);
long odue = cur.getLong(5);
long odid = cur.getLong(6);
@Consts.CARD_TYPE int type = cur.getInt(7);
// existing cards
if (!have.containsKey(nid)) {
have.put(nid, new HashMap<Integer, Long>());
}
have.get(nid).put(ord, id);
// if in a filtered deck, add new cards to original deck
if (odid != 0) {
did = odid;
}
// and their dids
if (dids.containsKey(nid)) {
if (dids.get(nid) != 0 && dids.get(nid) != did) {
// cards are in two or more different decks; revert to model default
dids.put(nid, 0L);
}
} else {
// first card or multiple cards in same deck
dids.put(nid, did);
}
// save due
if (odid != 0) {
due = odue;
}
if (!dues.containsKey(nid) && type == Consts.CARD_TYPE_NEW) {
dues.put(nid, due);
}
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
// build cards for each note
ArrayList<Object[]> data = new ArrayList<>();
long ts = getTime().maxID(mDb);
long now = getTime().intTime();
ArrayList<Long> rem = new ArrayList<>();
int usn = usn();
cur = null;
try {
cur = mDb.getDatabase().query("SELECT id, mid, flds FROM notes WHERE id IN " + snids, null);
while (cur.moveToNext()) {
long nid = cur.getLong(0);
long mid = cur.getLong(1);
String flds = cur.getString(2);
Model model = getModels().get(mid);
ArrayList<Integer> avail = getModels().availOrds(model, Utils.splitFields(flds));
Long did = dids.get(nid);
// use sibling due if there is one, else use a new id
long due;
if (dues.containsKey(nid)) {
due = dues.get(nid);
} else {
due = nextID("pos");
}
if (did == null || did == 0L) {
did = model.getLong("did");
}
// add any missing cards
for (JSONObject t : _tmplsFromOrds(model, avail)) {
int tord = t.getInt("ord");
boolean doHave = have.containsKey(nid) && have.get(nid).containsKey(tord);
if (!doHave) {
// check deck is not a cram deck
long ndid;
try {
ndid = t.getLong("did");
if (ndid != 0) {
did = ndid;
}
} catch (JSONException e) {
// do nothing
}
if (getDecks().isDyn(did)) {
did = 1L;
}
// if the deck doesn't exist, use default instead
did = mDecks.get(did).getLong("id");
// give it a new id instead
data.add(new Object[] { ts, nid, did, tord, now, usn, due });
ts += 1;
}
}
// note any cards that need removing
if (have.containsKey(nid)) {
for (Map.Entry<Integer, Long> n : have.get(nid).entrySet()) {
if (!avail.contains(n.getKey())) {
rem.add(n.getValue());
}
}
}
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
// bulk update
mDb.executeMany("INSERT INTO cards VALUES (?,?,?,?,?,?,0,0,?,0,0,0,0,0,0,0,0,\"\")", data);
return rem;
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Models method scmhash.
/**
* Schema hash ***********************************************************************************************
*/
/**
* Return a hash of the schema, to see if models are compatible.
*/
public String scmhash(Model m) {
String s = "";
JSONArray flds = m.getJSONArray("flds");
for (int i = 0; i < flds.length(); ++i) {
s += flds.getJSONObject(i).getString("name");
}
JSONArray tmpls = m.getJSONArray("tmpls");
for (int i = 0; i < tmpls.length(); ++i) {
JSONObject t = tmpls.getJSONObject(i);
s += t.getString("name");
}
return Utils.checksum(s);
}
Aggregations