adopt MVC pattern and add real time graph interface

This commit is contained in:
2019-12-18 16:48:24 +01:00
parent 7f18a66e98
commit e0160ca1df
18 changed files with 450 additions and 29 deletions
@@ -0,0 +1,41 @@
package core.gui;
import core.algo.Learning;
import core.controller.ViewListener;
import javax.swing.*;
public class LearningInfoPanel extends JPanel {
private Learning learning;
private JLabel policyLabel;
private JLabel discountLabel;
private JLabel epsilonLabel;
private JSlider epsilonSlider;
private JSlider delaySlider;
public LearningInfoPanel(Learning learning, ViewListener viewListener){
this.learning = learning;
setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
policyLabel = new JLabel();
discountLabel = new JLabel();
epsilonLabel = new JLabel();
epsilonSlider = new JSlider(0, 100, (int)(learning.getEpsilon() * 100));
epsilonSlider.addChangeListener(e -> viewListener.onEpsilonChange(epsilonSlider.getValue() / 100f));
add(policyLabel);
add(discountLabel);
add(epsilonLabel);
add(epsilonSlider);
refreshLabels();
setVisible(true);
}
public void refreshLabels(){
policyLabel.setText("Policy: " + learning.getPolicy().getClass());
discountLabel.setText("Discount factor: " + learning.getDiscountFactor());
epsilonLabel.setText("Exploration (Epsilon): " + learning.getEpsilon());
}
protected JSlider getEpsilonSlider(){
return epsilonSlider;
}
}
+102
View File
@@ -0,0 +1,102 @@
package core.gui;
import core.algo.Learning;
import core.controller.ViewListener;
import core.listener.LearningListener;
import lombok.Getter;
import org.knowm.xchart.QuickChart;
import org.knowm.xchart.XChartPanel;
import org.knowm.xchart.XYChart;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class View<A extends Enum> implements LearningListener {
private Learning<A> learning;
@Getter
private XYChart chart;
@Getter
private LearningInfoPanel learningInfoPanel;
@Getter
private JFrame mainFrame;
private XChartPanel<XYChart> rewardChartPanel;
private ViewListener viewListener;
private List<Double> rewardHistory;
public View(Learning<A> learning, ViewListener viewListener){
this.learning = learning;
this.viewListener = viewListener;
rewardHistory = new ArrayList<>();
this.initMainFrame();
}
private void initMainFrame(){
mainFrame = new JFrame();
mainFrame.setPreferredSize(new Dimension(1280, 720));
mainFrame.setLayout(new BorderLayout());
initLearningInfoPanel();
initRewardChart();
mainFrame.add(BorderLayout.WEST, learningInfoPanel);
mainFrame.add(BorderLayout.CENTER, rewardChartPanel);
mainFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
mainFrame.pack();
mainFrame.setVisible(true);
}
private void initLearningInfoPanel(){
learningInfoPanel = new LearningInfoPanel(learning, viewListener);
}
private void initRewardChart(){
chart =
QuickChart.getChart(
"Rewards per Episode",
"Episode",
"Reward",
"randomWalk",
new double[] {0},
new double[] {0});
chart.getStyler().setLegendVisible(true);
chart.getStyler().setXAxisTicksVisible(true);
rewardChartPanel = new XChartPanel<>(chart);
rewardChartPanel.setPreferredSize(new Dimension(300,300));
}
public void showState(Visualizable state){
new JFrame(){
{
JComponent stateComponent = state.visualize();
setPreferredSize(new Dimension(stateComponent.getWidth(), stateComponent.getHeight()));
add(stateComponent);
setVisible(true);
}
};
}
public void updateRewardGraph(double recentReward){
rewardHistory.add(recentReward);
chart.updateXYSeries("randomWalk", null, rewardHistory, null);
rewardChartPanel.revalidate();
rewardChartPanel.repaint();
}
public void updateLearningInfoPanel(){
this.learningInfoPanel.refreshLabels();
}
@Override
public void onEpisodeEnd(double sumOfRewards) {
SwingUtilities.invokeLater(()->updateRewardGraph(sumOfRewards));
}
@Override
public void onEpisodeStart() {
}
}
+7
View File
@@ -0,0 +1,7 @@
package core.gui;
import javax.swing.*;
public interface Visualizable {
JComponent visualize();
}