org.samjoey.gui.GraphicalViewer.java Source code

Java tutorial

Introduction

Here is the source code for org.samjoey.gui.GraphicalViewer.java

Source

/*
 * Copyright 2014 Sam.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.samjoey.gui;

import static java.awt.event.InputEvent.CTRL_DOWN_MASK;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import javax.swing.JFileChooser;
import javax.swing.JOptionPane;
import javax.swing.KeyStroke;
import javax.swing.filechooser.FileNameExtensionFilter;
import org.jfree.chart.ChartPanel;
import org.samjoey.graphing.GraphUtility;
import org.samjoey.model.Game;
import org.samjoey.parse.JSCAParser;
import org.samjoey.pattern.PatternFinder;

/**
 *
 * @author Sam
 */
public class GraphicalViewer extends javax.swing.JFrame {

    private static final String WHITE_PAWN = "♙";
    private static final String WHITE_BISHOP = "♗";
    private static final String WHITE_KNIGHT = "♘";
    private static final String WHITE_ROOK = "♖";
    private static final String WHITE_QUEEN = "♕";
    private static final String WHITE_KING = "♔";
    private static final String BLACK_PAWN = "♟";
    private static final String BLACK_BISHOP = "♝";
    private static final String BLACK_KNIGHT = "♞";
    private static final String BLACK_ROOK = "♜";
    private static final String BLACK_QUEEN = "♛";
    private static final String BLACK_KING = "♚";
    private LinkedList<Game> games;
    private int currentGame;
    private int currentPly;
    private HashMap<String, ChartPanel> graphs;
    private volatile boolean running = true;

