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); } }