com.raceup.fsae.test.TesterGui.java Source code

Java tutorial

Introduction

Here is the source code for com.raceup.fsae.test.TesterGui.java

Source

/*
 *  Copyright 2016-2018 Race Up
 *
 *  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 com.raceup.fsae.test;

import com.raceup.fsae.test.gui.TestFetcherPanel;
import com.raceup.fsae.test.gui.TestPanel;
import com.raceup.fsae.test.models.Answer;
import com.raceup.fsae.test.models.Question;
import com.raceup.fsae.test.models.Test;
import com.sirfoga.hal.gui.components.ClockTimer;
import com.sirfoga.hal.gui.dialog.AboutDialog;
import com.sirfoga.hal.gui.utils.SwingUtils;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVParser;
import org.apache.commons.csv.CSVRecord;

import javax.swing.*;
import java.awt.*;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;

import static com.sirfoga.hal.streams.Utils.readAllFromStream;

/**
 * New gui that holds a test
 */
class TesterGui extends JFrame {
    public static final String appName = "FSAE entry test simulator";
    public static final String appOrganization = "Raceup";
    public static final Image appIcon = Toolkit.getDefaultToolkit()
            .getImage("com.raceup.ed.telemetry.TelemetryGui".getClass().getResource("/res/images/icon.png"));
    private final ArrayList<String> results = new ArrayList<>(0);
    private final ClockTimer totalTestTimer = new ClockTimer("Total time");
    private Test test;
    private TestPanel testPanel;
    private boolean isPaused = false;
    private boolean isSubmitting = false;
    private int SECONDS_WAIT_BETWEEN_SUBMISSIONS = 30;
    private ClockTimer currentSubmissionTimer = new ClockTimer("Current submission time");

    public TesterGui() {
        super(appName);
        setIconImage(appIcon);
        setup();
    }

    /**
     * Shows gui
     */
    public void open() {
        openStartPanel();
        setLocationRelativeTo(null); // center in screen
        setVisible(true);
    }

    /*
     * Test
     */

    /**
     * Submit questions and reload test
     */
    private void submitTest() {
        if (!isPaused && !isSubmitting) { // not paused neither in submission
            currentSubmissionTimer.pause(); // pause timers
            totalTestTimer.pause();
            isSubmitting = true;

            String testResult = "Submission attempt: " + Integer.toString(results.size() + 1) + "\n";
            testResult += test.getSummary(currentSubmissionTimer.getTimeElapsed());
            results.add(testResult); // update list of results

            if (testPanel.isCorrect()) {
                showSuccessfulTestSubmissionDialog();
                exitApp();
            } else {
                testPanel.setVisible(false);
                showUnSuccessfulTestSubmissionDialog();
                isSubmitting = false;
                openQuestionsPanel(); // re-shuffle questions
                testPanel.setVisible(true);
            }
        }
    }

    /**
     * Pause timer and freeze test panel
     */
    private void pauseTest() {
        if (isPaused) {
            isPaused = false;
            currentSubmissionTimer.start(); // pause timers
            totalTestTimer.start();
        } else { // not paused
            isPaused = true;
            currentSubmissionTimer.pause(); // pause timers
            totalTestTimer.pause();
        }
    }

    /**
     * Exits test
     */
    private void exitTest() {
        exitApp();
    }

    /*
     * Setup gui
     */

    /**
     * setups gui
     */
    private void setup() {
        setupMenubar();
        setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    }

    /**
     * Shows gui to set preferences on test
     */
    private void openStartPanel() {
        setPreferredSize(new Dimension(600, 200));
        pack();
        repaint();
        setLocationRelativeTo(null);

        String pathToTestFile = new TestFetcherPanel().getPathOfDataFile();
        parseDataFileAndCreateTestOrFail(pathToTestFile);
        testPanel = new TestPanel(test);
        openQuestionsPanel();

        //        try {
        //            String pathToTestFile = new TestFetcherPanel()
        // .getPathOfDataFile();
        //            parseDataFileAndCreateTestOrFail(pathToTestFile);
        //            testPanel = new TestPanel(test);
        //            openQuestionsPanel();
        //        } catch (Exception e) {
        //            System.err.println(e.toString());
        //            JOptionPane.showMessageDialog(  // alert dialog with exception
        //                    null,
        //                    "Oops! Somehow data file could not be opened\n" +
        //                            "Check your connection (if you've downloaded
        // data) and retry!",
        //                    "Error",
        //                    JOptionPane.ERROR_MESSAGE
        //            );
        //            System.exit(1);
        //        }
    }

