use of com.ichi2.libanki.utils.Time in project AnkiChinaAndroid by ankichinateam.
the class ReminderService method getDeckOptionDue.
// getDeckOptionDue information, will recur one time to workaround collection close if recur is true
@Nullable
private List<DeckDueTreeNode> getDeckOptionDue(Collection col, long dConfId, boolean recur) {
// are working
if (col.getDb() == null || col.getDecks().getConf(dConfId) == null) {
Timber.d("Deck option %s became unavailable while ReminderService was working. Ignoring", dConfId);
return null;
}
List<DeckDueTreeNode> decks = new ArrayList<>();
try {
// This loop over top level deck only. No notification will ever occur for subdecks.
for (DeckDueTreeNode node : col.getSched().deckDueTree()) {
JSONObject deck = col.getDecks().get(node.getDid(), false);
// Dynamic deck has no "conf", so are not added here.
if (deck != null && deck.optLong("conf") == dConfId) {
decks.add(node);
}
}
return decks;
} catch (Exception e) {
if (recur) {
Timber.i(e, "getDeckOptionDue exception - likely database re-initialization from auto-sync. Will re-try after sleep.");
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
Timber.i(ex, "Thread interrupted while waiting to retry. Likely unimportant.");
Thread.currentThread().interrupt();
}
return getDeckOptionDue(col, dConfId, false);
} else {
Timber.w(e, "Database unavailable while working. No re-tries left.");
}
}
return null;
}
use of com.ichi2.libanki.utils.Time in project AnkiChinaAndroid by ankichinateam.
the class ReviewerCustomFonts method getCustomFontsMap.
/**
* Returns a map from custom fonts names to the corresponding {@link AnkiFont} object.
* <p>
* The list of constructed lazily the first time is needed.
*/
private static Map<String, AnkiFont> getCustomFontsMap(Context context) {
List<AnkiFont> fonts = Utils.getCustomFonts(context);
Map<String, AnkiFont> customFontsMap = new HashMap<>();
for (AnkiFont f : fonts) {
customFontsMap.put(f.getName(), f);
}
return customFontsMap;
}
use of com.ichi2.libanki.utils.Time in project AnkiChinaAndroid by ankichinateam.
the class ReviewerTest method testMultipleCards.
@Test
public synchronized void testMultipleCards() throws ConfirmModSchemaException, InterruptedException {
addNoteWithThreeCards();
Collection col = getCol();
JSONObject nw = col.getDecks().confForDid(1).getJSONObject("new");
MockTime time = getCollectionTime();
nw.put("delays", new JSONArray(new int[] { 1, 10, 60, 120 }));
waitForAsyncTasksToComplete();
Reviewer reviewer = startReviewer();
waitForAsyncTasksToComplete();
assertCounts(reviewer, 3, 0, 0);
// card 1 is shown
answerCardOrdinalAsGood(reviewer, 1);
// card get scheduler in [10, 12.5] minutes
time.addM(3);
// We wait 3 minutes to ensure card 2 is scheduled after card 1
// card 2 is shown
answerCardOrdinalAsGood(reviewer, 2);
// Same as above
time.addM(3);
// card 3 is shown
answerCardOrdinalAsGood(reviewer, 3);
undo(reviewer);
assertCurrentOrdIs(reviewer, 3);
// card 3 is shown
answerCardOrdinalAsGood(reviewer, 3);
// Anki Desktop shows "1"
assertCurrentOrdIsNot(reviewer, 3);
}
use of com.ichi2.libanki.utils.Time in project AnkiChinaAndroid by ankichinateam.
the class ACRATest method testCrashReportLimit.
@Test
public void testCrashReportLimit() throws Exception {
// To test ACRA switch on reporting, plant a production tree, and trigger a report
Timber.plant(new AnkiDroidApp.ProductionCrashReportingTree());
// set up as if the user had prefs saved to full auto
setReportConfig(FEEDBACK_REPORT_ALWAYS);
// If the user is set to always, then it's production, with interaction mode toast
// will be useful with ACRA 5.2.0
setAcraConfig("Production");
// The same class/method combo is only sent once, so we face a new method each time (should test that system later)
Exception crash = new Exception("testCrashReportSend at " + System.currentTimeMillis());
StackTraceElement[] trace = new StackTraceElement[] { new StackTraceElement("Class", "Method" + (int) System.currentTimeMillis(), "File", (int) System.currentTimeMillis()) };
crash.setStackTrace(trace);
// one send should work
CrashReportData crashData = new CrashReportDataFactory(InstrumentationRegistry.getInstrumentation().getTargetContext(), AnkiDroidApp.getInstance().getAcraCoreConfigBuilder().build()).createCrashData(new ReportBuilder().exception(crash));
assertTrue(new LimitingReportAdministrator().shouldSendReport(InstrumentationRegistry.getInstrumentation().getTargetContext(), AnkiDroidApp.getInstance().getAcraCoreConfigBuilder().build(), crashData));
// A second send should not work
assertFalse(new LimitingReportAdministrator().shouldSendReport(InstrumentationRegistry.getInstrumentation().getTargetContext(), AnkiDroidApp.getInstance().getAcraCoreConfigBuilder().build(), crashData));
// Now let's clear data
AnkiDroidApp.deleteACRALimiterData(InstrumentationRegistry.getInstrumentation().getTargetContext());
// A third send should work again
assertTrue(new LimitingReportAdministrator().shouldSendReport(InstrumentationRegistry.getInstrumentation().getTargetContext(), AnkiDroidApp.getInstance().getAcraCoreConfigBuilder().build(), crashData));
}
use of com.ichi2.libanki.utils.Time in project AnkiChinaAndroid by ankichinateam.
the class Sched method _fillLrn.
// sub-day learning
@Override
protected boolean _fillLrn() {
if (mLrnCount == 0) {
return false;
}
if (!mLrnQueue.isEmpty()) {
return true;
}
Cursor cur = null;
mLrnQueue.clear();
SupportSQLiteDatabase db = mCol.getDb().getDatabase();
try {
/* Difference with upstream:
* Current card can't come in the queue.
*
* In standard usage, a card is not requested before the previous card is marked as reviewed. However, if we
* decide to query a second card sooner, we don't want to get the same card a second time. This simulate
* _getLrnCard which did remove the card from the queue. _sortIntoLrn will add the card back to the queue if
* required when the card is reviewed.
*/
cur = db.query("SELECT due, id FROM cards WHERE did IN " + _deckLimit() + " AND queue = " + Consts.QUEUE_TYPE_LRN + " AND due < ? AND id != ? LIMIT ?", new Object[] { mDayCutoff, currentCardId(), mReportLimit });
while (cur.moveToNext()) {
mLrnQueue.add(cur.getLong(0), cur.getLong(1));
}
// as it arrives sorted by did first, we need to sort it
mLrnQueue.sort();
return !mLrnQueue.isEmpty();
} finally {
if (cur != null && !cur.isClosed()) {
cur.close();
}
}
}
Aggregations