Changeset ce08ae3


Ignore:
Timestamp:
May 18, 2010, 12:55:42 PM (10 years ago)
Author:
Michael Seifert <mseifert@…>
Branches:
master
Children:
5a3c8d9
Parents:
f29aea6
Message:

Fixed a bug that caused APM curves to appear twice;

Enhanced appearance of APM charts;

APMChart supports displaying multiple players

Location:
src/main/java/de/erichseifert/warp/gui
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • src/main/java/de/erichseifert/warp/gui/APMChart.java

    rf29aea6 rce08ae3  
    2828import javax.swing.JPanel;
    2929
     30import de.erichseifert.gral.DrawableConstants;
    3031import de.erichseifert.gral.DrawablePanel;
    3132import de.erichseifert.gral.InteractivePanel;
     33import de.erichseifert.gral.Legend;
     34import de.erichseifert.gral.DrawableConstants.Location;
     35import de.erichseifert.gral.data.DataSeries;
    3236import de.erichseifert.gral.data.DataTable;
    3337import de.erichseifert.gral.data.Row;
     
    4246import de.erichseifert.gral.plots.axes.AxisRenderer2D;
    4347import de.erichseifert.gral.plots.lines.DefaultLineRenderer2D;
     48import de.erichseifert.gral.plots.lines.LineRenderer2D;
    4449import de.erichseifert.gral.util.Insets2D;
    4550import de.erichseifert.warp.GameAction;
     51import de.erichseifert.warp.Player;
    4652
    4753public class APMChart extends JPanel {
    4854
    49         public APMChart(List<? extends GameAction> actions) {
     55        public APMChart(Player... players) {
    5056                super(new BorderLayout());
    51                 DataTable histogramData = new DataTable(Double.class, Double.class);
    52                 for (GameAction action : actions) {
    53                         histogramData.add(action.getTimestamp()/25.0, action.getTimestamp()/25.0);
     57                DataSeries[] playerData = new DataSeries[players.length];
     58                // For each of the specified players
     59                for (int playerIndex = 0; playerIndex < players.length; playerIndex++) {
     60                        Player player = players[playerIndex];
     61                        List<? extends GameAction> actions = player.getActions();
     62
     63                        // Create a data set and fill it with the actions' time stamps
     64                        DataTable timeStamps = new DataTable(Double.class, Double.class);
     65                        for (GameAction action : actions) {
     66                                double timeInSeconds = action.getTimestamp()/25.0;
     67                                timeStamps.add(timeInSeconds, timeInSeconds);
     68                        }
     69
     70                        /*
     71                         * The following step is needed to transform the time stamps of the actions,
     72                         * which occur irregularly, to discrete data. This allows a filter to be applied.
     73                         */
     74                        // Calculate the intervals of the histogram's sectors
     75                        double timeMax = actions.get(actions.size()-1).getTimestamp()/25.0;
     76                        int cellCount = (int) Math.ceil(timeMax);
     77                        Number[][] cells = new Number[1][cellCount];
     78                        // The intervals are one second wide
     79                        for (int i = 0; i < cellCount; i++) {
     80                                cells[0][i] = (double) i;
     81                        }
     82                        // The following histogram calculates the number of occurrences of a value in each sector
     83                        Histogram actionsPerInterval = new Histogram(timeStamps, cells);
     84
     85                        // Insert the number of occurrences (y-axis) per interval (x-axis) into a new data set
     86                        DataTable apmData = new DataTable(Double.class, Long.class);
     87                        for (Row row : actionsPerInterval) {
     88                                Number x = actionsPerInterval.getCellLimits(0, row.getRow())[0];
     89                                Number y = row.get(0);
     90                                apmData.add(x, y);
     91                        }
     92                        // Transform the current data's unit (actions per second) to actions per minute
     93                        Kernel kernelAPM = KernelUtils.getUniform(60, 30, 1.0);
     94                        Filter filterAPM = new Convolution(apmData, kernelAPM, Mode.MODE_ZERO, 1);
     95                        // Smooth the curve
     96                        Kernel kernelAPMSmooth = KernelUtils.getBinomial(1.0);
     97                        Filter filterAPMSmooth = new Convolution(filterAPM, kernelAPMSmooth, Mode.MODE_ZERO, 1);
     98                        DataSeries playerSeries = new DataSeries(player.getName(), filterAPMSmooth, 0, 1);
     99                        playerData[playerIndex] = playerSeries;
    54100                }
    55                 double timeMax = actions.get(actions.size()-1).getTimestamp()/25.0;
    56                 int cellCount = (int) Math.ceil(timeMax);
    57                 Number[][] cells = new Number[1][cellCount];
    58                 for (int i = 0; i < cellCount; i++) {
    59                         cells[0][i] = (double) i;
     101
     102                XYPlot plot = new XYPlot(playerData);
     103                // Configure plot
     104                plot.setSetting(XYPlot.KEY_TITLE, "Actions per minute (Smoothed)");
     105                plot.setInsets(new Insets2D.Double(20.0, 60.0, 80.0, 40.0));
     106                // Configure legend
     107                plot.setSetting(XYPlot.KEY_LEGEND, true);
     108                plot.setSetting(XYPlot.KEY_LEGEND_LOCATION, Location.NORTH_EAST);
     109                plot.setSetting(XYPlot.KEY_LEGEND_MARGIN, new Insets2D.Double(10.0));
     110                plot.getLegend().setInsets(new Insets2D.Double(5.0));
     111                plot.getLegend().setSetting(Legend.KEY_ORIENTATION, DrawableConstants.Orientation.HORIZONTAL);
     112                // Configure line and shape renderers
     113                for (int playerIndex = 0; playerIndex < players.length; playerIndex++) {
     114                        DataSeries playerSeries = playerData[playerIndex];
     115                        plot.setPointRenderer(playerSeries, null);
     116                        LineRenderer2D lineRenderer = new DefaultLineRenderer2D();
     117                        lineRenderer.setSetting(LineRenderer2D.KEY_COLOR, players[playerIndex].getColor());
     118                        plot.setLineRenderer(playerSeries, lineRenderer);
    60119                }
    61                 Histogram actionsPerInterval = new Histogram(histogramData, cells);
     120                // Configure axes
     121                AxisRenderer2D axisXRenderer = plot.getSetting(XYPlot.KEY_AXIS_X_RENDERER);
     122                axisXRenderer.setSetting(AxisRenderer2D.KEY_LABEL, "Time [s]");
     123                axisXRenderer.setSetting(AxisRenderer2D.KEY_TICKS_SPACING, 30.0);
     124                axisXRenderer.setSetting(AxisRenderer2D.KEY_TICKS_MINOR_COUNT, 0);
     125                AxisRenderer2D axisYRenderer = plot.getSetting(XYPlot.KEY_AXIS_Y_RENDERER);
     126                axisYRenderer.setSetting(AxisRenderer2D.KEY_LABEL, "APM");
     127                axisYRenderer.setSetting(AxisRenderer2D.KEY_LABEL_DISTANCE, 2.0);
     128                axisYRenderer.setSetting(AxisRenderer2D.KEY_TICKS_SPACING, 10.0);
     129                axisYRenderer.setSetting(AxisRenderer2D.KEY_TICKS_MINOR_COUNT, 0);
     130                Axis axisX = plot.getAxis(Axis.X);
     131                axisX.setMin(0);
     132                Axis axisY = plot.getAxis(Axis.Y);
     133                axisY.setMin(0);
     134                double maxY = plot.getAxis(Axis.Y).getMax().doubleValue() + 2.0*axisYRenderer.<Double>getSetting(AxisRenderer2D.KEY_TICKS_SPACING);
     135                axisY.setMax(maxY);
    62136
    63                 DataTable apmData = new DataTable(Double.class, Long.class);
    64                 for (Row row : actionsPerInterval) {
    65                         Number x = actionsPerInterval.getCellLimits(0, row.getRow())[0];
    66                         Number y = row.get(0);
    67                         apmData.add(x, y);
    68                 }
    69                 Kernel kernelAPM = KernelUtils.getUniform(60, 30, 1.0);
    70                 Filter filterAPM = new Convolution(apmData, kernelAPM, Mode.MODE_ZERO, 1);
    71                 Kernel kernelAPMSmooth = KernelUtils.getBinomial(1.0);
    72                 Filter filterAPMSmooth = new Convolution(filterAPM, kernelAPMSmooth, Mode.MODE_ZERO, 1);
    73 
    74                 XYPlot plot = new XYPlot(filterAPMSmooth, filterAPM);
    75                 plot.setSetting(XYPlot.KEY_TITLE, "Actions per minute");
    76                 plot.setInsets(new Insets2D.Double(20.0, 40.0, 40.0, 40.0));
    77                 plot.setPointRenderer(filterAPMSmooth, null);
    78                 plot.setLineRenderer(filterAPMSmooth, new DefaultLineRenderer2D());
    79                 plot.setPointRenderer(filterAPM, null);
    80                 plot.setLineRenderer(filterAPM, new DefaultLineRenderer2D());
    81                 AxisRenderer2D axisX = plot.getSetting(XYPlot.KEY_AXIS_X_RENDERER);
    82                 axisX.setSetting(AxisRenderer2D.KEY_TICKS_SPACING, 30.0);
    83                 axisX.setSetting(AxisRenderer2D.KEY_TICKS_MINOR_COUNT, 0);
    84                 AxisRenderer2D axisY = plot.getSetting(XYPlot.KEY_AXIS_Y_RENDERER);
    85                 axisY.setSetting(AxisRenderer2D.KEY_TICKS_SPACING, 10.0);
    86                 axisY.setSetting(AxisRenderer2D.KEY_TICKS_MINOR_COUNT, 0);
    87                 plot.getAxis(Axis.X).setMin(0);
    88                 /*plot.getAxis(Axis.X).setMax(100);*/
    89                 plot.getAxis(Axis.Y).setMin(0.0);
    90                 //plot.getAxis(Axis.Y).setMax(10.0);
    91137                DrawablePanel plotPanel = new InteractivePanel(plot);
    92138                plotPanel.setPreferredSize(new Dimension(640, 480));
  • src/main/java/de/erichseifert/warp/gui/DefaultPlayerRenderer.java

    rf29aea6 rce08ae3  
    2828import java.awt.Insets;
    2929import java.awt.Shape;
     30import java.awt.Window;
    3031import java.awt.event.ActionEvent;
    3132import java.awt.event.ActionListener;
     
    3637import java.util.HashMap;
    3738import java.util.HashSet;
    38 import java.util.List;
    3939import java.util.Map;
    4040import java.util.Set;
     
    4949import javax.swing.event.ChangeListener;
    5050
    51 import de.erichseifert.warp.GameAction;
    5251import de.erichseifert.warp.Player;
    5352
     
    9796                                @Override
    9897                                public void actionPerformed(ActionEvent e) {
    99                                         JDialog infoDialog = new JDialog();
    100                                         List<? extends GameAction> actions = DefaultPlayerComponent.this.player.getActions();
    101                                         infoDialog.getContentPane().add(new APMChart(actions));
     98                                        JDialog infoDialog = new JDialog((Window)null, "APM chart");
     99                                        infoDialog.getContentPane().add(new APMChart(DefaultPlayerComponent.this.player));
    102100                                        infoDialog.setVisible(true);
    103                                         infoDialog.setSize(800, 600);
     101                                        infoDialog.setSize(1024, 768);
    104102                                        infoDialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
    105103                                }
Note: See TracChangeset for help on using the changeset viewer.