use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class Models method _reqForTemplate.
// 'String f' is unused upstream as well
@SuppressWarnings("PMD.UnusedLocalVariable")
private Object[] _reqForTemplate(Model m, ArrayList<String> flds, JSONObject t) {
int nbFields = flds.size();
String[] a = new String[nbFields];
String[] b = new String[nbFields];
Arrays.fill(a, "ankiflag");
Arrays.fill(b, "");
int ord = t.getInt("ord");
String full = mCol._renderQA(1L, m, 1L, ord, "", a, 0).get("q");
String empty = mCol._renderQA(1L, m, 1L, ord, "", b, 0).get("q");
// if full and empty are the same, the template is invalid and there is no way to satisfy it
if (full.equals(empty)) {
return new Object[] { "none", new JSONArray(), new JSONArray() };
}
String type = "all";
JSONArray req = new JSONArray();
for (int i = 0; i < flds.size(); i++) {
a[i] = "";
// if no field content appeared, field is required
if (!mCol._renderQA(1L, m, 1L, ord, "", a, 0).get("q").contains("ankiflag")) {
req.put(i);
}
a[i] = "ankiflag";
}
if (req.length() > 0) {
return new Object[] { type, req };
}
// if there are no required fields, switch to any mode
type = "any";
req = new JSONArray();
for (int i = 0; i < flds.size(); i++) {
b[i] = "1";
// if not the same as empty, this field can make the card non-blank
if (!mCol._renderQA(1L, m, 1L, ord, "", b, 0).get("q").equals(empty)) {
req.put(i);
}
b[i] = "";
}
return new Object[] { type, req };
}
use of com.ichi2.anki.CardBrowser.Column.CARD 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.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class SchedV2 method _deckNewLimitSingle.
/**
* Maximal number of new card still to see today in deck g. It's computed as:
* the number of new card to see by day according to the deck optinos
* minus the number of new cards seen today in deck d or a descendant
* plus the number of extra new cards to see today in deck d, a parent or a descendant.
*
* Limits of its ancestors are not applied, current card is not treated differently.
*/
public int _deckNewLimitSingle(@NonNull Deck g) {
if (g.getInt("dyn") != 0) {
return mDynReportLimit;
}
long did = g.getLong("id");
@NonNull DeckConfig c = mCol.getDecks().confForDid(did);
int lim = Math.max(0, c.getJSONObject("new").getInt("perDay") - g.getJSONArray("newToday").getInt(1));
// So currentCard does not have to be taken into consideration in this method
if (currentCardIsInQueueWithDeck(Consts.QUEUE_TYPE_NEW, did)) {
lim--;
}
return lim;
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class SchedV2 method _checkLeech.
/**
* Leeches ****************************************************************** *****************************
*/
/**
* Leech handler. True if card was a leech.
* Overridden: in V1, due and did are changed
*/
protected boolean _checkLeech(@NonNull Card card, @NonNull JSONObject conf) {
int lf;
lf = conf.getInt("leechFails");
if (lf == 0) {
return false;
}
// if over threshold or every half threshold reps after that
if (card.getLapses() >= lf && (card.getLapses() - lf) % Math.max(lf / 2, 1) == 0) {
// add a leech tag
Note n = card.note();
n.addTag("leech");
n.flush();
// handle
if (conf.getInt("leechAction") == Consts.LEECH_SUSPEND) {
card.setQueue(Consts.QUEUE_TYPE_SUSPENDED);
}
// notify UI
if (mContextReference != null) {
Activity context = mContextReference.get();
leech(card, context);
}
return true;
}
return false;
}
use of com.ichi2.anki.CardBrowser.Column.CARD in project AnkiChinaAndroid by ankichinateam.
the class SchedV2 method _burySiblings.
/**
* Sibling spacing
* ********************
*/
protected void _burySiblings(@NonNull Card card) {
ArrayList<Long> toBury = new ArrayList<>();
JSONObject nconf = _newConf(card);
boolean buryNew = nconf.optBoolean("bury", true);
JSONObject rconf = _revConf(card);
boolean buryRev = rconf.optBoolean("bury", true);
// loop through and remove from queues
Cursor cur = null;
try {
cur = mCol.getDb().query("select id, queue from cards where nid=? and id!=? " + "and (queue=" + Consts.QUEUE_TYPE_NEW + " or (queue=" + Consts.QUEUE_TYPE_REV + " and due<=?))", card.getNid(), card.getId(), mToday);
while (cur.moveToNext()) {
long cid = cur.getLong(0);
int queue = cur.getInt(1);
SimpleCardQueue queue_object;
if (queue == Consts.QUEUE_TYPE_REV) {
queue_object = mRevQueue;
if (buryRev) {
toBury.add(cid);
}
} else {
queue_object = mNewQueue;
if (buryNew) {
toBury.add(cid);
}
}
// even if burying disabled, we still discard to give
// same-day spacing
queue_object.remove(cid);
}
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
// then bury
if (!toBury.isEmpty()) {
buryCards(Utils.collection2Array(toBury), false);
}
}
Aggregations