    /**
     * Creates new form GraphicalViewer
     */
    public GraphicalViewer() {
        initComponents();
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPanel_Parser = new javax.swing.JPanel();
        jTextField_Parser = new javax.swing.JTextField();
        jButton_Parser_Open = new javax.swing.JButton();
        parserProgress = new javax.swing.JProgressBar();
        jPanel1 = new javax.swing.JPanel();
        jButton_PreviousGame = new javax.swing.JButton();
        jButton_Next_Game = new javax.swing.JButton();
        jButton_Previous_Ply = new javax.swing.JButton();
        jButton_Next_Ply = new javax.swing.JButton();
        jScrollPane2 = new javax.swing.JScrollPane();
        jTextArea_Game_Viewer = new javax.swing.JTextPane();
        Ply_Label = new javax.swing.JLabel();
        Game_Label = new javax.swing.JLabel();
        Variable_Viewer_Panel = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        jScrollPane1 = new javax.swing.JScrollPane();
        Variable_Viewer_Textpane = new javax.swing.JTextPane();
        Graph_Panel = new javax.swing.JPanel();
        Variable_Chooser = new javax.swing.JComboBox();
        graphFrame = new javax.swing.JInternalFrame();
        jPanel2 = new javax.swing.JPanel();
        pattern_Button = new javax.swing.JButton();
        writerPanel = new javax.swing.JPanel();
        pattern_Button1 = new javax.swing.JButton();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenu_Open = new javax.swing.JMenuItem();
        jMenu2 = new javax.swing.JMenu();
        jMenu_Game = new javax.swing.JMenuItem();
        jMenu_Ply = new javax.swing.JMenuItem();
        Graphs_MenuItem = new javax.swing.JMenuItem();

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setPreferredSize(new java.awt.Dimension(20000, 20000));

        jPanel_Parser.setBorder(
                javax.swing.BorderFactory.createTitledBorder(javax.swing.BorderFactory.createEtchedBorder(),
                        "Parser", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.TOP));
        jPanel_Parser.setName("Parser"); // NOI18N

        jTextField_Parser.setText("No File Chosen");
        jTextField_Parser.setEnabled(false);
        jTextField_Parser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jTextField_ParserActionPerformed(evt);
            }
        });

        jButton_Parser_Open.setText("Parse");
        jButton_Parser_Open.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton_Parser_OpenActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel_ParserLayout = new javax.swing.GroupLayout(jPanel_Parser);
        jPanel_Parser.setLayout(jPanel_ParserLayout);
        jPanel_ParserLayout.setHorizontalGroup(jPanel_ParserLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel_ParserLayout.createSequentialGroup().addContainerGap()
                        .addGroup(jPanel_ParserLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(parserProgress, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGroup(jPanel_ParserLayout.createSequentialGroup()
                                        .addComponent(jButton_Parser_Open, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                        .addComponent(jTextField_Parser, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                109, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addContainerGap()));
        jPanel_ParserLayout
                .setVerticalGroup(jPanel_ParserLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(jPanel_ParserLayout.createSequentialGroup().addGap(3, 3, 3)
                                .addGroup(jPanel_ParserLayout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                        .addComponent(jTextField_Parser).addComponent(jButton_Parser_Open,
                                                javax.swing.GroupLayout.PREFERRED_SIZE, 0, Short.MAX_VALUE))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(parserProgress, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addContainerGap()));

        jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder(
                javax.swing.BorderFactory.createEtchedBorder(), "Game Viewer",
                javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.TOP));

        jButton_PreviousGame.setText("");
        jButton_PreviousGame.setToolTipText("Beginning of Game");
        jButton_PreviousGame.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton_PreviousGameActionPerformed(evt);
            }
        });

        jButton_Next_Game.setText("");
        jButton_Next_Game.setToolTipText("End of Game");
        jButton_Next_Game.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton_Next_GameActionPerformed(evt);
            }
        });

        jButton_Previous_Ply.setText("");
        jButton_Previous_Ply.setToolTipText("Previous Ply");
        jButton_Previous_Ply.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton_Previous_PlyActionPerformed(evt);
            }
        });

        jButton_Next_Ply.setText("");
        jButton_Next_Ply.setToolTipText("Next Ply");
        jButton_Next_Ply.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jButton_Next_PlyActionPerformed(evt);
            }
        });

        jTextArea_Game_Viewer.setContentType("text/html"); // NOI18N
        jTextArea_Game_Viewer.setFont(new java.awt.Font("Monospaced", 0, 24)); // NOI18N
        jScrollPane2.setViewportView(jTextArea_Game_Viewer);

        Ply_Label.setText("Ply: ");

        Game_Label.setText("Game: ");

        javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
        jPanel1.setLayout(jPanel1Layout);
        jPanel1Layout.setHorizontalGroup(jPanel1Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup().addContainerGap().addGroup(jPanel1Layout
                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                        .addGroup(
                                jPanel1Layout.createSequentialGroup().addComponent(jScrollPane2).addContainerGap())
                        .addGroup(jPanel1Layout.createSequentialGroup().addComponent(jButton_PreviousGame)
                                .addGap(18, 18, 18)
                                .addGroup(jPanel1Layout
                                        .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                        .addComponent(jButton_Previous_Ply, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                43, javax.swing.GroupLayout.PREFERRED_SIZE)
                                        .addComponent(Game_Label))
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 89,
                                        Short.MAX_VALUE)
                                .addGroup(
                                        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                                .addGroup(jPanel1Layout.createSequentialGroup()
                                                        .addComponent(jButton_Next_Ply).addGap(18, 18, 18)
                                                        .addComponent(jButton_Next_Game))
                                                .addComponent(Ply_Label))
                                .addGap(11, 11, 11)))));
        jPanel1Layout.setVerticalGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel1Layout.createSequentialGroup().addContainerGap().addComponent(jScrollPane2)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(jButton_PreviousGame)
                                .addComponent(jButton_Previous_Ply, javax.swing.GroupLayout.PREFERRED_SIZE, 23,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jButton_Next_Ply, javax.swing.GroupLayout.PREFERRED_SIZE, 23,
                                        javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addComponent(jButton_Next_Game))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(Game_Label).addComponent(Ply_Label))
                        .addGap(6, 6, 6)));

        Variable_Viewer_Panel.setBorder(javax.swing.BorderFactory.createTitledBorder(
                javax.swing.BorderFactory.createEtchedBorder(), "Variable View",
                javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.TOP));

        jScrollPane3.setMaximumSize(new java.awt.Dimension(75, 100));

        Variable_Viewer_Textpane.setEnabled(false);
        jScrollPane1.setViewportView(Variable_Viewer_Textpane);

        jScrollPane3.setViewportView(jScrollPane1);

        javax.swing.GroupLayout Variable_Viewer_PanelLayout = new javax.swing.GroupLayout(Variable_Viewer_Panel);
        Variable_Viewer_Panel.setLayout(Variable_Viewer_PanelLayout);
        Variable_Viewer_PanelLayout
                .setHorizontalGroup(
                        Variable_Viewer_PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addGroup(Variable_Viewer_PanelLayout.createSequentialGroup().addContainerGap()
                                        .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addContainerGap()));
        Variable_Viewer_PanelLayout.setVerticalGroup(Variable_Viewer_PanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(Variable_Viewer_PanelLayout.createSequentialGroup().addContainerGap()
                        .addComponent(jScrollPane3, javax.swing.GroupLayout.DEFAULT_SIZE, 339, Short.MAX_VALUE)
                        .addContainerGap()));

        Graph_Panel.setBorder(javax.swing.BorderFactory.createTitledBorder(
                javax.swing.BorderFactory.createEtchedBorder(), "Graph Viewer",
                javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.TOP));

        Variable_Chooser.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Select Variable..." }));
        Variable_Chooser.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Variable_ChooserActionPerformed(evt);
            }
        });

        graphFrame.setEnabled(false);
        graphFrame.setVisible(true);

        javax.swing.GroupLayout graphFrameLayout = new javax.swing.GroupLayout(graphFrame.getContentPane());
        graphFrame.getContentPane().setLayout(graphFrameLayout);
        graphFrameLayout.setHorizontalGroup(graphFrameLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 0, Short.MAX_VALUE));
        graphFrameLayout.setVerticalGroup(graphFrameLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING).addGap(0, 0, Short.MAX_VALUE));

        javax.swing.GroupLayout Graph_PanelLayout = new javax.swing.GroupLayout(Graph_Panel);
        Graph_Panel.setLayout(Graph_PanelLayout);
        Graph_PanelLayout.setHorizontalGroup(Graph_PanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, Graph_PanelLayout.createSequentialGroup()
                        .addContainerGap()
                        .addGroup(Graph_PanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
                                .addComponent(graphFrame).addComponent(Variable_Chooser, 0, 371, Short.MAX_VALUE))
                        .addContainerGap()));
        Graph_PanelLayout.setVerticalGroup(Graph_PanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(Graph_PanelLayout.createSequentialGroup().addContainerGap()
                        .addComponent(Variable_Chooser, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(graphFrame).addContainerGap()));

        pattern_Button.setText("Find Patterns");
        pattern_Button.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pattern_ButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(jPanel2Layout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap().addComponent(pattern_Button,
                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap()));
        jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(jPanel2Layout.createSequentialGroup().addContainerGap()
                        .addComponent(pattern_Button, javax.swing.GroupLayout.DEFAULT_SIZE, 28, Short.MAX_VALUE)
                        .addContainerGap()));

        pattern_Button1.setText("Write to File");
        pattern_Button1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                pattern_Button1ActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout writerPanelLayout = new javax.swing.GroupLayout(writerPanel);
        writerPanel.setLayout(writerPanelLayout);
        writerPanelLayout.setHorizontalGroup(writerPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(writerPanelLayout.createSequentialGroup().addContainerGap()
                        .addComponent(pattern_Button1, javax.swing.GroupLayout.DEFAULT_SIZE, 368, Short.MAX_VALUE)
                        .addContainerGap()));
        writerPanelLayout.setVerticalGroup(writerPanelLayout
                .createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(writerPanelLayout.createSequentialGroup().addContainerGap().addComponent(pattern_Button1,
                        javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addContainerGap()));

        jMenu1.setText("File");

        jMenu_Open.setText("Open");
        jMenu_Open.setAccelerator(KeyStroke.getKeyStroke('O', CTRL_DOWN_MASK));
        jMenu_Open.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenu_OpenActionPerformed(evt);
            }
        });
        jMenu1.add(jMenu_Open);

        jMenuBar1.add(jMenu1);

        jMenu2.setText("Game");

        jMenu_Game.setText("Game");
        jMenu_Game.setAccelerator(KeyStroke.getKeyStroke('G', CTRL_DOWN_MASK));
        jMenu_Game.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenu_GameActionPerformed(evt);
            }
        });
        jMenu2.add(jMenu_Game);

        jMenu_Ply.setAccelerator(KeyStroke.getKeyStroke('T', CTRL_DOWN_MASK));
        jMenu_Ply.setText("Ply");
        jMenu_Ply.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenu_PlyActionPerformed(evt);
            }
        });
        jMenu2.add(jMenu_Ply);

        Graphs_MenuItem.setText("Display Graphs");
        Graphs_MenuItem.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                Graphs_MenuItemActionPerformed(evt);
            }
        });
        jMenu2.add(Graphs_MenuItem);

        jMenuBar1.add(jMenu2);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addGap(24, 24, 24)
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                                .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(Variable_Viewer_Panel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(jPanel_Parser, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addComponent(writerPanel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(Graph_Panel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)));
        layout.setVerticalGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                .addGroup(layout.createSequentialGroup().addContainerGap()
                        .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                .addGroup(layout.createSequentialGroup()
                                        .addComponent(jPanel_Parser, javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                        .addComponent(Variable_Viewer_Panel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                                javax.swing.GroupLayout.DEFAULT_SIZE,
                                                javax.swing.GroupLayout.PREFERRED_SIZE))
                                .addComponent(Graph_Panel, javax.swing.GroupLayout.DEFAULT_SIZE,
                                        javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(writerPanel, javax.swing.GroupLayout.PREFERRED_SIZE,
                                javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addGap(133, 133, 133)));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    //Nothing happens
    private void jTextField_ParserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jTextField_ParserActionPerformed
        // TODO add your handling code here:
    }//GEN-LAST:event_jTextField_ParserActionPerformed

    //When the 'Parse' button is pressed, open a file chooser
    private void jButton_Parser_OpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton_Parser_OpenActionPerformed
        JFileChooser fc = new JFileChooser();
        fc.setFileSelectionMode(JFileChooser.FILES_ONLY);
        String[] exts = new String[2];
        exts[0] = "pgn";
        exts[1] = "jsca";
        FileNameExtensionFilter filter = new FileNameExtensionFilter(".pgn or .jsca files ONLY!", exts);
        fc.setFileFilter(filter);
        int returnVal = fc.showDialog(this, "Parse");

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            final java.io.File file = fc.getSelectedFile();
            //This is where a real application would open the file.
            this.jTextField_Parser.setText(file.getName());
            (new Thread() {
                @Override
                public void run() {
                    selectedPGN(file);
                }
            }).start();
        } else {
        }
    }//GEN-LAST:event_jButton_Parser_OpenActionPerformed

    //Forward the viewer onto the next game
    private void jButton_Next_GameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton_Next_GameActionPerformed
        try {
            if (currentGame < games.size() - 1) {
                this.setViewer(currentGame + 1, 0);
            }
        } catch (NullPointerException npe) {
        }
    }//GEN-LAST:event_jButton_Next_GameActionPerformed

    //Send the viewer back a ply
    private void jButton_Previous_PlyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton_Previous_PlyActionPerformed
        try {
            if (currentPly > 1) {
                this.setViewer(currentGame, currentPly - 1);
            }
        } catch (NullPointerException npe) {
        }
    }//GEN-LAST:event_jButton_Previous_PlyActionPerformed

    //Send the viewer forward a ply
    private void jButton_Next_PlyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton_Next_PlyActionPerformed
        try {
            if (currentPly < games.get(currentGame).getPlyCount() - 1) {
                this.setViewer(currentGame, currentPly + 1);
            }
        } catch (NullPointerException npe) {
        }
    }//GEN-LAST:event_jButton_Next_PlyActionPerformed

    //Send the viewer back a game
    private void jButton_PreviousGameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton_PreviousGameActionPerformed
        try {
            if (currentGame > 1) {
                this.setViewer(currentGame - 1, 0);
            }
        } catch (NullPointerException npe) {
        }
    }//GEN-LAST:event_jButton_PreviousGameActionPerformed

    //When different variable is chosen for graphs
    private void Variable_ChooserActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Variable_ChooserActionPerformed
        // Explaination here please
        Set<String> keys = games.get(0).getVarData().keySet();
        for (String key : keys) {
            Variable_Chooser.addItem(key);
        }
        graphs = GraphUtility.getGraphs(games);

        String var = (String) this.Variable_Chooser.getSelectedItem();
        if (var != null && graphs.containsKey(var)) {
            graphFrame.setVisible(false);
            graphFrame.setContentPane(graphs.get(var));
            graphFrame.pack();
            graphFrame.setVisible(true);
        }
    }//GEN-LAST:event_Variable_ChooserActionPerformed

    //Initiate pattern finding
    private void pattern_ButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pattern_ButtonActionPerformed
        PatternFinder.findPatterns(games);
    }//GEN-LAST:event_pattern_ButtonActionPerformed

    //To write the games to a .jsca file
    private void pattern_Button1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_pattern_Button1ActionPerformed
        try {
            PrintWriter writer = new PrintWriter(
                    this.jTextField_Parser.getText().substring(0, this.jTextField_Parser.getText().length() - 3)
                            + "jsca",
                    "UTF-8");
            for (int j = 0; j < games.size(); j++) {
                Game g = games.get(j);
                if (g == null) {
                    continue;
                }
                String str = g.toString();
                int last = 0;
                for (int i = 0; i < str.length(); i++) {
                    try {
                        if (str.substring(i, i + 1).equals("]") && !str.substring(i, i + 3).equals("] ]")) {
                            writer.println(str.substring(last, i + 1));
                            last = i + 1;
                        }
                    } catch (java.lang.StringIndexOutOfBoundsException ex) {
                        if (str.substring(i, i + 1).equals("]")) {
                            writer.println(str.substring(last, i + 1));
                            last = i + 1;
                        }
                    }
                }
                writer.println();
            }
            writer.close();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(GraphicalViewer.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(GraphicalViewer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_pattern_Button1ActionPerformed

    //When the menu 'Open' is pressed, fire as if 'Parse' was pressed
    private void jMenu_OpenActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenu_OpenActionPerformed
        this.jButton_Parser_OpenActionPerformed(evt);
    }//GEN-LAST:event_jMenu_OpenActionPerformed

    //When the user wants to jump games, prompt them for a game number and try to jump to that game
    private void jMenu_GameActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenu_GameActionPerformed
        String inputValue = JOptionPane.showInputDialog("Please input a value (Integers only):");
        try {
            setViewer(Integer.parseInt(inputValue), 0);
        } catch (Exception e) {
        }
    }//GEN-LAST:event_jMenu_GameActionPerformed

    //When the user wants to jump to a new ply, prompt them for a ply number and try to jump to that ply
    private void jMenu_PlyActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jMenu_PlyActionPerformed
        String inputValue = JOptionPane.showInputDialog("Please input a value (Integers only):");
        try {
            setViewer(currentGame, Integer.parseInt(inputValue));
        } catch (Exception e) {
        }
    }//GEN-LAST:event_jMenu_PlyActionPerformed

    //For displaying graphs from specific games
    private void Graphs_MenuItemActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_Graphs_MenuItemActionPerformed
        String inputValue = JOptionPane.showInputDialog("Please input a values separated by commas:");
        try {
            String[] vals = inputValue.split(",");
            LinkedList<Game> getFor = new LinkedList<>();
            for (String str : vals) {
                getFor.add(games.get(Integer.parseInt(str)));
            }
            for (String s : getFor.get(0).getVarData().keySet()) {
                this.Variable_Chooser.addItem(s);
            }
            graphs = GraphUtility.getGraphs(getFor);
        } catch (Exception e) {
            try {
                String[] vals = inputValue.split(", ");
                LinkedList<Game> getFor = new LinkedList<>();
                for (String str : vals) {
                    getFor.add(games.get(Integer.parseInt(str)));
                }
                for (String s : getFor.get(0).getVarData().keySet()) {
                    this.Variable_Chooser.addItem(s);
                }
                graphs = GraphUtility.getGraphs(getFor);
            } catch (Exception ee) {
            }
        }
    }//GEN-LAST:event_Graphs_MenuItemActionPerformed

    //Mananage opening a file;
    private void selectedPGN(File file) {

        String fileLoc = file.getAbsolutePath();
        //fileLoc = "File:" + fileLoc.substring(2);
        if (fileLoc.substring(fileLoc.length() - 3).equals("pgn")) {
            for (int i = 0; i < fileLoc.length(); i++) {
                if (fileLoc.substring(i, i + 1).equals("/")) {
                    fileLoc = fileLoc.substring(0, i) + "\\" + fileLoc.substring(i + 1);
                }
            }
            try {
                // Below: Talk to JavaScript
                ScriptEngineManager factory = new ScriptEngineManager();
                // create JavaScript engine
                final ScriptEngine engine = factory.getEngineByName("JavaScript");
                // evaluate JavaScript code from given file - specified by first argument
                engine.put("engine", engine);
                ClassLoader cl = GraphicalViewer.class.getClassLoader();
                // Talk to GameLooper_1
                URL url = cl.getResource("\\org\\samjoey\\gameLooper\\GameLooper_1.js");
                String loopLoc = url.toString().substring(5);
                for (int i = 0; i < loopLoc.length() - 3; i++) {
                    if (loopLoc.substring(i, i + 3).equals("%5c")) {
                        loopLoc = loopLoc.substring(0, i) + "/" + loopLoc.substring(i + 3);
                    }
                }
                engine.put("loopLoc", loopLoc);
                // Talk to calcDefs_1
                url = cl.getResource("\\org\\samjoey\\calculator\\calcDefs_1.js");
                String defsLoc = url.toString().substring(5);
                for (int i = 0; i < defsLoc.length() - 3; i++) {
                    if (defsLoc.substring(i, i + 3).equals("%5c")) {
                        defsLoc = defsLoc.substring(0, i) + "/" + defsLoc.substring(i + 3);
                    }
                }
                engine.put("defsLoc", defsLoc);
                // Talk to Calculator
                url = cl.getResource("\\org\\samjoey\\calculator\\Calculator.js");
                String calcLoc = url.toString().substring(5);
                for (int i = 0; i < calcLoc.length() - 3; i++) {
                    if (calcLoc.substring(i, i + 3).equals("%5c")) {
                        calcLoc = calcLoc.substring(0, i) + "/" + calcLoc.substring(i + 3);
                    }
                }
                engine.put("calcLoc", calcLoc);
                String args[] = { "-g:false", fileLoc };
                engine.put("arguments", args);

                // Create a Thread to update the parser's progress bar
                parserProgress.setStringPainted(true);
                running = false;
                running = true;
                Thread thread = new Thread() {
                    @Override
                    public void run() {
                        long last = 0l;
                        boolean print = true;
                        double p = .01;
                        while (engine.get("progress") == null || engine.get("size") == null
                                || Integer.parseInt((String) engine.get("progress")) != Integer
                                        .parseInt((String) engine.get("size"))) {
                            //if (Parser.numGames > 0 && Parser.progress == Parser.numGames) {
                            try {
                                parserProgress.setValue(Integer.parseInt((String) engine.get("progress")));
                                parserProgress.setMaximum(Integer.parseInt((String) engine.get("size")));
                                if (last == 0l) {
                                    last = System.nanoTime();
                                }
                                if ((double) parserProgress.getValue() / (double) parserProgress.getMaximum() > p
                                        && print) {
                                    //System.out.println(p + ": " + (System.nanoTime() - last));
                                    //print = false;
                                    p += .01;
                                }
                            } catch (Exception e) {
                            }
                            //} else {
                            //    parserProgress.setMaximum(Parser.numGames - 1);
                            //    parserProgress.setMinimum(0);
                            //    parserProgress.setValue(Parser.progress);
                            //}
                        }
                        // finally
                        parserProgress.setValue(parserProgress.getMaximum());
                    }
                };
                thread.start();

                // I have no clue what's here!??
                engine.eval(new java.io.FileReader(
                        GraphicalViewer.class.getClassLoader().getResource("driver_1.js").toString().substring(5)));
                while (games == null || games.get((int) (Math.random() * games.size())).getVarData().size() < 20) {
                    games = (LinkedList<Game>) engine.get("gameList");
                }
            } catch (ScriptException | FileNotFoundException ex) {
                Logger.getLogger(GraphicalViewer.class.getName()).log(Level.SEVERE, null, ex);
            }
        } else if (fileLoc.substring(fileLoc.length() - 4).equals("jsca")) {
            JSCAParser jsca = new JSCAParser(fileLoc);
            games = (LinkedList<Game>) jsca.getGamesList();
        }

        Set<String> keys = games.get(0).getVarData().keySet();
        for (String key : keys) {
            Variable_Chooser.addItem(key);
        }
        graphs = GraphUtility.getGraphs(games);

        setViewer(0, 0);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String args[]) {
        /* Set the Nimbus look and feel */
        //<editor-fold defaultstate="collapsed" desc=" Look and feel setting code (optional) ">
        /* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.
         * For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html 
         */
        try {
            for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {
                if ("Nimbus".equals(info.getName())) {
                    javax.swing.UIManager.setLookAndFeel(info.getClassName());
                    break;
                }
            }
        } catch (ClassNotFoundException | InstantiationException | IllegalAccessException
                | javax.swing.UnsupportedLookAndFeelException ex) {
            java.util.logging.Logger.getLogger(GraphicalViewer.class.getName()).log(java.util.logging.Level.SEVERE,
                    null, ex);
        }
        //</editor-fold>

        /* Create and display the form */
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                javax.swing.JFrame gv = new GraphicalViewer();
                gv.setVisible(true);
                gv.setExtendedState(gv.getExtendedState() | javax.swing.JFrame.MAXIMIZED_BOTH);
            }
        });
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JLabel Game_Label;
    private javax.swing.JPanel Graph_Panel;
    private javax.swing.JMenuItem Graphs_MenuItem;
    private javax.swing.JLabel Ply_Label;
    private javax.swing.JComboBox Variable_Chooser;
    private javax.swing.JPanel Variable_Viewer_Panel;
    private javax.swing.JTextPane Variable_Viewer_Textpane;
    private javax.swing.JInternalFrame graphFrame;
    protected javax.swing.JButton jButton_Next_Game;
    protected javax.swing.JButton jButton_Next_Ply;
    private javax.swing.JButton jButton_Parser_Open;
    protected javax.swing.JButton jButton_PreviousGame;
    protected javax.swing.JButton jButton_Previous_Ply;
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenu jMenu2;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenu_Game;
    private javax.swing.JMenuItem jMenu_Open;
    private javax.swing.JMenuItem jMenu_Ply;
    private javax.swing.JPanel jPanel1;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel_Parser;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JTextPane jTextArea_Game_Viewer;
    private javax.swing.JTextField jTextField_Parser;
    private volatile javax.swing.JProgressBar parserProgress;
    private javax.swing.JButton pattern_Button;
    private javax.swing.JButton pattern_Button1;
    private javax.swing.JPanel writerPanel;
    // End of variables declaration//GEN-END:variables

    //Set the viewer to a new game and ply   // Neutral setViewer (pgn and jsca)
    private void setViewer(int game, int ply) {
        Game g = games.get(game);
        // If g in null, will throw NullPointerException here
        String[][] board = g.getAllBoards().get(ply).getAll();
        String viewer = "";
        for (String[] r : board) {
            for (String c : r) {
                viewer += "|";
                if (c.equals("")) {
                    viewer += "&#8199;&thinsp;&thinsp;&thinsp;";
                    continue;
                }
                if (c.equals("WP")) {
                    viewer += WHITE_PAWN;
                    continue;
                }
                if (c.equals("WB")) {
                    viewer += WHITE_BISHOP;
                    continue;
                }
                if (c.equals("WN")) {
                    viewer += WHITE_KNIGHT;
                    continue;
                }
                if (c.equals("WR")) {
                    viewer += WHITE_ROOK;
                    continue;
                }
                if (c.equals("WQ")) {
                    viewer += WHITE_QUEEN;
                    continue;
                }
                if (c.equals("WK")) {
                    viewer += WHITE_KING;
                    continue;
                }
                if (c.equals("BP")) {
                    viewer += BLACK_PAWN;
                    continue;
                }
                if (c.equals("BB")) {
                    viewer += BLACK_BISHOP;
                    continue;
                }
                if (c.equals("BN")) {
                    viewer += BLACK_KNIGHT;
                    continue;
                }
                if (c.equals("BR")) {
                    viewer += BLACK_ROOK;
                    continue;
                }
                if (c.equals("BQ")) {
                    viewer += BLACK_QUEEN;
                    continue;
                }
                if (c.equals("BK")) {
                    viewer += BLACK_KING;
                    continue;
                }
            }
            viewer += "<br>";
        }
        this.jTextArea_Game_Viewer.setText(viewer);

        String variables = "";
        HashMap<String, ArrayList<Double>> vars = g.getVarData();
        for (String key : vars.keySet()) {
            variables += key;
            variables += "= ";
            variables += ("" + vars.get(key).get(ply));
            variables += "\n";
        }
        this.Variable_Viewer_Textpane.setText(variables);

        this.Game_Label.setText("Game ID: " + g.getId());
        this.Ply_Label.setText("Ply: " + ply + "/" + g.getPlyCount());
        this.currentGame = game;
        this.currentPly = ply;
    }
}