    /**
     * Shows gui to start a test
     */
    private void openQuestionsPanel() {
        currentSubmissionTimer = new ClockTimer("Current submission time"); // start timer
        currentSubmissionTimer.start();
        totalTestTimer.start();

        shuffleQuestions();
        testPanel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10) // title border
        );

        JPanel panel = new JPanel();
        panel.setLayout(new BoxLayout(panel, BoxLayout.PAGE_AXIS));

        panel.add(Box.createVerticalStrut(20));
        panel.add(new JScrollPane(testPanel));

        panel.add(createTimersPanel());
        panel.add(createMonitorPanel());
        setContentPane(panel); // scroll pane with questions

        setPreferredSize(new Dimension(400, 600));
        pack();
        repaint();
        setLocationRelativeTo(null);
    }

    /**
     * Randomize questions and update screen
     */
    private void shuffleQuestions() {
        testPanel.shuffle();
        testPanel.repaint();
    }

    /**
     * Parses data file, builds a Test
     * @param pathToDataFile path to data csv file
     */
    private void parseDataFileAndCreateTestOrFail(String pathToDataFile) {
        ArrayList<Question> questions = new ArrayList<>();
        CSVRecord[] rows = null;

        try {
            CSVParser parser = CSVFormat.DEFAULT.parse(new FileReader(pathToDataFile));
            rows = parser.getRecords().toArray(new CSVRecord[parser.getRecords().size()]);
        } catch (Exception e) {
            System.err.println(e.toString());
        }

        for (CSVRecord row : rows) { // each row represent a question
            ArrayList<Answer> answers = new ArrayList<>(); // list of answers
            if (row.size() > 1) {
                for (int i = 1; i < row.size(); i++) {
                    if (row.get(i).length() > 0) {
                        answers.add(new Answer(row.get(i)));
                    }
                }

                Answer correctAnswer = answers.get(0); // the correct
                // answer is always the first one
                String questionText = row.get(0);
                questions.add(
                        new Question(questionText, answers.toArray(new Answer[answers.size()]), correctAnswer)); // add to list of questions
            }
        }
        test = new Test(questions.toArray(new Question[questions.size()]));
    }

    /*
     * Menubar and statusbar
     */

    /**
     * Creates and adds menubar
     */
    private void setupMenubar() {
        setJMenuBar(createMenuBar()); // set menubar
    }

    /**
     * Creates a menu bar for frame
     *
     * @return menu bar for frame
     */
    private JMenuBar createMenuBar() {
        JMenuBar menuBar = new JMenuBar();
        menuBar.add(createFileMenu()); // file
        menuBar.add(createEditMenu()); // edit
        menuBar.add(createHelpMenu()); // help/ about

        return menuBar;
    }

    /**
     * Creates file menu with save/exit options
     *
     * @return file menu
     */
    private JMenu createFileMenu() {
        JMenu menu = new JMenu("File"); // file menu

        JMenuItem item = new JMenuItem("Exit");
        item.addActionListener(e -> System.exit(0));
        menu.add(item);

        return menu;
    }

    /**
     * Creates new edit menu
     *
     * @return edit menu
     */
    private JMenu createEditMenu() {
        JMenu menu = new JMenu("Edit"); // file menu
        JMenuItem item = new JMenuItem("Test submissions seconds wait");
        item.addActionListener(e -> {
            String userInput = JOptionPane.showInputDialog("Test submissions seconds wait",
                    SECONDS_WAIT_BETWEEN_SUBMISSIONS);
            SECONDS_WAIT_BETWEEN_SUBMISSIONS = Integer.parseInt(userInput); // update
        });
        menu.add(item);
        return menu;
    }

    /**
     * Creates new help menu with help/about options
     *
     * @return help menu
     */
    private JMenu createHelpMenu() {
        JMenu menu = new JMenu("Help"); // help menu

        JMenuItem item = new JMenuItem("Help"); // help menu -> help
        item.addActionListener(e -> showHelpDialogOrFail());
        menu.add(item);

        item = new JMenuItem("About"); // help menu -> about
        item.addActionListener(e -> showAboutDialogOrFail());
        menu.add(item);

        return menu;
    }

    /*
     * Panels
     */

    /**
     * Monitor panel with Submit, Pause, Stop buttons
     *
     * @return panel to manage test
     */
    private JPanel createMonitorPanel() {
        JPanel panel = new JPanel(); // monitor panel
        JButton submitButton = new JButton("Submit"); // create buttons
        JButton pauseButton = new JButton("Pause");
        JButton exitButton = new JButton("Exit");

        submitButton.addActionListener(e -> submitTest()); // add listeners
        pauseButton.addActionListener(e -> {
            pauseTest();

            if (isPaused) {
                pauseButton.setText("Resume");
            } else {
                pauseButton.setText("Pause");
            }
        });
        exitButton.addActionListener(e -> exitTest());

        panel.add(submitButton);
        panel.add(pauseButton);
        panel.add(exitButton);
        return panel;
    }

    /**
     * Panel with 2 timers: current submission timer and total test timer
     *
     * @return panel with 2 timers
     */
    private JPanel createTimersPanel() {
        JPanel panel = new JPanel();

        panel.add(currentSubmissionTimer);
        panel.add(totalTestTimer);

        SwingUtils.addTitleBorder(panel, "Timing");
        return panel;
    }

    /*
     * Dialogs
     */

    /**
     * Show a dialog about the app
     */
    private void showAboutDialogOrFail() {
        String content = "";
        try {
            InputStream inputStream = TesterGui.class.getResourceAsStream("/res/strings/about.html");
            content = readAllFromStream(new BufferedReader(new InputStreamReader(inputStream))); // read content of dialog from html
        } catch (Exception e) {
            System.err.println(e.toString());
        }

        String title = "About this app";
        new AboutDialog(this, content, title).setVisible(true);
    }

    /**
     * Show a help dialog about the app
     */
    private void showHelpDialogOrFail() {
        String content = "";
        InputStream inputStream = TesterGui.class.getResourceAsStream("/res/strings/help.html");
        try {
            content = readAllFromStream(new BufferedReader(new InputStreamReader(inputStream))); // read content of dialog from html
        } catch (Exception e) {
            System.err.println(e.toString());
        }

        String title = "Help";
        new AboutDialog(this, content, title).setVisible(true);
    }

    /**
     * Shows dialog with info about successful test submission
     */
    private void showSuccessfulTestSubmissionDialog() {
        String testSummary = test.toString();
        StringBuilder message = new StringBuilder(testSummary + "\n" + "More" + " info below." + "\n");

        for (String testResult : results) {
            message.append("\n").append(testResult).append("\n");
        }

        JTextArea textArea = new JTextArea(message.toString());
        JScrollPane scrollPane = new JScrollPane(textArea);
        scrollPane.setPreferredSize(this.getSize());
        JOptionPane.showMessageDialog(this, scrollPane, "Wonderful! You did it!", JOptionPane.INFORMATION_MESSAGE);
    }

    /**
     * Shows dialog with info about unsuccessful test submission
     */
    private void showUnSuccessfulTestSubmissionDialog() {
        totalTestTimer.start(); // re-start total timer

        String message = test.toString();
        message += "\nDon't worry, be happy: this box will automatically " + "close after "
                + Integer.toString(SECONDS_WAIT_BETWEEN_SUBMISSIONS) + " seconds of your " + "submission.\nEnjoy.";

        JOptionPane opt = new JOptionPane(message, JOptionPane.WARNING_MESSAGE, JOptionPane.DEFAULT_OPTION, null,
                new Object[] {}); // no buttons
        final JDialog dlg = opt.createDialog("Error");
        new Thread(() -> {
            try {
                Thread.sleep(SECONDS_WAIT_BETWEEN_SUBMISSIONS * 1000);
                dlg.dispose();
            } catch (Throwable t) {
                System.err.println(t.toString());
            }
        }).start();
        dlg.setVisible(true);
    }

    /**
     * Exit app nicely
     */
    private void exitApp() {
        System.exit(0);
    }
}