package info.opencards.ui.ltmstats; import info.opencards.Utils; import info.opencards.core.CardFile; import info.opencards.core.Item; import info.opencards.learnstrats.ltm.LTMCollection; import info.opencards.learnstrats.ltm.ScheduleUtils; import org.jfree.chart.ChartFactory; import org.jfree.chart.ChartPanel; import org.jfree.chart.JFreeChart; import org.jfree.chart.axis.NumberAxis; import org.jfree.chart.axis.TickUnits; import org.jfree.chart.axis.ValueAxis; import org.jfree.chart.labels.StandardCategoryToolTipGenerator; import org.jfree.chart.plot.CategoryPlot; import org.jfree.chart.plot.PlotOrientation; import org.jfree.chart.renderer.category.StackedBarRenderer; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.ui.GradientPaintTransformType; import org.jfree.ui.StandardGradientPaintTransformer; import javax.swing.*; import java.awt.*; import java.util.*; import java.util.List; /** * DOCUMENT ME! * * @author Holger Brandl */ class SchedulePlanningPanel extends JPanel { private final DefaultCategoryDataset dataset; private final ValueAxis valueAxis; private static final int NUM_HIST_BINS = 8; private Collection<CardFile> currentFiles; public SchedulePlanningPanel() { setLayout(new BorderLayout()); // setup the stacked bar chart dataset = new DefaultCategoryDataset(); final JFreeChart chart = ChartFactory.createStackedBarChart( null, // chart title Utils.getRB().getString("CardTableModel.stats.weekSchedule"), // domain axis label // "# cards", // range axis label null, // range axis label dataset, // data PlotOrientation.VERTICAL, // the plot orientation false, // legend true, // tooltips false // urls ); StackedBarRenderer renderer = new StackedBarRenderer(); renderer.setGradientPaintTransformer(new StandardGradientPaintTransformer(GradientPaintTransformType.HORIZONTAL)); //green renderer.setItemMargin(0.0); Paint greenPaint = new GradientPaint(0.0f, 0.0f, new Color(0x22, 0xFF, 0x22), 0.0f, 0.0f, new Color(0x88, 0xFF, 0x88)); renderer.setSeriesPaint(1, greenPaint); renderer.setSeriesToolTipGenerator(1, new StandardCategoryToolTipGenerator()); //blue Paint bluePaint = new GradientPaint(0.0f, 0.0f, new Color(0x22, 0x22, 0xFF), 0.0f, 0.0f, new Color(0x88, 0x88, 0xFF)); renderer.setSeriesPaint(0, bluePaint); renderer.setSeriesToolTipGenerator(0, new StandardCategoryToolTipGenerator()); // Paint p2 = new GradientPaint(0.0f, 0.0f, new Color(0xFF, 0x22, 0x22), 0.0f, 0.0f, new Color(0xFF, 0x88, 0x88)); // renderer.setSeriesPaint(1, p2); // renderer.setSeriesToolTipGenerator(1, new StandardCategoryToolTipGenerator()); // // Paint p3 = new GradientPaint(0.0f, 0.0f, new Color(0x22, 0xFF, 0x22), 0.0f, 0.0f, new Color(0x88, 0xFF, 0x88)); // renderer.setSeriesPaint(2, p3); // renderer.setSeriesToolTipGenerator(2, new StandardCategoryToolTipGenerator()); CategoryPlot plot = (CategoryPlot) chart.getPlot(); plot.setRenderer(renderer); valueAxis = plot.getRangeAxis(); TickUnits units = (TickUnits) NumberAxis.createIntegerTickUnits(); valueAxis.setStandardTickUnits(units); ChartPanel chartPanel = new ChartPanel(chart); chartPanel.setPopupMenu(null); chartPanel.setDomainZoomable(false); chartPanel.setRangeZoomable(false); add(chartPanel, BorderLayout.CENTER); rebuildPanel(new HashSet<CardFile>()); } void rebuildPanel(Collection<CardFile> currentFiles) { if (currentFiles != null) this.currentFiles = currentFiles; dataset.clear(); if (this.currentFiles == null) return; computeScheduleHist(this.currentFiles); // set2EDistribution(currentFiles); } private boolean computeScheduleHist(Collection<CardFile> currentFiles) { Map<Integer, List<Item>> schedule = new HashMap<Integer, List<Item>>(); for (int i = 0; i < NUM_HIST_BINS; i++) { for (CardFile currentFile : currentFiles) { LTMCollection ltmCollection = currentFile.getFlashCards().getLTMItems(); if (!schedule.containsKey(i)) { schedule.put(i, new ArrayList<Item>()); } if (i == 0) { schedule.get(i).addAll(ltmCollection.getScheduledItems()); } else { schedule.get(i).addAll(ltmCollection.predictItemsForDate(ScheduleUtils.getIncDate(ScheduleUtils.getToday(), i), false)); } } } // now set up the histogram int[] scheduleHist = new int[NUM_HIST_BINS]; int[] newHist = new int[NUM_HIST_BINS]; int numRemainingNewItems = -Integer.MAX_VALUE; // just to make sure that is never used int maxNewPerDay = ScheduleUtils.getMaxNewCardsPerDay(); for (Integer scheduleDate : schedule.keySet()) { int numScheduledCards; List<Item> curScheduleSet = schedule.get(scheduleDate); List<Item> newItems = ScheduleUtils.getNewItems(curScheduleSet); // incorporate the knowledge about new cards when computing the schedule-histogram int curDatNewRation = 0; if (scheduleDate == 0) { int maxNewCardsToday = ScheduleUtils.getMaxCardToBeLearntToday(); curDatNewRation = Math.min(maxNewCardsToday, newItems.size()); numScheduledCards = (curScheduleSet.size() - newItems.size()); numRemainingNewItems = newItems.size() - Math.min(maxNewCardsToday, newItems.size()); } else { numRemainingNewItems += newItems.size(); numScheduledCards = curScheduleSet.size() - newItems.size(); if (numRemainingNewItems > 0) { int dailyNewRation = Math.min(maxNewPerDay, numRemainingNewItems); curDatNewRation = dailyNewRation; // numScheduledCards += dailyNewRation; numRemainingNewItems -= dailyNewRation; } } // set the value to the histogram if (scheduleDate < NUM_HIST_BINS) { scheduleHist[scheduleDate] = numScheduledCards; newHist[scheduleDate] = curDatNewRation; } // scheduleHist[scheduleDate >= NUM_HIST_BINS - 1 ? NUM_HIST_BINS - 1 : scheduleDate] = numScheduledCards; } List<Integer> eBinSize = new ArrayList<Integer>(); dataset.addValue((double) newHist[0], "# new flashcards", Utils.getRB().getString("CardTableModel.when.today")); dataset.addValue((double) scheduleHist[0], "# flashcards", Utils.getRB().getString("CardTableModel.when.today")); eBinSize.add(scheduleHist[0] + newHist[0]); dataset.addValue((double) newHist[1], "# new flashcards", Utils.getRB().getString("CardTableModel.when.tomorrow")); dataset.addValue((double) scheduleHist[1], "# flashcards", Utils.getRB().getString("CardTableModel.when.tomorrow")); eBinSize.add(scheduleHist[1] + newHist[1]); for (int i = 2; i < scheduleHist.length; i++) { String days = Utils.getRB().getString("CardTableModel.when.days"); // dataset.addValue((double) scheduleHist[i], "Scheduled", (i == scheduleHist.length - 1 ? (NUM_HIST_BINS-1) + "+" + " " + days : i + " " + days)); dataset.addValue((double) newHist[i], "# new flashcards", i + " " + days); dataset.addValue((double) scheduleHist[i], "# flashcards", i + " " + days); eBinSize.add(scheduleHist[i] + newHist[i]); } valueAxis.setLowerBound(0); valueAxis.setUpperBound(1.1 * Math.max(Collections.max(eBinSize), 1)); valueAxis.setAutoRange(false); return false; } public void selectionChanged(List<CardFile> selectedFiles) { rebuildPanel(selectedFiles); } }