Java tutorial
/* * 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); } }