package info.opencards.core;
import info.opencards.Utils;
import info.opencards.ui.AbstractLearnDialog;
import info.opencards.ui.preferences.GeneralSettings;
import java.util.ArrayList;
import java.util.List;
/**
* An abstract learning method.
*
* @author Holger Brandl
*/
public abstract class LearnMethod implements ScoringListener {
// here we define constants for the three possible skipping behaviors, which can be configured in the OC-Settings
public static final int SKIP_BUT_KEEP = 778800;
public static final int SKIP_UNTIL_NEXT = 778801;
public static final int SKIP_UNTIL_TOMORROW = 778802;
protected final ItemValuater valuater;
protected final List<LearnMethodListener> procListeners = new ArrayList<LearnMethodListener>();
protected LearnMethod(ItemValuater itemValuater) {
valuater = itemValuater;
valuater.addScoringListener(this);
}
/**
* @param parentCollection The collection of items to which the set of scheduled items belongs to.
* @param scheduledFileItems A set of items scheduled for today.
* @return <code>true</code> if the card session has finshed without being interrupted.
*/
public abstract void run(ItemCollection parentCollection, List<Item> scheduledFileItems);
protected abstract void scoreNextItem();
/**
* Processes the feedback generated by the user for a given <code>item</code> . Beside the possible
* learning-feedback-values which are defined in <code>AbstractLearnDialog</code> there are some special
* signal-feedback which needs to be processed: <ul> <li>SKIP_UNTIL_NEXT which should defer the <code>item</code> to
* the next session <li>SKIP_UNTIL_TOMORROW which should defer the <code>item</code> until tomorrow (if possible)
* <li>ITEM_DELETED which indicates that the <code>item</code> is no longer contained in the item-collection </ul>
*
* @param item The item which was scored
* @param feedback The feedback generated by the user
* @see info.opencards.ui.AbstractLearnDialog
*/
protected abstract boolean processItemFeedBack(Item item, Integer feedback);
public abstract void fireStatusInfo();
public void itemScored(Item item, Integer feedback) {
Utils.log("item '" + item.toString() + "'scored :" + feedback);
if (feedback.equals(AbstractLearnDialog.SESSION_INTERRUPTED)) {
for (LearnMethodListener procListener : procListeners) {
procListener.cardFileProcessingFinished(true);
}
valuater.removeScoringListener(this);
return;
}
// map (if "skip" was chosen by the user) the skip-feedback to the chosen skip-behavior
if (feedback.equals(AbstractLearnDialog.SKIP_ITEM)) {
feedback = Utils.getPrefs().getInt(GeneralSettings.SKIPPING_BEHAVIOR, GeneralSettings.SKIPPING_BEHAVIOR_DEFAULT);
}
if (!feedback.equals(SKIP_BUT_KEEP)) {
boolean isStillOnSchedule = processItemFeedBack(item, feedback);
for (LearnMethodListener procListener : procListeners)
procListener.itemChanged(item, isStillOnSchedule, feedback);
fireStatusInfo();
}
if (isFinished()) {
for (LearnMethodListener procListener : procListeners) {
procListener.cardFileProcessingFinished(false);
}
valuater.removeScoringListener(this);
} else {
scoreNextItem();
}
}
protected abstract boolean isFinished();
/**
* Adds a new listener.
*/
public void addLearnProcessListener(LearnMethodListener l) {
if (l == null || procListeners.contains(l))
return;
procListeners.add(l);
}
/**
* Removes a listener.
*/
public void removeLearnProcessListener(LearnMethodListener l) {
if (l == null)
return;
procListeners.remove(l);
}
}