package info.opencards.learnstrats.leitner;
import info.opencards.Utils;
import info.opencards.core.Item;
import info.opencards.core.ItemCollection;
import info.opencards.core.ItemValuater;
import info.opencards.core.LearnMethod;
import info.opencards.ui.AbstractLearnDialog;
import info.opencards.ui.preferences.LeitnerSettings;
import java.util.ArrayList;
import java.util.List;
/**
* DOCUMENT ME!
*
* @author Holger Brandl
*/
public abstract class LeitnerLearning extends LearnMethod {
LeitnerSystem leitnerSystem;
private final List<Item> skipList = new ArrayList<Item>();
private Item lastItem;
LeitnerLearning(ItemValuater itemValuater) {
super(itemValuater);
}
public void run(ItemCollection parentCollection, List<Item> scheduledFileItems) {
leitnerSystem = (LeitnerSystem) parentCollection;
scoreNextItem();
}
protected void scoreNextItem() {
// do not show last card if possible
if (getNonFinalCards().size() <= 1)
valuater.score(leitnerSystem.getRandomCard(0, leitnerSystem.numBoxes() - 2, skipList));
else {
ArrayList<Item> tempSkipList = new ArrayList<Item>(skipList);
// add the last-item to the skipped ones to avoid that it is immediatly rescheduled if:
// a) the there are still other items left to be learned
if (lastItem != null && getNonFinalCards().size() - skipList.size() != 1)
tempSkipList.add(lastItem);
valuater.score(leitnerSystem.getRandomCard(0, leitnerSystem.numBoxes() - 2, tempSkipList));
}
}
/**
* Returns all flashcards which are not in the last box yet.
*/
private List<Item> getNonFinalCards() {
return leitnerSystem.getAllCards(0, leitnerSystem.numBoxes() - 2);
}
protected boolean isFinished() {
List<Item> queryCards = getNonFinalCards();
return queryCards.isEmpty() || skipList.containsAll(queryCards);
}
/**
* @return <code>true</code> if the item is still on schedule in the current session.
*/
boolean updateLeitnerSystem(LeitnerItem item, Integer feedback) {
lastItem = null;
if (feedback.equals(AbstractLearnDialog.INVALID_ITEM)) {
leitnerSystem.remove(item);
return false;
}
if (feedback.equals(LearnMethod.SKIP_UNTIL_TOMORROW) || feedback.equals(LearnMethod.SKIP_UNTIL_NEXT)) {
skipList.add(item);
return false;
}
lastItem = item;
item.getFlashCard().resetRndRevPolicy(); // to make items to change their reversing when moving from box to box
if (didKnew(feedback)) {
item.setState(LeitnerSystem.LEARNT);
leitnerSystem.moveUp(item);
} else {
item.setState(LeitnerSystem.FAILED);
// dependent on the properties move the card to the next lower or to the first leitner box
if (Utils.getPrefs().getBoolean(LeitnerSettings.DO_MOVE2_FIRST, LeitnerSettings.DO_MOVE2_FIRST_DEFAULT)) {
leitnerSystem.moveCard(item, 0);
} else {
leitnerSystem.moveDown(item);
}
}
return leitnerSystem.getBoxIndex(item) == (leitnerSystem.numBoxes() - 1);
}
boolean didKnew(Integer feedback) {
assert feedback == AbstractLearnDialog.SCORE_1 || feedback == AbstractLearnDialog.SCORE_5;
return feedback == AbstractLearnDialog.SCORE_5;
}
}