use of com.ichi2.anki.CardBrowser.Column.REVIEWS in project Anki-Android by ankidroid.
the class SchedV2Test method test_review_limits.
@Test
public void test_review_limits() throws Exception {
Collection col = getColV2();
Deck parent = col.getDecks().get(addDeck("parent"));
Deck child = col.getDecks().get(addDeck("parent::child"));
DeckConfig pconf = col.getDecks().getConf(col.getDecks().confId("parentConf"));
DeckConfig cconf = col.getDecks().getConf(col.getDecks().confId("childConf"));
pconf.getJSONObject("rev").put("perDay", 5);
col.getDecks().updateConf(pconf);
col.getDecks().setConf(parent, pconf.getLong("id"));
cconf.getJSONObject("rev").put("perDay", 10);
col.getDecks().updateConf(cconf);
col.getDecks().setConf(child, cconf.getLong("id"));
Model m = col.getModels().current();
m.put("did", child.getLong("id"));
col.getModels().save(m, false);
// add some cards
for (int i = 0; i < 20; i++) {
Note note = col.newNote();
note.setItem("Front", "one");
note.setItem("Back", "two");
col.addNote(note);
// make them reviews
Card c = note.cards().get(0);
c.setQueue(QUEUE_TYPE_REV);
c.setType(CARD_TYPE_REV);
c.setDue(0);
c.flush();
}
// position 0 is default deck. Different from upstream
DeckDueTreeNode tree = col.getSched().deckDueTree().get(1);
// (('parent', 1514457677462, 5, 0, 0, (('child', 1514457677463, 5, 0, 0, ()),)))
assertEquals("parent", tree.getFullDeckName());
// paren, tree.review_count)t
assertEquals(5, tree.getRevCount());
assertEquals(10, tree.getChildren().get(0).getRevCount());
// .counts() should match
col.getDecks().select(child.getLong("id"));
col.reset();
assertEquals(new Counts(0, 0, 10), col.getSched().counts());
// answering a card in the child should decrement parent count
Card c = getCard();
col.getSched().answerCard(c, BUTTON_THREE);
assertEquals(new Counts(0, 0, 9), col.getSched().counts());
tree = col.getSched().deckDueTree().get(1);
assertEquals(4, tree.getRevCount());
assertEquals(9, tree.getChildren().get(0).getRevCount());
}
use of com.ichi2.anki.CardBrowser.Column.REVIEWS in project Anki-Android by ankidroid.
the class AdvancedStatistics method calculateDueAsMetaInfo.
/**
* Determine forecast statistics based on a computation or simulation of future reviews.
* Returns all information required by stats.java to plot the 'forecast' chart based on these statistics.
* The chart will display:
* - The forecasted number of reviews per review type (relearn, mature, young, learn) as bars
* - The forecasted number of cards in each state (new, young, mature) as lines
* @param metaInfo Object which will be filled with all information required by stats.java to plot the 'forecast' chart and returned by this method.
* @param type Type of 'forecast' chart for which to determine forecast statistics. Accepted values:
* Stats.TYPE_MONTH: Determine forecast statistics for next 30 days with 1-day chunks
* Stats.TYPE_YEAR: Determine forecast statistics for next year with 7-day chunks
* Stats.TYPE_LIFE: Determine forecast statistics for next 2 years with 30-day chunks
* @param context Contains The collection which contains the decks to be simulated.
* Also used for access to the database and access to the creation time of the collection.
* The creation time of the collection is needed since due times of cards are relative to the creation time of the collection.
* So we could pass mCol here.
* @param dids Deck id's
* @return @see #metaInfo
*/
public StatsMetaInfo calculateDueAsMetaInfo(StatsMetaInfo metaInfo, Stats.AxisType type, Context context, String dids) {
if (!AnkiDroidApp.getSharedPrefs(context).getBoolean("advanced_statistics_enabled", false)) {
return metaInfo;
}
// To indicate that we calculated the statistics so that Stats.java knows that it shouldn't display the standard Forecast chart.
mSettings = new Settings(context);
metaInfo.setStatsCalculated(true);
Collection col = CollectionHelper.getInstance().getCol(context);
int maxCards = 0;
double lastElement = 0;
int zeroIndex = 0;
int[] valueLabels = { R.string.statistics_relearn, R.string.statistics_mature, R.string.statistics_young, R.string.statistics_learn };
int[] colors = { R.attr.stats_relearn, R.attr.stats_mature, R.attr.stats_young, R.attr.stats_learn };
int[] axisTitles = { type.ordinal(), R.string.stats_cards, R.string.stats_cumulative_cards };
PlottableSimulationResult simuationResult = calculateDueAsPlottableSimulationResult(type, col, dids);
ArrayList<int[]> dues = simuationResult.getNReviews();
double[][] seriesList = new double[REVIEW_TYPE_COUNT_PLUS_1][dues.size()];
for (int t = 0; t < dues.size(); t++) {
int[] data = dues.get(t);
int nReviews = data[REVIEW_TYPE_LEARN_PLUS_1] + data[REVIEW_TYPE_YOUNG_PLUS_1] + data[REVIEW_TYPE_MATURE_PLUS_1] + data[REVIEW_TYPE_RELEARN_PLUS_1];
if (nReviews > maxCards)
// Y-Axis: Max. value
maxCards = nReviews;
// In the bar-chart, the bars will be stacked on top of each other.
// For the i^{th} bar counting from the bottom we therefore have to
// provide the sum of the heights of the i^{th} bar and all bars below it.
// X-Axis: Day / Week / Month
seriesList[TIME][t] = data[TIME];
seriesList[REVIEW_TYPE_LEARN_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1] + data[REVIEW_TYPE_YOUNG_PLUS_1] + data[REVIEW_TYPE_MATURE_PLUS_1] + // Y-Axis: # Cards
data[REVIEW_TYPE_RELEARN_PLUS_1];
seriesList[REVIEW_TYPE_YOUNG_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1] + data[REVIEW_TYPE_YOUNG_PLUS_1] + // Y-Axis: # Mature cards
data[REVIEW_TYPE_MATURE_PLUS_1];
seriesList[REVIEW_TYPE_MATURE_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1] + // Y-Axis: # Young
data[REVIEW_TYPE_YOUNG_PLUS_1];
// Y-Axis: # Learn
seriesList[REVIEW_TYPE_RELEARN_PLUS_1][t] = data[REVIEW_TYPE_LEARN_PLUS_1];
if (data[TIME] > lastElement)
// X-Axis: Max. value (only for TYPE_LIFE)
lastElement = data[TIME];
if (data[TIME] == 0) {
// Because we retrieve dues in the past and we should not cumulate them
zeroIndex = t;
}
}
// # X values
int maxElements = dues.size() - 1;
switch(type) {
case TYPE_MONTH:
// X-Axis: Max. value
lastElement = 31;
break;
case TYPE_YEAR:
// X-Axis: Max. value
lastElement = 52;
break;
default:
}
// X-Axis: Min. value
double firstElement = 0;
// Day starting at zeroIndex, Cumulative # cards
double[][] cumulative = simuationResult.getNInState();
double count = // Y-Axis: Max. cumulative value
cumulative[CARD_TYPE_NEW_PLUS_1][cumulative[CARD_TYPE_NEW_PLUS_1].length - 1] + cumulative[CARD_TYPE_YOUNG_PLUS_1][cumulative[CARD_TYPE_YOUNG_PLUS_1].length - 1] + cumulative[CARD_TYPE_MATURE_PLUS_1][cumulative[CARD_TYPE_MATURE_PLUS_1].length - 1];
// some adjustments to not crash the chartbuilding with empty data
if (maxElements == 0) {
maxElements = 10;
}
if (count == 0) {
count = 10;
}
if (firstElement == lastElement) {
firstElement = 0;
lastElement = 6;
}
if (maxCards == 0)
maxCards = 10;
metaInfo.setmDynamicAxis(true);
metaInfo.setmHasColoredCumulative(true);
metaInfo.setmType(type);
metaInfo.setmTitle(R.string.stats_forecast);
metaInfo.setmBackwards(true);
metaInfo.setmValueLabels(valueLabels);
metaInfo.setmColors(colors);
metaInfo.setmAxisTitles(axisTitles);
metaInfo.setmMaxCards(maxCards);
metaInfo.setmMaxElements(maxElements);
metaInfo.setmFirstElement(firstElement);
metaInfo.setmLastElement(lastElement);
metaInfo.setmZeroIndex(zeroIndex);
metaInfo.setmCumulative(cumulative);
metaInfo.setmMcount(count);
metaInfo.setmSeriesList(seriesList);
metaInfo.setDataAvailable(!dues.isEmpty());
return metaInfo;
}
use of com.ichi2.anki.CardBrowser.Column.REVIEWS in project Anki-Android by ankidroid.
the class OverviewStatsBuilderTest method testInfoHtmlStringMonth.
@Test
@Config(qualifiers = "en")
public void testInfoHtmlStringMonth() {
OverviewStatsBuilder statsTester = new OverviewStatsBuilder(new WebView(getTargetContext()), getCol(), 42L, Stats.AxisType.TYPE_MONTH);
String HTML = statsTester.createInfoHtmlString();
assertEquals(HTML, "<center><style>\n" + "h1, h3 { margin-bottom: 0; margin-top: 1em; text-transform: capitalize; }\n" + ".pielabel { text-align:center; padding:0px; color:white; }\n" + "body {color:#FFFFFF;}\n" + "</style><h1>Today</h1>Studied <b>0 cards</b> in <b>0 minutes</b> today<br>Again count: <b>0</b><br>Learn: <b>0</b>, review: <b>0</b>, relearn: <b>0</b>, filtered: <b>0</b><br>No mature cards were studied today<h1>1 month</h1><h3>FORECAST</h3>Total: <b>0</b> reviews<br>Average: <b>0.0</b> reviews/day<br>Due tomorrow: <b>0</b><br><h3>REVIEW COUNT</h3>Days studied: <b>0%</b> (0 of 30)<br>Total: <b>0</b> reviews<br>Average for days studied: <b>0.0</b> reviews/day<br>If you studied every day: <b>0.0</b> reviews/day<br><h3>REVIEW TIME</h3>Days studied: <b>0%</b> (0 of 30)<br>Total: <b>0</b> minutes<br>Average for days studied: <b>0.0</b> minutes/day<br>If you studied every day: <b>0.0</b> minutes/day<br>Average answer time: <b>0.0s</b> (<b>0.00</b> cards/minute)<br><h3>ADDED</h3>Total: <b>0</b> cards<br>Average: <b>0.0</b> cards/day<br><h3>INTERVALS</h3>Average interval: <b>0.0</b> hours<br>Longest interval: <b>0.0</b> hours<h3>ANSWER BUTTONS</h3>Learning: <b>0.00%</b> correct (0 of 0)<br>Young: <b>0.00%</b> correct (0 of 0)<br>Mature: <b>0.00%</b> correct (0 of 0)<h3>CARD TYPES</h3>Total cards: <b>0</b><br>Total notes: <b>0</b><br>Lowest ease: <b>0%</b><br>Average ease: <b>0%</b><br>Highest ease: <b>0%</b></center>");
}
use of com.ichi2.anki.CardBrowser.Column.REVIEWS in project AnkiChinaAndroid by ankichinateam.
the class SchedTest method test_cram_resched.
@Test
public void test_cram_resched() throws Exception {
// add card
Collection col = getColV1();
Note note = col.newNote();
note.setItem("Front", "one");
col.addNote(note);
// cram deck
long did = col.getDecks().newDyn("Cram");
Deck cram = col.getDecks().get(did);
cram.put("resched", false);
col.getDecks().save(cram);
col.getSched().rebuildDyn(did);
col.reset();
// graduate should return it to new
Card c = col.getSched().getCard();
assertEquals(60, col.getSched().nextIvl(c, 1));
assertEquals(600, col.getSched().nextIvl(c, 2));
assertEquals(0, col.getSched().nextIvl(c, 3));
assertEquals("(end)", col.getSched().nextIvlStr(getTargetContext(), c, 3));
col.getSched().answerCard(c, 3);
assertEquals(CARD_TYPE_NEW, c.getType());
assertEquals(QUEUE_TYPE_NEW, c.getQueue());
// undue reviews should also be unaffected
c.setIvl(100);
c.setQueue(CARD_TYPE_REV);
c.setType(QUEUE_TYPE_REV);
c.setDue(col.getSched().getToday() + 25);
c.setFactor(STARTING_FACTOR);
c.flush();
Card cardcopy = c.clone();
col.getSched().rebuildDyn(did);
col.reset();
c = col.getSched().getCard();
assertEquals(600, col.getSched().nextIvl(c, 1));
assertEquals(0, col.getSched().nextIvl(c, 2));
assertEquals(0, col.getSched().nextIvl(c, 3));
col.getSched().answerCard(c, 2);
assertEquals(100, c.getIvl());
assertEquals(col.getSched().getToday() + 25, c.getDue());
// check failure too
c = cardcopy;
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = col.getSched().getCard();
col.getSched().answerCard(c, 1);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(col.getSched().getToday() + 25, c.getDue());
// fail+grad early
c = cardcopy;
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = col.getSched().getCard();
col.getSched().answerCard(c, 1);
col.getSched().answerCard(c, 3);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(col.getSched().getToday() + 25, c.getDue());
// due cards - pass
c = cardcopy;
c.setDue(-25);
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = col.getSched().getCard();
col.getSched().answerCard(c, 3);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(-25, c.getDue());
// fail
c = cardcopy;
c.setDue(-25);
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = col.getSched().getCard();
col.getSched().answerCard(c, 1);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(-25, c.getDue());
// fail with normal grad
c = cardcopy;
c.setDue(-25);
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = col.getSched().getCard();
col.getSched().answerCard(c, 1);
col.getSched().answerCard(c, 3);
c.load();
assertEquals(100, c.getIvl());
assertEquals(-25, c.getDue());
// lapsed card pulled into cram
// col.getSched()._cardConf(c)['lapse']['mult']=0.5
// col.getSched().answerCard(c, 1)
// col.getSched().rebuildDyn(did)
// col.reset()
// c = col.getSched().getCard()
// col.getSched().answerCard(c, 2)
// print c.__dict__
}
use of com.ichi2.anki.CardBrowser.Column.REVIEWS in project Anki-Android by ankidroid.
the class SchedTest method test_cram_resched.
@Test
public void test_cram_resched() throws Exception {
// add card
Collection col = getColV1();
Note note = col.newNote();
note.setItem("Front", "one");
col.addNote(note);
// cram deck
long did = addDynamicDeck("Cram");
Deck cram = col.getDecks().get(did);
cram.put("resched", false);
col.getDecks().save(cram);
col.getSched().rebuildDyn(did);
col.reset();
// graduate should return it to new
Card c = getCard();
assertEquals(60, col.getSched().nextIvl(c, BUTTON_ONE));
assertEquals(600, col.getSched().nextIvl(c, BUTTON_TWO));
assertEquals(0, col.getSched().nextIvl(c, BUTTON_THREE));
assertEquals("(end)", col.getSched().nextIvlStr(getTargetContext(), c, BUTTON_THREE));
col.getSched().answerCard(c, BUTTON_THREE);
assertEquals(CARD_TYPE_NEW, c.getType());
assertEquals(QUEUE_TYPE_NEW, c.getQueue());
// undue reviews should also be unaffected
c.setIvl(100);
c.setQueue(QUEUE_TYPE_REV);
c.setType(CARD_TYPE_REV);
c.setDue(col.getSched().getToday() + 25);
c.setFactor(STARTING_FACTOR);
c.flush();
Card cardcopy = c.clone();
col.getSched().rebuildDyn(did);
col.reset();
c = getCard();
assertEquals(600, col.getSched().nextIvl(c, BUTTON_ONE));
assertEquals(0, col.getSched().nextIvl(c, BUTTON_TWO));
assertEquals(0, col.getSched().nextIvl(c, BUTTON_THREE));
col.getSched().answerCard(c, BUTTON_TWO);
assertEquals(100, c.getIvl());
assertEquals(col.getSched().getToday() + 25, c.getDue());
// check failure too
c = cardcopy;
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = getCard();
col.getSched().answerCard(c, BUTTON_ONE);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(col.getSched().getToday() + 25, c.getDue());
// fail+grad early
c = cardcopy;
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = getCard();
col.getSched().answerCard(c, BUTTON_ONE);
col.getSched().answerCard(c, BUTTON_THREE);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(col.getSched().getToday() + 25, c.getDue());
// due cards - pass
c = cardcopy;
c.setDue(-25);
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = getCard();
col.getSched().answerCard(c, BUTTON_THREE);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(-25, c.getDue());
// fail
c = cardcopy;
c.setDue(-25);
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = getCard();
col.getSched().answerCard(c, BUTTON_ONE);
col.getSched().emptyDyn(did);
c.load();
assertEquals(100, c.getIvl());
assertEquals(-25, c.getDue());
// fail with normal grad
c = cardcopy;
c.setDue(-25);
c.flush();
col.getSched().rebuildDyn(did);
col.reset();
c = getCard();
col.getSched().answerCard(c, BUTTON_ONE);
col.getSched().answerCard(c, BUTTON_THREE);
c.load();
assertEquals(100, c.getIvl());
assertEquals(-25, c.getDue());
// lapsed card pulled into cram
// col.getSched()._cardConf(c)['lapse']['mult']=0.5
// col.getSched().answerCard(c, 1)
// col.getSched().rebuildDyn(did)
// col.reset()
// c = getCard()
// col.getSched().answerCard(c, 2)
// print c.__dict__
}
Aggregations