use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Models method getTemplateNames.
public HashMap<Long, HashMap<Integer, String>> getTemplateNames() {
HashMap<Long, HashMap<Integer, String>> result = new HashMap<>();
for (Model m : mModels.values()) {
JSONArray templates;
templates = m.getJSONArray("tmpls");
HashMap<Integer, String> names = new HashMap<>();
for (int i = 0; i < templates.length(); i++) {
JSONObject t = templates.getJSONObject(i);
names.put(t.getInt("ord"), t.getString("name"));
}
result.put(m.getLong("id"), names);
}
return result;
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Collection method _renderQA.
public HashMap<String, String> _renderQA(long cid, Model model, long did, int ord, String tags, String[] flist, int flags, boolean browser, String qfmt, String afmt) {
// data is [cid, nid, mid, did, ord, tags, flds, cardFlags]
// unpack fields and create dict
Map<String, String> fields = new HashMap<>();
Map<String, Pair<Integer, JSONObject>> fmap = Models.fieldMap(model);
for (String name : fmap.keySet()) {
fields.put(name, flist[fmap.get(name).first]);
}
int cardNum = ord + 1;
fields.put("Tags", tags.trim());
fields.put("Type", model.getString("name"));
fields.put("Deck", mDecks.name(did));
String baseName = Decks.basename(fields.get("Deck"));
fields.put("Subdeck", baseName);
fields.put("CardFlag", _flagNameFromCardFlags(flags));
JSONObject template;
if (model.getInt("type") == Consts.MODEL_STD) {
template = model.getJSONArray("tmpls").getJSONObject(ord);
} else {
template = model.getJSONArray("tmpls").getJSONObject(0);
}
fields.put("Card", template.getString("name"));
fields.put(String.format(Locale.US, "c%d", cardNum), "1");
// render q & a
HashMap<String, String> d = new HashMap<>();
d.put("id", Long.toString(cid));
qfmt = TextUtils.isEmpty(qfmt) ? template.getString("qfmt") : qfmt;
afmt = TextUtils.isEmpty(afmt) ? template.getString("afmt") : afmt;
for (Pair<String, String> p : new Pair[] { new Pair<>("q", qfmt), new Pair<>("a", afmt) }) {
String type = p.first;
String format = p.second;
if ("q".equals(type)) {
format = fClozePatternQ.matcher(format).replaceAll(String.format(Locale.US, "{{$1cq-%d:", cardNum));
format = fClozeTagStart.matcher(format).replaceAll(String.format(Locale.US, "<%%cq:%d:", cardNum));
} else {
format = fClozePatternA.matcher(format).replaceAll(String.format(Locale.US, "{{$1ca-%d:", cardNum));
format = fClozeTagStart.matcher(format).replaceAll(String.format(Locale.US, "<%%ca:%d:", cardNum));
// the following line differs from libanki // TODO: why?
// fields.put("FrontSide", mMedia.stripAudio(d.get("q")));
fields.put("FrontSide", d.get("q"));
}
String html = new Template(format, fields).render();
html = ChessFilter.fenToChessboard(html, getContext());
if (!browser) {
// browser don't show image. So compiling LaTeX actually remove information.
html = LaTeX.mungeQA(html, this, model);
}
d.put(type, html);
// empty cloze?
if ("q".equals(type) && model.getInt("type") == Consts.MODEL_CLOZE) {
if (getModels()._availClozeOrds(model, flist, false).size() == 0) {
String link = String.format("<a href=%s#cloze>%s</a>", Consts.HELP_SITE, "help");
d.put("q", mContext.getString(R.string.empty_cloze_warning, link));
}
}
}
return d;
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class Syncer method mergeModels.
private void mergeModels(JSONArray rchg) throws UnexpectedSchemaChange {
for (int i = 0; i < rchg.length(); i++) {
Model r = new Model(rchg.getJSONObject(i));
Model l = mCol.getModels().get(r.getLong("id"));
// if missing locally or server is newer, update
if (l == null || r.getLong("mod") > l.getLong("mod")) {
// syncing algorithm should handle this in a better way.
if (l != null) {
if (l.getJSONArray("flds").length() != r.getJSONArray("flds").length()) {
throw new UnexpectedSchemaChange();
}
if (l.getJSONArray("tmpls").length() != r.getJSONArray("tmpls").length()) {
throw new UnexpectedSchemaChange();
}
}
mCol.getModels().update(r);
}
}
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class AnkiChinaSyncer method saveLatestData.
/**
* 同步结束后将数据写入synclog
*/
@SuppressLint("DefaultLocale")
private void saveLatestData() {
mCol = CollectionHelper.getInstance().getColSafe(AnkiDroidApp.getInstance());
CollectionHelper.getInstance().lockCollection();
mCol.getDb().getDatabase().beginTransaction();
try {
mCol.getDb().execute("delete from synclog");
} catch (Exception e) {
// mCol=CollectionHelper.getInstance().getColSafe(AnkiDroidApp.getInstance());
// mCol.getDb().execute("drop table synclog");
// mCol.getDb().execute("create table if not exists synclog (" + " id integer not null,"
// + " type integer not null," + " mod integer not null" + ")");
e.printStackTrace();
}
List<Deck> newDecks = mCol.getDecks().all();
StringBuilder values = new StringBuilder();
for (Deck item : newDecks) {
if (values.length() != 0) {
values.append(",");
}
values.append("(").append(item.getLong("id")).append(",").append(SYNC_LOG_TYPE_DECKS).append(",").append(item.getLong("mod")).append(")");
}
// db.execute(String.format("insert into synclog values %s",sbDeck.toString()));
List<Model> newModels = mCol.getModels().all();
// StringBuilder sbModel=new StringBuilder();
for (Model item : newModels) {
if (values.length() != 0) {
values.append(",");
}
values.append("(").append(item.getLong("id")).append(",").append(SYNC_LOG_TYPE_MODELS).append(",").append(item.getLong("mod")).append(")");
}
// db.execute(String.format("insert into synclog values %s",sbModel.toString()));
List<DeckConfig> newDConf = mCol.getDecks().allConf();
// StringBuilder sbDConf=new StringBuilder();
for (DeckConfig item : newDConf) {
if (values.length() != 0) {
values.append(",");
}
values.append("(").append(item.getLong("id")).append(",").append(SYNC_LOG_TYPE_DCONF).append(",").append(item.getLong("mod")).append(")");
}
String sql = String.format("insert into synclog values %s", values.toString());
Timber.i("sync to local synclog:%s", sql);
mCol.getDb().execute(sql);
// List<Card> newDConf = mCol.getDecks().allConf();
// for(DeckConfig item:newDConf){
// if(values.length()!=0)values.append(",");
// values.append("(").append(item.getLong("id")).append(",").append(SYNC_LOG_TYPE_DCONF).append(",").append(item.getLong("mod")).append(")");
// }
mCol.getDb().execute(String.format("insert into synclog select cards.id,%d,cards.mod from cards", SYNC_LOG_TYPE_CARD));
mCol.getDb().execute(String.format("insert into synclog select notes.id,%d,notes.mod from notes", SYNC_LOG_TYPE_NOTE));
mCol.getDb().execute(String.format("insert into synclog select revlog.id,%d,revlog.id from revlog", SYNC_LOG_TYPE_REVLOG));
mCol.getDb().getDatabase().setTransactionSuccessful();
mCol.getDb().getDatabase().endTransaction();
// mCol.fixIntegrity(new CollectionTask.ProgressCallback(null, AnkiDroidApp.getAppResources()));
CollectionHelper.getInstance().unlockCollection();
// db.execute(String.format("insert into synclog select revlog.id,%d,revlog.mod from revlog", SYNC_LOG_TYPE_REVLOG));
}
use of com.ichi2.libanki.Model in project AnkiChinaAndroid by ankichinateam.
the class AnkiChinaSyncer method getChangedColJson.
private <T extends JSONObject> JSONObject getChangedColJson(int type, List<T> newModels) {
List<T> changedModel = new ArrayList<>();
boolean deleted;
Cursor cur = null;
Map<Long, Long> oldModel = new HashMap<>();
JSONObject modelsJson = new JSONObject();
try {
cur = CollectionHelper.getInstance().getColSafe(AnkiDroidApp.getInstance()).getDb().getDatabase().query("SELECT id,mod FROM synclog WHERE type = " + type, null);
while (cur.moveToNext()) {
oldModel.put(cur.getLong(0), cur.getLong(1));
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
if (oldModel.isEmpty()) {
changedModel.addAll(newModels);
} else {
StringBuilder deletedModelSb = new StringBuilder();
for (Map.Entry<Long, Long> entry : oldModel.entrySet()) {
// System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
deleted = true;
for (T model : newModels) {
if (!changedModel.contains(model) && (oldModel.get(model.getLong("id")) == null || oldModel.get(model.getLong("id")) < model.getLong("mod"))) {
// 新增或修改过的deck
changedModel.add(model);
} else if (model.getLong("id") == entry.getKey()) {
// 未被删除的deck
deleted = false;
}
}
if (deleted) {
if (deletedModelSb.length() != 0) {
deletedModelSb.append(",");
}
deletedModelSb.append(entry.getKey());
}
}
if (deletedModelSb.length() > 0) {
modelsJson.put("delete", new JSONArray(deletedModelSb.toString().split(",")));
// modelsJson.put("delete", strArray2jsonArray(deletedModelSb.toString().split(",")));
}
}
JSONArray changedModelJson = new JSONArray();
for (T item : changedModel) {
changedModelJson.put(item);
}
modelsJson.put("replace", changedModelJson);
return modelsJson;
}
Aggregations