{"id":"gui-views-practice-app-views","slug":"practice-app-views","title":"A practice app, part 2: the views","text":"Step 6 wrote the capitals trainer's logic: a `CardBox` that stores the cards, and a `PracticeRound` that runs the training and remembers the missed countries. Neither knows that a window exists. This step puts views on top of them.\n\n### The plan for the window\n\n- A BorderPane, with a menu in the top region: an HBox with the buttons `Add cards` and `Train`. The center shows one of two views, each a class with a `getView()` method (step 4).\n- **NewCardView** has a field for the country, one for the capital, the button `Add card` and a label for messages. It's made once, in its constructor, so that what the user typed stays when they visit the training and come back.\n- **TrainingView** shows a country, a field for the answer, the button `Answer`, a label that says whether the answer was right, and the score. It builds its nodes at each call of `getView()`, since the question depends on the cards, and the user may have added some since the last visit.\n- `Main` makes one CardBox and one PracticeRound, and gives both views what they need of them.\n\n\n<figure class=\"uml\"><div class=\"uml-scroll\" tabindex=\"0\" role=\"group\" aria-label=\"Class diagram of Main, NewCardView, TrainingView, CardBox and PracticeRound\">\n<svg class=\"uml-svg\" viewBox=\"0 0 416 518\" width=\"416\" height=\"518\" style=\"width:26rem;min-width:23.84rem;aspect-ratio:416/518\" font-size=\"12\" aria-hidden=\"true\" focusable=\"false\"><path class=\"u-edge\" fill=\"none\" d=\"M104.8 30L104.8 148L6 148L6 416L170.5 416L170.5 440\"/><path class=\"u-edge\" fill=\"none\" d=\"M126.2 30L126.2 148L143 148L143 172\"/><path class=\"u-edge\" fill=\"none\" d=\"M238.5 440L238.5 416L204.5 416L204.5 394\"/><path class=\"u-edge\" fill=\"none\" d=\"M204.5 244L204.5 266L145.3 266L145.3 290\"/><path class=\"u-edge\" fill=\"none\" d=\"M266 172L266 148L254.8 148L254.8 126\"/><path class=\"u-edge\" fill=\"none\" d=\"M332.2 126L332.2 148L403 148L403 266L263.7 266L263.7 290\"/><path class=\"u-edge\" fill=\"none\" d=\"M165 430L170.5 440L176 430\"/><path class=\"u-edge\" fill=\"none\" d=\"M137.5 162L143 172L148.5 162\"/><path class=\"u-edge\" fill=\"none\" d=\"M210 404L204.5 394L199 404\"/><path class=\"u-edge\" fill=\"none\" d=\"M139.8 280L145.3 290L150.8 280\"/><path class=\"u-edge\" fill=\"none\" d=\"M260.3 136L254.8 126L249.3 136\"/><path class=\"u-edge\" fill=\"none\" d=\"M258.2 280L263.7 290L269.2 280\"/><rect class=\"u-bg\" fill=\"none\" x=\"83.5\" y=\"6\" width=\"64\" height=\"24\"/><rect class=\"u-head\" fill=\"none\" x=\"83.5\" y=\"6\" width=\"64\" height=\"24\"/><text x=\"115.5\" y=\"22\" text-anchor=\"middle\" class=\"u-name\">Main</text><rect class=\"u-frame\" fill=\"none\" x=\"83.5\" y=\"6\" width=\"64\" height=\"24\"/><rect class=\"u-bg\" fill=\"none\" x=\"102.5\" y=\"440\" width=\"204\" height=\"72\"/><rect class=\"u-head\" fill=\"none\" x=\"102.5\" y=\"440\" width=\"204\" height=\"24\"/><text x=\"204.5\" y=\"456\" text-anchor=\"middle\" class=\"u-name\">NewCardView</text><text x=\"110.5\" y=\"488\">+NewCardView(box: CardBox)</text><text x=\"110.5\" y=\"504\">+getView(): Parent</text><path class=\"u-sep\" fill=\"none\" d=\"M102.5 464h204M102.5 472h204\"/><rect class=\"u-frame\" fill=\"none\" x=\"102.5\" y=\"440\" width=\"204\" height=\"72\"/><rect class=\"u-bg\" fill=\"none\" x=\"20\" y=\"172\" width=\"369\" height=\"72\"/><rect class=\"u-head\" fill=\"none\" x=\"20\" y=\"172\" width=\"369\" height=\"24\"/><text x=\"204.5\" y=\"188\" text-anchor=\"middle\" class=\"u-name\">TrainingView</text><text x=\"28\" y=\"220\">+TrainingView(box: CardBox, round: PracticeRound)</text><text x=\"28\" y=\"236\">+getView(): Parent</text><path class=\"u-sep\" fill=\"none\" d=\"M20 196h369M20 204h369\"/><rect class=\"u-frame\" fill=\"none\" x=\"20\" y=\"172\" width=\"369\" height=\"72\"/><rect class=\"u-bg\" fill=\"none\" x=\"27\" y=\"290\" width=\"355\" height=\"104\"/><rect class=\"u-head\" fill=\"none\" x=\"27\" y=\"290\" width=\"355\" height=\"24\"/><text x=\"204.5\" y=\"306\" text-anchor=\"middle\" class=\"u-name\">CardBox</text><text x=\"35\" y=\"338\">+add(country: String, capital: String): boolean</text><text x=\"35\" y=\"354\">+capitalOf(country: String): String</text><text x=\"35\" y=\"370\">+size(): int</text><text x=\"35\" y=\"386\">...</text><path class=\"u-sep\" fill=\"none\" d=\"M27 314h355M27 322h355\"/><rect class=\"u-frame\" fill=\"none\" x=\"27\" y=\"290\" width=\"355\" height=\"104\"/><rect class=\"u-bg\" fill=\"none\" x=\"177.5\" y=\"6\" width=\"232\" height=\"120\"/><rect class=\"u-head\" fill=\"none\" x=\"177.5\" y=\"6\" width=\"232\" height=\"24\"/><text x=\"293.5\" y=\"22\" text-anchor=\"middle\" class=\"u-name\">PracticeRound</text><text x=\"185.5\" y=\"54\">+question(): String</text><text x=\"185.5\" y=\"70\">+answer(text: String): boolean</text><text x=\"185.5\" y=\"86\">+getRight(): int</text><text x=\"185.5\" y=\"102\">+getWrong(): int</text><text x=\"185.5\" y=\"118\">...</text><path class=\"u-sep\" fill=\"none\" d=\"M177.5 30h232M177.5 38h232\"/><rect class=\"u-frame\" fill=\"none\" x=\"177.5\" y=\"6\" width=\"232\" height=\"120\"/></svg>\n</div><details class=\"uml-text\"><summary>The diagram as text</summary><ul><li><strong>Main</strong>, a class</li><li><strong>NewCardView</strong>, a class<ul><li>public constructor <code>NewCardView(box: CardBox)</code></li><li>public method <code>getView(): Parent</code></li></ul></li><li><strong>TrainingView</strong>, a class<ul><li>public constructor <code>TrainingView(box: CardBox, round: PracticeRound)</code></li><li>public method <code>getView(): Parent</code></li></ul></li><li><strong>CardBox</strong>, a class<ul><li>public method <code>add(country: String, capital: String): boolean</code></li><li>public method <code>capitalOf(country: String): String</code></li><li>public method <code>size(): int</code></li><li>more members, not shown</li></ul></li><li><strong>PracticeRound</strong>, a class<ul><li>public method <code>question(): String</code></li><li>public method <code>answer(text: String): boolean</code></li><li>public method <code>getRight(): int</code></li><li>public method <code>getWrong(): int</code></li><li>more members, not shown</li></ul></li></ul><p>Connections:</p><ul><li>Each Main has one NewCardView object.</li><li>Each Main has one TrainingView object.</li><li>Each NewCardView has one CardBox object.</li><li>Each TrainingView has one CardBox object.</li><li>Each TrainingView has one PracticeRound object.</li><li>Each PracticeRound has one CardBox object.</li></ul></details></figure>\n\n\n### A first version, with a stand-in\n\nA larger program is easier to build in pieces that each run. The first version has the real NewCardView and a **stand-in** for TrainingView: a class with the right constructor and `getView()`, which only shows a label for now. Everything compiles, the menu works, and the adding of cards can be tried before the training view exists:\n\n```java\nimport javafx.application.Application;\nimport javafx.geometry.Insets;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        CardBox box = new CardBox();\n        PracticeRound round = new PracticeRound(box);\n        NewCardView newCards = new NewCardView(box);\n        TrainingView training = new TrainingView(box, round);\n\n        Button toNewCards = new Button(\"Add cards\");\n        Button toTraining = new Button(\"Train\");\n        HBox menu = new HBox(10, toNewCards, toTraining);\n        menu.setPadding(new Insets(10));\n\n        BorderPane frame = new BorderPane();\n        frame.setTop(menu);\n        frame.setCenter(newCards.getView());\n        toNewCards.setOnAction(event -> frame.setCenter(newCards.getView()));\n        toTraining.setOnAction(event -> frame.setCenter(training.getView()));\n\n        stage.setScene(new Scene(frame));\n        stage.setTitle(\"Capitals\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n// ==== NewCardView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class NewCardView {\n    private CardBox box;\n    private VBox view;\n\n    public NewCardView(CardBox box) {\n        this.box = box;\n        TextField country = new TextField();\n        country.setPromptText(\"Country\");\n        TextField capital = new TextField();\n        capital.setPromptText(\"Capital\");\n        Button add = new Button(\"Add card\");\n        Label message = new Label(\"\");\n        add.setOnAction(event -> {\n            if (this.box.add(country.getText(), capital.getText())) {\n                message.setText(\"Added. Cards in the box: \" + this.box.size());\n                country.clear();\n                capital.clear();\n            } else {\n                message.setText(\"Fill in both fields, and add each country once.\");\n            }\n        });\n        this.view = new VBox(8, country, capital, add, message);\n        this.view.setPadding(new Insets(10));\n    }\n\n    public Parent getView() {\n        return this.view;\n    }\n}\n// ==== TrainingView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Label;\nimport javafx.scene.layout.VBox;\n\npublic class TrainingView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public TrainingView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(8, new Label(\"Training comes in the next version.\"));\n        view.setPadding(new Insets(10));\n        return view;\n    }\n}\n// ==== CardBox.java ====\nimport java.util.ArrayList;\n\npublic class CardBox {\n    private ArrayList<Card> cards;\n\n    public CardBox() {\n        this.cards = new ArrayList<>();\n    }\n\n    public boolean add(String country, String capital) {\n        String name = country.trim();\n        String city = capital.trim();\n        if (name.isEmpty() || city.isEmpty() || this.capitalOf(name) != null) {\n            return false;\n        }\n        this.cards.add(new Card(name, city));\n        return true;\n    }\n\n    public String capitalOf(String country) {\n        for (Card card : this.cards) {\n            if (card.getCountry().equals(country)) {\n                return card.getCapital();\n            }\n        }\n        return null;\n    }\n\n    public String countryAt(int index) {\n        return this.cards.get(index).getCountry();\n    }\n\n    public int size() {\n        return this.cards.size();\n    }\n}\n// ==== Card.java ====\npublic class Card {\n    private String country;\n    private String capital;\n\n    public Card(String country, String capital) {\n        this.country = country;\n        this.capital = capital;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getCapital() {\n        return this.capital;\n    }\n}\n// ==== PracticeRound.java ====\nimport java.util.ArrayList;\n\npublic class PracticeRound {\n    private CardBox box;\n    private int next;\n    private int right;\n    private int wrong;\n    private ArrayList<String> missed;\n\n    public PracticeRound(CardBox box) {\n        this.box = box;\n        this.missed = new ArrayList<>();\n    }\n\n    public String question() {\n        if (this.box.size() == 0) {\n            return null;\n        }\n        return this.box.countryAt(this.next);\n    }\n\n    public boolean answer(String text) {\n        String country = this.question();\n        if (country == null) {\n            return false;\n        }\n        boolean correct = text.trim().equalsIgnoreCase(this.box.capitalOf(country));\n        if (correct) {\n            this.right++;\n        } else {\n            this.wrong++;\n            if (!this.missed.contains(country)) {\n                this.missed.add(country);\n            }\n        }\n        this.next++;\n        if (this.next >= this.box.size()) {\n            this.next = 0;\n        }\n        return correct;\n    }\n\n    public int getRight() {\n        return this.right;\n    }\n\n    public int getWrong() {\n        return this.wrong;\n    }\n\n    public ArrayList<String> missed() {\n        return this.missed;\n    }\n}\n```\n\n```window\n{\"events\":[\"type TextField 1 \\\"Peru\\\"\",\"type TextField 2 \\\"Lima\\\"\",\"click Button \\\"Add card\\\"\",\"type TextField 1 \\\"Kenya\\\"\",\"click Button \\\"Add card\\\"\"],\"window\":{\"windows\":[{\"title\":\"Capitals\",\"scene\":{\"root\":{\"n\":1,\"type\":\"BorderPane\",\"top\":{\"n\":2,\"type\":\"HBox\",\"padding\":[10,10,10,10],\"spacing\":10,\"children\":[{\"n\":3,\"type\":\"Button\",\"text\":\"Add cards\",\"onAction\":true},{\"n\":4,\"type\":\"Button\",\"text\":\"Train\",\"onAction\":true}]},\"center\":{\"n\":5,\"type\":\"VBox\",\"padding\":[10,10,10,10],\"spacing\":8,\"children\":[{\"n\":6,\"type\":\"TextField\",\"text\":\"Kenya\",\"promptText\":\"Country\"},{\"n\":7,\"type\":\"TextField\",\"text\":\"\",\"promptText\":\"Capital\"},{\"n\":8,\"type\":\"Button\",\"text\":\"Add card\",\"onAction\":true},{\"n\":9,\"type\":\"Label\",\"text\":\"Fill in both fields, and add each country once.\"}]}}}}],\"problems\":[]},\"outline\":\"Window \\\"Capitals\\\"\\n  BorderPane\\n    top: HBox spacing 10, padding 10\\n      Button \\\"Add cards\\\"\\n      Button \\\"Train\\\"\\n    center: VBox spacing 8, padding 10\\n      TextField \\\"Kenya\\\", prompt \\\"Country\\\"\\n      TextField \\\"\\\", prompt \\\"Capital\\\"\\n      Button \\\"Add card\\\"\\n      Label \\\"Fill in both fields, and add each country once.\\\"\"}\n```\n\n- NewCardView's handler forwards both texts to `box.add` and lets the box decide. On `true` it says how many cards there are and empties the fields for the next card; on `false` it explains what the box refuses. The rule itself stays in CardBox.\n- Kenya wasn't added, since its capital was missing, and the field still holds `Kenya`, so the user only needs to type the capital.\n- The stand-in TrainingView already takes the box and the round, as the real one will, so `Main` won't need to change when it's replaced.\n\n### The training view\n\nTrainingView's `getView()` builds a new VBox at each call. When the box is empty, there is nothing to train, and the view holds only a label that says so. Otherwise it holds the question, the answer field, the Answer button, the feedback label and the score.\n\nAnswer's handler must be careful about order. `round.answer(...)` moves the turn on to the next card, so the country that was asked, and its capital for the feedback, have to be read **before** calling it. After it, the question label shows the next country, the field is emptied for the next answer, and the score is updated.\n","task":"Replace the stand-in. Write `TrainingView` in `TrainingView.java`; everything else is ready, and `PracticeRound` is step 6's, with `missed()`. `getView()` returns a VBox with the spacing 8 and the padding 10 on every side:\n\n- when the box is empty, it holds only the label `Add some cards first.`\n- otherwise it holds, in order: the label `Capital of Peru?` (with the country of `round.question()`), a text field with the prompt text `Capital`, the button `Answer`, an empty label for feedback, and the label `Right 0, wrong 0` (with the round's counts)\n\n**Answer** answers with the field's text, and then:\n\n- the feedback label says `Yes, Lima.` for a right answer, or `No, it's Lima.` for a wrong one (with the capital of the country that was asked)\n- the question label shows the next question, the field is emptied, and the score label shows the new counts\n\nThe task card shows the window after adding Peru and Kenya, clicking Train and answering `lima`.\n","kind":"code","seed":"// ==== TrainingView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class TrainingView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public TrainingView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(8, new Label(\"Training comes in the next version.\"));\n        view.setPadding(new Insets(10));\n        return view;\n    }\n}\n\n// ==== Main.java ====\nimport javafx.application.Application;\nimport javafx.geometry.Insets;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        CardBox box = new CardBox();\n        PracticeRound round = new PracticeRound(box);\n        NewCardView newCards = new NewCardView(box);\n        TrainingView training = new TrainingView(box, round);\n\n        Button toNewCards = new Button(\"Add cards\");\n        Button toTraining = new Button(\"Train\");\n        HBox menu = new HBox(10, toNewCards, toTraining);\n        menu.setPadding(new Insets(10));\n\n        BorderPane frame = new BorderPane();\n        frame.setTop(menu);\n        frame.setCenter(newCards.getView());\n        toNewCards.setOnAction(event -> frame.setCenter(newCards.getView()));\n        toTraining.setOnAction(event -> frame.setCenter(training.getView()));\n\n        stage.setScene(new Scene(frame));\n        stage.setTitle(\"Capitals\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n\n// ==== NewCardView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class NewCardView {\n    private CardBox box;\n    private VBox view;\n\n    public NewCardView(CardBox box) {\n        this.box = box;\n        TextField country = new TextField();\n        country.setPromptText(\"Country\");\n        TextField capital = new TextField();\n        capital.setPromptText(\"Capital\");\n        Button add = new Button(\"Add card\");\n        Label message = new Label(\"\");\n        add.setOnAction(event -> {\n            if (this.box.add(country.getText(), capital.getText())) {\n                message.setText(\"Added. Cards in the box: \" + this.box.size());\n                country.clear();\n                capital.clear();\n            } else {\n                message.setText(\"Fill in both fields, and add each country once.\");\n            }\n        });\n        this.view = new VBox(8, country, capital, add, message);\n        this.view.setPadding(new Insets(10));\n    }\n\n    public Parent getView() {\n        return this.view;\n    }\n}\n\n// ==== CardBox.java ====\nimport java.util.ArrayList;\n\npublic class CardBox {\n    private ArrayList<Card> cards;\n\n    public CardBox() {\n        this.cards = new ArrayList<>();\n    }\n\n    public boolean add(String country, String capital) {\n        String name = country.trim();\n        String city = capital.trim();\n        if (name.isEmpty() || city.isEmpty() || this.capitalOf(name) != null) {\n            return false;\n        }\n        this.cards.add(new Card(name, city));\n        return true;\n    }\n\n    public String capitalOf(String country) {\n        for (Card card : this.cards) {\n            if (card.getCountry().equals(country)) {\n                return card.getCapital();\n            }\n        }\n        return null;\n    }\n\n    public String countryAt(int index) {\n        return this.cards.get(index).getCountry();\n    }\n\n    public int size() {\n        return this.cards.size();\n    }\n}\n\n// ==== Card.java ====\npublic class Card {\n    private String country;\n    private String capital;\n\n    public Card(String country, String capital) {\n        this.country = country;\n        this.capital = capital;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getCapital() {\n        return this.capital;\n    }\n}\n\n// ==== PracticeRound.java ====\nimport java.util.ArrayList;\n\npublic class PracticeRound {\n    private CardBox box;\n    private int next;\n    private int right;\n    private int wrong;\n    private ArrayList<String> missed;\n\n    public PracticeRound(CardBox box) {\n        this.box = box;\n        this.missed = new ArrayList<>();\n    }\n\n    public String question() {\n        if (this.box.size() == 0) {\n            return null;\n        }\n        return this.box.countryAt(this.next);\n    }\n\n    public boolean answer(String text) {\n        String country = this.question();\n        if (country == null) {\n            return false;\n        }\n        boolean correct = text.trim().equalsIgnoreCase(this.box.capitalOf(country));\n        if (correct) {\n            this.right++;\n        } else {\n            this.wrong++;\n            if (!this.missed.contains(country)) {\n                this.missed.add(country);\n            }\n        }\n        this.next++;\n        if (this.next >= this.box.size()) {\n            this.next = 0;\n        }\n        return correct;\n    }\n\n    public int getRight() {\n        return this.right;\n    }\n\n    public int getWrong() {\n        return this.wrong;\n    }\n\n    public ArrayList<String> missed() {\n        return this.missed;\n    }\n}\n","solution":"// ==== TrainingView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class TrainingView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public TrainingView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(8);\n        view.setPadding(new Insets(10));\n        if (this.round.question() == null) {\n            view.getChildren().add(new Label(\"Add some cards first.\"));\n            return view;\n        }\n        Label question = new Label(\"Capital of \" + this.round.question() + \"?\");\n        TextField answer = new TextField();\n        answer.setPromptText(\"Capital\");\n        Button check = new Button(\"Answer\");\n        Label feedback = new Label(\"\");\n        Label score = new Label(this.scoreText());\n        check.setOnAction(event -> {\n            String country = this.round.question();\n            String capital = this.box.capitalOf(country);\n            if (this.round.answer(answer.getText())) {\n                feedback.setText(\"Yes, \" + capital + \".\");\n            } else {\n                feedback.setText(\"No, it's \" + capital + \".\");\n            }\n            question.setText(\"Capital of \" + this.round.question() + \"?\");\n            answer.clear();\n            score.setText(this.scoreText());\n        });\n        view.getChildren().addAll(question, answer, check, feedback, score);\n        return view;\n    }\n\n    private String scoreText() {\n        return \"Right \" + this.round.getRight() + \", wrong \" + this.round.getWrong();\n    }\n}\n\n// ==== Main.java ====\nimport javafx.application.Application;\nimport javafx.geometry.Insets;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        CardBox box = new CardBox();\n        PracticeRound round = new PracticeRound(box);\n        NewCardView newCards = new NewCardView(box);\n        TrainingView training = new TrainingView(box, round);\n\n        Button toNewCards = new Button(\"Add cards\");\n        Button toTraining = new Button(\"Train\");\n        HBox menu = new HBox(10, toNewCards, toTraining);\n        menu.setPadding(new Insets(10));\n\n        BorderPane frame = new BorderPane();\n        frame.setTop(menu);\n        frame.setCenter(newCards.getView());\n        toNewCards.setOnAction(event -> frame.setCenter(newCards.getView()));\n        toTraining.setOnAction(event -> frame.setCenter(training.getView()));\n\n        stage.setScene(new Scene(frame));\n        stage.setTitle(\"Capitals\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n\n// ==== NewCardView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class NewCardView {\n    private CardBox box;\n    private VBox view;\n\n    public NewCardView(CardBox box) {\n        this.box = box;\n        TextField country = new TextField();\n        country.setPromptText(\"Country\");\n        TextField capital = new TextField();\n        capital.setPromptText(\"Capital\");\n        Button add = new Button(\"Add card\");\n        Label message = new Label(\"\");\n        add.setOnAction(event -> {\n            if (this.box.add(country.getText(), capital.getText())) {\n                message.setText(\"Added. Cards in the box: \" + this.box.size());\n                country.clear();\n                capital.clear();\n            } else {\n                message.setText(\"Fill in both fields, and add each country once.\");\n            }\n        });\n        this.view = new VBox(8, country, capital, add, message);\n        this.view.setPadding(new Insets(10));\n    }\n\n    public Parent getView() {\n        return this.view;\n    }\n}\n\n// ==== CardBox.java ====\nimport java.util.ArrayList;\n\npublic class CardBox {\n    private ArrayList<Card> cards;\n\n    public CardBox() {\n        this.cards = new ArrayList<>();\n    }\n\n    public boolean add(String country, String capital) {\n        String name = country.trim();\n        String city = capital.trim();\n        if (name.isEmpty() || city.isEmpty() || this.capitalOf(name) != null) {\n            return false;\n        }\n        this.cards.add(new Card(name, city));\n        return true;\n    }\n\n    public String capitalOf(String country) {\n        for (Card card : this.cards) {\n            if (card.getCountry().equals(country)) {\n                return card.getCapital();\n            }\n        }\n        return null;\n    }\n\n    public String countryAt(int index) {\n        return this.cards.get(index).getCountry();\n    }\n\n    public int size() {\n        return this.cards.size();\n    }\n}\n\n// ==== Card.java ====\npublic class Card {\n    private String country;\n    private String capital;\n\n    public Card(String country, String capital) {\n        this.country = country;\n        this.capital = capital;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getCapital() {\n        return this.capital;\n    }\n}\n\n// ==== PracticeRound.java ====\nimport java.util.ArrayList;\n\npublic class PracticeRound {\n    private CardBox box;\n    private int next;\n    private int right;\n    private int wrong;\n    private ArrayList<String> missed;\n\n    public PracticeRound(CardBox box) {\n        this.box = box;\n        this.missed = new ArrayList<>();\n    }\n\n    public String question() {\n        if (this.box.size() == 0) {\n            return null;\n        }\n        return this.box.countryAt(this.next);\n    }\n\n    public boolean answer(String text) {\n        String country = this.question();\n        if (country == null) {\n            return false;\n        }\n        boolean correct = text.trim().equalsIgnoreCase(this.box.capitalOf(country));\n        if (correct) {\n            this.right++;\n        } else {\n            this.wrong++;\n            if (!this.missed.contains(country)) {\n                this.missed.add(country);\n            }\n        }\n        this.next++;\n        if (this.next >= this.box.size()) {\n            this.next = 0;\n        }\n        return correct;\n    }\n\n    public int getRight() {\n        return this.right;\n    }\n\n    public int getWrong() {\n        return this.wrong;\n    }\n\n    public ArrayList<String> missed() {\n        return this.missed;\n    }\n}\n","hints":["Start `getView()` with `VBox view = new VBox(8);` and `view.setPadding(new Insets(10));`. If `this.round.question() == null`, add the label `Add some cards first.` and return the view. Otherwise make the five nodes and add them with `view.getChildren().addAll(...)`.","In Answer's handler, first `String country = this.round.question();` and `String capital = this.box.capitalOf(country);`. Then `if (this.round.answer(answer.getText()))` chooses the feedback, and after that come the question label, `answer.clear()` and the score."],"tests":[{"name":"Test 1","stdin":"","expect":"","hidden":false,"events":["type TextField 1 \"Peru\"","type TextField 2 \"Lima\"","click Button \"Add card\"","type TextField 1 \"Kenya\"","type TextField 2 \"Nairobi\"","click Button \"Add card\"","click Button \"Train\"","type TextField 1 \"lima\"","click Button \"Answer\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Capital of Kenya?"},{"n":7,"type":"TextField","text":"","promptText":"Capital"},{"n":8,"type":"Button","text":"Answer","onAction":true},{"n":9,"type":"Label","text":"Yes, Lima."},{"n":10,"type":"Label","text":"Right 1, wrong 0"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Capital of Kenya?\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Answer\"\n      Label \"Yes, Lima.\"\n      Label \"Right 1, wrong 0\""},{"name":"Test 2","stdin":"","expect":"","hidden":true,"events":["click Button \"Train\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Add some cards first."}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Add some cards first.\""},{"name":"Test 3","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Japan\"","type TextField 2 \"Tokyo\"","click Button \"Add card\"","click Button \"Train\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Capital of Japan?"},{"n":7,"type":"TextField","text":"","promptText":"Capital"},{"n":8,"type":"Button","text":"Answer","onAction":true},{"n":9,"type":"Label","text":""},{"n":10,"type":"Label","text":"Right 0, wrong 0"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Capital of Japan?\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Answer\"\n      Label \"\"\n      Label \"Right 0, wrong 0\""},{"name":"Test 4","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Japan\"","type TextField 2 \"Tokyo\"","click Button \"Add card\"","click Button \"Train\"","type TextField 1 \"Kyoto\"","click Button \"Answer\"","type TextField 1 \"tokyo\"","click Button \"Answer\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Capital of Japan?"},{"n":7,"type":"TextField","text":"","promptText":"Capital"},{"n":8,"type":"Button","text":"Answer","onAction":true},{"n":9,"type":"Label","text":"Yes, Tokyo."},{"n":10,"type":"Label","text":"Right 1, wrong 1"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Capital of Japan?\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Answer\"\n      Label \"Yes, Tokyo.\"\n      Label \"Right 1, wrong 1\""},{"name":"Test 5","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Chile\"","type TextField 2 \"Santiago\"","click Button \"Add card\"","type TextField 1 \"Egypt\"","type TextField 2 \"Cairo\"","click Button \"Add card\"","click Button \"Train\"","type TextField 1 \"Valparaiso\"","click Button \"Answer\"","click Button \"Add cards\"","type TextField 1 \"Ghana\"","type TextField 2 \"Accra\"","click Button \"Add card\"","click Button \"Train\"","type TextField 1 \"Cairo\"","click Button \"Answer\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Capital of Ghana?"},{"n":7,"type":"TextField","text":"","promptText":"Capital"},{"n":8,"type":"Button","text":"Answer","onAction":true},{"n":9,"type":"Label","text":"Yes, Cairo."},{"n":10,"type":"Label","text":"Right 1, wrong 1"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Capital of Ghana?\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Answer\"\n      Label \"Yes, Cairo.\"\n      Label \"Right 1, wrong 1\""}],"require":[],"forbid":[],"more":[{"task":"The trainer gets a third view: the countries to practice again. Write the class `MissedView` in `MissedView.java`, and add it to the menu in `Main`:\n\n- a constructor `MissedView(CardBox box, PracticeRound round)`\n- `getView()` builds a new VBox at each call, with the spacing 4 and the padding 10 on every side. When `round.missed()` is empty, it holds only the label `Nothing missed so far.` Otherwise it holds the label `Practice these again:` and then a label for each missed country, in the order of `missed()`, like `Peru: Lima` (the country and its capital).\n- in `Main`, a third button `Missed`, after `Train` in the menu, puts the missed view in the center\n\nThe other classes are ready. The task card shows the window after adding Peru and Kenya, answering `Cusco` and `Nairobi`, and clicking Missed.\n","kind":"code","seed":"// ==== MissedView.java ====\npublic class MissedView {\n\n}\n\n// ==== Main.java ====\nimport javafx.application.Application;\nimport javafx.geometry.Insets;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        CardBox box = new CardBox();\n        PracticeRound round = new PracticeRound(box);\n        NewCardView newCards = new NewCardView(box);\n        TrainingView training = new TrainingView(box, round);\n\n        Button toNewCards = new Button(\"Add cards\");\n        Button toTraining = new Button(\"Train\");\n        HBox menu = new HBox(10, toNewCards, toTraining);\n        menu.setPadding(new Insets(10));\n\n        BorderPane frame = new BorderPane();\n        frame.setTop(menu);\n        frame.setCenter(newCards.getView());\n        toNewCards.setOnAction(event -> frame.setCenter(newCards.getView()));\n        toTraining.setOnAction(event -> frame.setCenter(training.getView()));\n\n        stage.setScene(new Scene(frame));\n        stage.setTitle(\"Capitals\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n\n// ==== TrainingView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class TrainingView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public TrainingView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(8);\n        view.setPadding(new Insets(10));\n        if (this.round.question() == null) {\n            view.getChildren().add(new Label(\"Add some cards first.\"));\n            return view;\n        }\n        Label question = new Label(\"Capital of \" + this.round.question() + \"?\");\n        TextField answer = new TextField();\n        answer.setPromptText(\"Capital\");\n        Button check = new Button(\"Answer\");\n        Label feedback = new Label(\"\");\n        Label score = new Label(this.scoreText());\n        check.setOnAction(event -> {\n            String country = this.round.question();\n            String capital = this.box.capitalOf(country);\n            if (this.round.answer(answer.getText())) {\n                feedback.setText(\"Yes, \" + capital + \".\");\n            } else {\n                feedback.setText(\"No, it's \" + capital + \".\");\n            }\n            question.setText(\"Capital of \" + this.round.question() + \"?\");\n            answer.clear();\n            score.setText(this.scoreText());\n        });\n        view.getChildren().addAll(question, answer, check, feedback, score);\n        return view;\n    }\n\n    private String scoreText() {\n        return \"Right \" + this.round.getRight() + \", wrong \" + this.round.getWrong();\n    }\n}\n\n// ==== NewCardView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class NewCardView {\n    private CardBox box;\n    private VBox view;\n\n    public NewCardView(CardBox box) {\n        this.box = box;\n        TextField country = new TextField();\n        country.setPromptText(\"Country\");\n        TextField capital = new TextField();\n        capital.setPromptText(\"Capital\");\n        Button add = new Button(\"Add card\");\n        Label message = new Label(\"\");\n        add.setOnAction(event -> {\n            if (this.box.add(country.getText(), capital.getText())) {\n                message.setText(\"Added. Cards in the box: \" + this.box.size());\n                country.clear();\n                capital.clear();\n            } else {\n                message.setText(\"Fill in both fields, and add each country once.\");\n            }\n        });\n        this.view = new VBox(8, country, capital, add, message);\n        this.view.setPadding(new Insets(10));\n    }\n\n    public Parent getView() {\n        return this.view;\n    }\n}\n\n// ==== CardBox.java ====\nimport java.util.ArrayList;\n\npublic class CardBox {\n    private ArrayList<Card> cards;\n\n    public CardBox() {\n        this.cards = new ArrayList<>();\n    }\n\n    public boolean add(String country, String capital) {\n        String name = country.trim();\n        String city = capital.trim();\n        if (name.isEmpty() || city.isEmpty() || this.capitalOf(name) != null) {\n            return false;\n        }\n        this.cards.add(new Card(name, city));\n        return true;\n    }\n\n    public String capitalOf(String country) {\n        for (Card card : this.cards) {\n            if (card.getCountry().equals(country)) {\n                return card.getCapital();\n            }\n        }\n        return null;\n    }\n\n    public String countryAt(int index) {\n        return this.cards.get(index).getCountry();\n    }\n\n    public int size() {\n        return this.cards.size();\n    }\n}\n\n// ==== Card.java ====\npublic class Card {\n    private String country;\n    private String capital;\n\n    public Card(String country, String capital) {\n        this.country = country;\n        this.capital = capital;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getCapital() {\n        return this.capital;\n    }\n}\n\n// ==== PracticeRound.java ====\nimport java.util.ArrayList;\n\npublic class PracticeRound {\n    private CardBox box;\n    private int next;\n    private int right;\n    private int wrong;\n    private ArrayList<String> missed;\n\n    public PracticeRound(CardBox box) {\n        this.box = box;\n        this.missed = new ArrayList<>();\n    }\n\n    public String question() {\n        if (this.box.size() == 0) {\n            return null;\n        }\n        return this.box.countryAt(this.next);\n    }\n\n    public boolean answer(String text) {\n        String country = this.question();\n        if (country == null) {\n            return false;\n        }\n        boolean correct = text.trim().equalsIgnoreCase(this.box.capitalOf(country));\n        if (correct) {\n            this.right++;\n        } else {\n            this.wrong++;\n            if (!this.missed.contains(country)) {\n                this.missed.add(country);\n            }\n        }\n        this.next++;\n        if (this.next >= this.box.size()) {\n            this.next = 0;\n        }\n        return correct;\n    }\n\n    public int getRight() {\n        return this.right;\n    }\n\n    public int getWrong() {\n        return this.wrong;\n    }\n\n    public ArrayList<String> missed() {\n        return this.missed;\n    }\n}\n","solution":"// ==== MissedView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Label;\nimport javafx.scene.layout.VBox;\n\npublic class MissedView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public MissedView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(4);\n        view.setPadding(new Insets(10));\n        if (this.round.missed().isEmpty()) {\n            view.getChildren().add(new Label(\"Nothing missed so far.\"));\n            return view;\n        }\n        view.getChildren().add(new Label(\"Practice these again:\"));\n        for (String country : this.round.missed()) {\n            view.getChildren().add(new Label(country + \": \" + this.box.capitalOf(country)));\n        }\n        return view;\n    }\n}\n\n// ==== Main.java ====\nimport javafx.application.Application;\nimport javafx.geometry.Insets;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        CardBox box = new CardBox();\n        PracticeRound round = new PracticeRound(box);\n        NewCardView newCards = new NewCardView(box);\n        TrainingView training = new TrainingView(box, round);\n        MissedView missed = new MissedView(box, round);\n\n        Button toNewCards = new Button(\"Add cards\");\n        Button toTraining = new Button(\"Train\");\n        Button toMissed = new Button(\"Missed\");\n        HBox menu = new HBox(10, toNewCards, toTraining, toMissed);\n        menu.setPadding(new Insets(10));\n\n        BorderPane frame = new BorderPane();\n        frame.setTop(menu);\n        frame.setCenter(newCards.getView());\n        toNewCards.setOnAction(event -> frame.setCenter(newCards.getView()));\n        toTraining.setOnAction(event -> frame.setCenter(training.getView()));\n        toMissed.setOnAction(event -> frame.setCenter(missed.getView()));\n\n        stage.setScene(new Scene(frame));\n        stage.setTitle(\"Capitals\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n\n// ==== TrainingView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class TrainingView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public TrainingView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(8);\n        view.setPadding(new Insets(10));\n        if (this.round.question() == null) {\n            view.getChildren().add(new Label(\"Add some cards first.\"));\n            return view;\n        }\n        Label question = new Label(\"Capital of \" + this.round.question() + \"?\");\n        TextField answer = new TextField();\n        answer.setPromptText(\"Capital\");\n        Button check = new Button(\"Answer\");\n        Label feedback = new Label(\"\");\n        Label score = new Label(this.scoreText());\n        check.setOnAction(event -> {\n            String country = this.round.question();\n            String capital = this.box.capitalOf(country);\n            if (this.round.answer(answer.getText())) {\n                feedback.setText(\"Yes, \" + capital + \".\");\n            } else {\n                feedback.setText(\"No, it's \" + capital + \".\");\n            }\n            question.setText(\"Capital of \" + this.round.question() + \"?\");\n            answer.clear();\n            score.setText(this.scoreText());\n        });\n        view.getChildren().addAll(question, answer, check, feedback, score);\n        return view;\n    }\n\n    private String scoreText() {\n        return \"Right \" + this.round.getRight() + \", wrong \" + this.round.getWrong();\n    }\n}\n\n// ==== NewCardView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class NewCardView {\n    private CardBox box;\n    private VBox view;\n\n    public NewCardView(CardBox box) {\n        this.box = box;\n        TextField country = new TextField();\n        country.setPromptText(\"Country\");\n        TextField capital = new TextField();\n        capital.setPromptText(\"Capital\");\n        Button add = new Button(\"Add card\");\n        Label message = new Label(\"\");\n        add.setOnAction(event -> {\n            if (this.box.add(country.getText(), capital.getText())) {\n                message.setText(\"Added. Cards in the box: \" + this.box.size());\n                country.clear();\n                capital.clear();\n            } else {\n                message.setText(\"Fill in both fields, and add each country once.\");\n            }\n        });\n        this.view = new VBox(8, country, capital, add, message);\n        this.view.setPadding(new Insets(10));\n    }\n\n    public Parent getView() {\n        return this.view;\n    }\n}\n\n// ==== CardBox.java ====\nimport java.util.ArrayList;\n\npublic class CardBox {\n    private ArrayList<Card> cards;\n\n    public CardBox() {\n        this.cards = new ArrayList<>();\n    }\n\n    public boolean add(String country, String capital) {\n        String name = country.trim();\n        String city = capital.trim();\n        if (name.isEmpty() || city.isEmpty() || this.capitalOf(name) != null) {\n            return false;\n        }\n        this.cards.add(new Card(name, city));\n        return true;\n    }\n\n    public String capitalOf(String country) {\n        for (Card card : this.cards) {\n            if (card.getCountry().equals(country)) {\n                return card.getCapital();\n            }\n        }\n        return null;\n    }\n\n    public String countryAt(int index) {\n        return this.cards.get(index).getCountry();\n    }\n\n    public int size() {\n        return this.cards.size();\n    }\n}\n\n// ==== Card.java ====\npublic class Card {\n    private String country;\n    private String capital;\n\n    public Card(String country, String capital) {\n        this.country = country;\n        this.capital = capital;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getCapital() {\n        return this.capital;\n    }\n}\n\n// ==== PracticeRound.java ====\nimport java.util.ArrayList;\n\npublic class PracticeRound {\n    private CardBox box;\n    private int next;\n    private int right;\n    private int wrong;\n    private ArrayList<String> missed;\n\n    public PracticeRound(CardBox box) {\n        this.box = box;\n        this.missed = new ArrayList<>();\n    }\n\n    public String question() {\n        if (this.box.size() == 0) {\n            return null;\n        }\n        return this.box.countryAt(this.next);\n    }\n\n    public boolean answer(String text) {\n        String country = this.question();\n        if (country == null) {\n            return false;\n        }\n        boolean correct = text.trim().equalsIgnoreCase(this.box.capitalOf(country));\n        if (correct) {\n            this.right++;\n        } else {\n            this.wrong++;\n            if (!this.missed.contains(country)) {\n                this.missed.add(country);\n            }\n        }\n        this.next++;\n        if (this.next >= this.box.size()) {\n            this.next = 0;\n        }\n        return correct;\n    }\n\n    public int getRight() {\n        return this.right;\n    }\n\n    public int getWrong() {\n        return this.wrong;\n    }\n\n    public ArrayList<String> missed() {\n        return this.missed;\n    }\n}\n","hints":["MissedView keeps the box and the round in instance variables. `getView()` makes `new VBox(4)` with `setPadding(new Insets(10))`, and checks `this.round.missed().isEmpty()` to choose between the one label and the list.","For the list, a for-each loop over `this.round.missed()` adds `new Label(country + \": \" + this.box.capitalOf(country))`. In `Main`, make `new MissedView(box, round)` and a third button, put the button in the HBox, and give it a handler like the other two."],"tests":[{"name":"Test 1","stdin":"","expect":"","hidden":false,"events":["type TextField 1 \"Peru\"","type TextField 2 \"Lima\"","click Button \"Add card\"","type TextField 1 \"Kenya\"","type TextField 2 \"Nairobi\"","click Button \"Add card\"","click Button \"Train\"","type TextField 1 \"Cusco\"","click Button \"Answer\"","type TextField 1 \"Nairobi\"","click Button \"Answer\"","click Button \"Missed\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true},{"n":5,"type":"Button","text":"Missed","onAction":true}]},"center":{"n":6,"type":"VBox","padding":[10,10,10,10],"spacing":4,"children":[{"n":7,"type":"Label","text":"Practice these again:"},{"n":8,"type":"Label","text":"Peru: Lima"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n      Button \"Missed\"\n    center: VBox spacing 4, padding 10\n      Label \"Practice these again:\"\n      Label \"Peru: Lima\""},{"name":"Test 2","stdin":"","expect":"","hidden":true,"events":["click Button \"Missed\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true},{"n":5,"type":"Button","text":"Missed","onAction":true}]},"center":{"n":6,"type":"VBox","padding":[10,10,10,10],"spacing":4,"children":[{"n":7,"type":"Label","text":"Nothing missed so far."}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n      Button \"Missed\"\n    center: VBox spacing 4, padding 10\n      Label \"Nothing missed so far.\""},{"name":"Test 3","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Japan\"","type TextField 2 \"Tokyo\"","click Button \"Add card\"","type TextField 1 \"Chile\"","type TextField 2 \"Santiago\"","click Button \"Add card\"","click Button \"Train\"","type TextField 1 \"Tokyo\"","click Button \"Answer\"","click Button \"Missed\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true},{"n":5,"type":"Button","text":"Missed","onAction":true}]},"center":{"n":6,"type":"VBox","padding":[10,10,10,10],"spacing":4,"children":[{"n":7,"type":"Label","text":"Nothing missed so far."}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n      Button \"Missed\"\n    center: VBox spacing 4, padding 10\n      Label \"Nothing missed so far.\""},{"name":"Test 4","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Japan\"","type TextField 2 \"Tokyo\"","click Button \"Add card\"","type TextField 1 \"Chile\"","type TextField 2 \"Santiago\"","click Button \"Add card\"","click Button \"Train\"","type TextField 1 \"Osaka\"","click Button \"Answer\"","type TextField 1 \"Lima\"","click Button \"Answer\"","type TextField 1 \"Kyoto\"","click Button \"Answer\"","click Button \"Missed\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true},{"n":5,"type":"Button","text":"Missed","onAction":true}]},"center":{"n":6,"type":"VBox","padding":[10,10,10,10],"spacing":4,"children":[{"n":7,"type":"Label","text":"Practice these again:"},{"n":8,"type":"Label","text":"Japan: Tokyo"},{"n":9,"type":"Label","text":"Chile: Santiago"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n      Button \"Missed\"\n    center: VBox spacing 4, padding 10\n      Label \"Practice these again:\"\n      Label \"Japan: Tokyo\"\n      Label \"Chile: Santiago\""}],"require":[],"forbid":[]},{"task":"A text field has an action too: `setOnAction` on a TextField gives it a handler that runs when the user presses Enter in it. Typing an answer and then reaching for the mouse is slow, so make Enter work:\n\n- in NewCardView, Enter in the capital field adds the card, exactly as a click on `Add card` does\n- in TrainingView, Enter in the answer field answers, exactly as a click on `Answer` does\n\nA button's `fire()` runs its handler, so neither handler needs to be written twice. Enter in the country field still does nothing. Nothing else changes. The task card shows the window after adding Peru and Kenya with Enter, clicking Train, and answering `Lima` with Enter.\n","kind":"code","seed":"// ==== NewCardView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class NewCardView {\n    private CardBox box;\n    private VBox view;\n\n    public NewCardView(CardBox box) {\n        this.box = box;\n        TextField country = new TextField();\n        country.setPromptText(\"Country\");\n        TextField capital = new TextField();\n        capital.setPromptText(\"Capital\");\n        Button add = new Button(\"Add card\");\n        Label message = new Label(\"\");\n        add.setOnAction(event -> {\n            if (this.box.add(country.getText(), capital.getText())) {\n                message.setText(\"Added. Cards in the box: \" + this.box.size());\n                country.clear();\n                capital.clear();\n            } else {\n                message.setText(\"Fill in both fields, and add each country once.\");\n            }\n        });\n        this.view = new VBox(8, country, capital, add, message);\n        this.view.setPadding(new Insets(10));\n    }\n\n    public Parent getView() {\n        return this.view;\n    }\n}\n\n// ==== TrainingView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class TrainingView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public TrainingView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(8);\n        view.setPadding(new Insets(10));\n        if (this.round.question() == null) {\n            view.getChildren().add(new Label(\"Add some cards first.\"));\n            return view;\n        }\n        Label question = new Label(\"Capital of \" + this.round.question() + \"?\");\n        TextField answer = new TextField();\n        answer.setPromptText(\"Capital\");\n        Button check = new Button(\"Answer\");\n        Label feedback = new Label(\"\");\n        Label score = new Label(this.scoreText());\n        check.setOnAction(event -> {\n            String country = this.round.question();\n            String capital = this.box.capitalOf(country);\n            if (this.round.answer(answer.getText())) {\n                feedback.setText(\"Yes, \" + capital + \".\");\n            } else {\n                feedback.setText(\"No, it's \" + capital + \".\");\n            }\n            question.setText(\"Capital of \" + this.round.question() + \"?\");\n            answer.clear();\n            score.setText(this.scoreText());\n        });\n        view.getChildren().addAll(question, answer, check, feedback, score);\n        return view;\n    }\n\n    private String scoreText() {\n        return \"Right \" + this.round.getRight() + \", wrong \" + this.round.getWrong();\n    }\n}\n\n// ==== Main.java ====\nimport javafx.application.Application;\nimport javafx.geometry.Insets;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        CardBox box = new CardBox();\n        PracticeRound round = new PracticeRound(box);\n        NewCardView newCards = new NewCardView(box);\n        TrainingView training = new TrainingView(box, round);\n\n        Button toNewCards = new Button(\"Add cards\");\n        Button toTraining = new Button(\"Train\");\n        HBox menu = new HBox(10, toNewCards, toTraining);\n        menu.setPadding(new Insets(10));\n\n        BorderPane frame = new BorderPane();\n        frame.setTop(menu);\n        frame.setCenter(newCards.getView());\n        toNewCards.setOnAction(event -> frame.setCenter(newCards.getView()));\n        toTraining.setOnAction(event -> frame.setCenter(training.getView()));\n\n        stage.setScene(new Scene(frame));\n        stage.setTitle(\"Capitals\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n\n// ==== CardBox.java ====\nimport java.util.ArrayList;\n\npublic class CardBox {\n    private ArrayList<Card> cards;\n\n    public CardBox() {\n        this.cards = new ArrayList<>();\n    }\n\n    public boolean add(String country, String capital) {\n        String name = country.trim();\n        String city = capital.trim();\n        if (name.isEmpty() || city.isEmpty() || this.capitalOf(name) != null) {\n            return false;\n        }\n        this.cards.add(new Card(name, city));\n        return true;\n    }\n\n    public String capitalOf(String country) {\n        for (Card card : this.cards) {\n            if (card.getCountry().equals(country)) {\n                return card.getCapital();\n            }\n        }\n        return null;\n    }\n\n    public String countryAt(int index) {\n        return this.cards.get(index).getCountry();\n    }\n\n    public int size() {\n        return this.cards.size();\n    }\n}\n\n// ==== Card.java ====\npublic class Card {\n    private String country;\n    private String capital;\n\n    public Card(String country, String capital) {\n        this.country = country;\n        this.capital = capital;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getCapital() {\n        return this.capital;\n    }\n}\n\n// ==== PracticeRound.java ====\nimport java.util.ArrayList;\n\npublic class PracticeRound {\n    private CardBox box;\n    private int next;\n    private int right;\n    private int wrong;\n    private ArrayList<String> missed;\n\n    public PracticeRound(CardBox box) {\n        this.box = box;\n        this.missed = new ArrayList<>();\n    }\n\n    public String question() {\n        if (this.box.size() == 0) {\n            return null;\n        }\n        return this.box.countryAt(this.next);\n    }\n\n    public boolean answer(String text) {\n        String country = this.question();\n        if (country == null) {\n            return false;\n        }\n        boolean correct = text.trim().equalsIgnoreCase(this.box.capitalOf(country));\n        if (correct) {\n            this.right++;\n        } else {\n            this.wrong++;\n            if (!this.missed.contains(country)) {\n                this.missed.add(country);\n            }\n        }\n        this.next++;\n        if (this.next >= this.box.size()) {\n            this.next = 0;\n        }\n        return correct;\n    }\n\n    public int getRight() {\n        return this.right;\n    }\n\n    public int getWrong() {\n        return this.wrong;\n    }\n\n    public ArrayList<String> missed() {\n        return this.missed;\n    }\n}\n","solution":"// ==== NewCardView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class NewCardView {\n    private CardBox box;\n    private VBox view;\n\n    public NewCardView(CardBox box) {\n        this.box = box;\n        TextField country = new TextField();\n        country.setPromptText(\"Country\");\n        TextField capital = new TextField();\n        capital.setPromptText(\"Capital\");\n        Button add = new Button(\"Add card\");\n        Label message = new Label(\"\");\n        add.setOnAction(event -> {\n            if (this.box.add(country.getText(), capital.getText())) {\n                message.setText(\"Added. Cards in the box: \" + this.box.size());\n                country.clear();\n                capital.clear();\n            } else {\n                message.setText(\"Fill in both fields, and add each country once.\");\n            }\n        });\n        capital.setOnAction(event -> add.fire());\n        this.view = new VBox(8, country, capital, add, message);\n        this.view.setPadding(new Insets(10));\n    }\n\n    public Parent getView() {\n        return this.view;\n    }\n}\n\n// ==== TrainingView.java ====\nimport javafx.geometry.Insets;\nimport javafx.scene.Parent;\nimport javafx.scene.control.Button;\nimport javafx.scene.control.Label;\nimport javafx.scene.control.TextField;\nimport javafx.scene.layout.VBox;\n\npublic class TrainingView {\n    private CardBox box;\n    private PracticeRound round;\n\n    public TrainingView(CardBox box, PracticeRound round) {\n        this.box = box;\n        this.round = round;\n    }\n\n    public Parent getView() {\n        VBox view = new VBox(8);\n        view.setPadding(new Insets(10));\n        if (this.round.question() == null) {\n            view.getChildren().add(new Label(\"Add some cards first.\"));\n            return view;\n        }\n        Label question = new Label(\"Capital of \" + this.round.question() + \"?\");\n        TextField answer = new TextField();\n        answer.setPromptText(\"Capital\");\n        Button check = new Button(\"Answer\");\n        Label feedback = new Label(\"\");\n        Label score = new Label(this.scoreText());\n        check.setOnAction(event -> {\n            String country = this.round.question();\n            String capital = this.box.capitalOf(country);\n            if (this.round.answer(answer.getText())) {\n                feedback.setText(\"Yes, \" + capital + \".\");\n            } else {\n                feedback.setText(\"No, it's \" + capital + \".\");\n            }\n            question.setText(\"Capital of \" + this.round.question() + \"?\");\n            answer.clear();\n            score.setText(this.scoreText());\n        });\n        answer.setOnAction(event -> check.fire());\n        view.getChildren().addAll(question, answer, check, feedback, score);\n        return view;\n    }\n\n    private String scoreText() {\n        return \"Right \" + this.round.getRight() + \", wrong \" + this.round.getWrong();\n    }\n}\n\n// ==== Main.java ====\nimport javafx.application.Application;\nimport javafx.geometry.Insets;\nimport javafx.scene.Scene;\nimport javafx.scene.control.Button;\nimport javafx.scene.layout.BorderPane;\nimport javafx.scene.layout.HBox;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        CardBox box = new CardBox();\n        PracticeRound round = new PracticeRound(box);\n        NewCardView newCards = new NewCardView(box);\n        TrainingView training = new TrainingView(box, round);\n\n        Button toNewCards = new Button(\"Add cards\");\n        Button toTraining = new Button(\"Train\");\n        HBox menu = new HBox(10, toNewCards, toTraining);\n        menu.setPadding(new Insets(10));\n\n        BorderPane frame = new BorderPane();\n        frame.setTop(menu);\n        frame.setCenter(newCards.getView());\n        toNewCards.setOnAction(event -> frame.setCenter(newCards.getView()));\n        toTraining.setOnAction(event -> frame.setCenter(training.getView()));\n\n        stage.setScene(new Scene(frame));\n        stage.setTitle(\"Capitals\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n\n// ==== CardBox.java ====\nimport java.util.ArrayList;\n\npublic class CardBox {\n    private ArrayList<Card> cards;\n\n    public CardBox() {\n        this.cards = new ArrayList<>();\n    }\n\n    public boolean add(String country, String capital) {\n        String name = country.trim();\n        String city = capital.trim();\n        if (name.isEmpty() || city.isEmpty() || this.capitalOf(name) != null) {\n            return false;\n        }\n        this.cards.add(new Card(name, city));\n        return true;\n    }\n\n    public String capitalOf(String country) {\n        for (Card card : this.cards) {\n            if (card.getCountry().equals(country)) {\n                return card.getCapital();\n            }\n        }\n        return null;\n    }\n\n    public String countryAt(int index) {\n        return this.cards.get(index).getCountry();\n    }\n\n    public int size() {\n        return this.cards.size();\n    }\n}\n\n// ==== Card.java ====\npublic class Card {\n    private String country;\n    private String capital;\n\n    public Card(String country, String capital) {\n        this.country = country;\n        this.capital = capital;\n    }\n\n    public String getCountry() {\n        return this.country;\n    }\n\n    public String getCapital() {\n        return this.capital;\n    }\n}\n\n// ==== PracticeRound.java ====\nimport java.util.ArrayList;\n\npublic class PracticeRound {\n    private CardBox box;\n    private int next;\n    private int right;\n    private int wrong;\n    private ArrayList<String> missed;\n\n    public PracticeRound(CardBox box) {\n        this.box = box;\n        this.missed = new ArrayList<>();\n    }\n\n    public String question() {\n        if (this.box.size() == 0) {\n            return null;\n        }\n        return this.box.countryAt(this.next);\n    }\n\n    public boolean answer(String text) {\n        String country = this.question();\n        if (country == null) {\n            return false;\n        }\n        boolean correct = text.trim().equalsIgnoreCase(this.box.capitalOf(country));\n        if (correct) {\n            this.right++;\n        } else {\n            this.wrong++;\n            if (!this.missed.contains(country)) {\n                this.missed.add(country);\n            }\n        }\n        this.next++;\n        if (this.next >= this.box.size()) {\n            this.next = 0;\n        }\n        return correct;\n    }\n\n    public int getRight() {\n        return this.right;\n    }\n\n    public int getWrong() {\n        return this.wrong;\n    }\n\n    public ArrayList<String> missed() {\n        return this.missed;\n    }\n}\n","hints":["In NewCardView's constructor, after Add card's handler: `capital.setOnAction(event -> add.fire());`.","In TrainingView's `getView()`, after Answer's handler: `answer.setOnAction(event -> check.fire());`, with the names your fields and buttons have."],"tests":[{"name":"Test 1","stdin":"","expect":"","hidden":false,"events":["type TextField 1 \"Peru\"","type TextField 2 \"Lima\"","enter TextField 2","type TextField 1 \"Kenya\"","type TextField 2 \"Nairobi\"","enter TextField 2","click Button \"Train\"","type TextField 1 \"Lima\"","enter TextField 1"],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Capital of Kenya?"},{"n":7,"type":"TextField","text":"","promptText":"Capital","onAction":true},{"n":8,"type":"Button","text":"Answer","onAction":true},{"n":9,"type":"Label","text":"Yes, Lima."},{"n":10,"type":"Label","text":"Right 1, wrong 0"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Capital of Kenya?\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Answer\"\n      Label \"Yes, Lima.\"\n      Label \"Right 1, wrong 0\""},{"name":"Test 2","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Japan\"","enter TextField 2"],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"TextField","text":"Japan","promptText":"Country"},{"n":7,"type":"TextField","text":"","promptText":"Capital","onAction":true},{"n":8,"type":"Button","text":"Add card","onAction":true},{"n":9,"type":"Label","text":"Fill in both fields, and add each country once."}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      TextField \"Japan\", prompt \"Country\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Add card\"\n      Label \"Fill in both fields, and add each country once.\""},{"name":"Test 3","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Japan\"","type TextField 2 \"Tokyo\"","enter TextField 2","click Button \"Train\"","type TextField 1 \"Kyoto\"","enter TextField 1","type TextField 1 \"Tokyo\"","click Button \"Answer\""],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Capital of Japan?"},{"n":7,"type":"TextField","text":"","promptText":"Capital","onAction":true},{"n":8,"type":"Button","text":"Answer","onAction":true},{"n":9,"type":"Label","text":"Yes, Tokyo."},{"n":10,"type":"Label","text":"Right 1, wrong 1"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Capital of Japan?\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Answer\"\n      Label \"Yes, Tokyo.\"\n      Label \"Right 1, wrong 1\""},{"name":"Test 4","stdin":"","expect":"","hidden":true,"events":["type TextField 1 \"Japan\"","type TextField 2 \"Tokyo\"","click Button \"Add card\"","type TextField 1 \"Egypt\"","type TextField 2 \"Cairo\"","enter TextField 1","click Button \"Train\"","enter TextField 1"],"window":{"windows":[{"title":"Capitals","scene":{"root":{"n":1,"type":"BorderPane","top":{"n":2,"type":"HBox","padding":[10,10,10,10],"spacing":10,"children":[{"n":3,"type":"Button","text":"Add cards","onAction":true},{"n":4,"type":"Button","text":"Train","onAction":true}]},"center":{"n":5,"type":"VBox","padding":[10,10,10,10],"spacing":8,"children":[{"n":6,"type":"Label","text":"Capital of Japan?"},{"n":7,"type":"TextField","text":"","promptText":"Capital","onAction":true},{"n":8,"type":"Button","text":"Answer","onAction":true},{"n":9,"type":"Label","text":"No, it's Tokyo."},{"n":10,"type":"Label","text":"Right 0, wrong 1"}]}}}}],"problems":[]},"outline":"Window \"Capitals\"\n  BorderPane\n    top: HBox spacing 10, padding 10\n      Button \"Add cards\"\n      Button \"Train\"\n    center: VBox spacing 8, padding 10\n      Label \"Capital of Japan?\"\n      TextField \"\", prompt \"Capital\"\n      Button \"Answer\"\n      Label \"No, it's Tokyo.\"\n      Label \"Right 0, wrong 1\""}],"require":[],"forbid":[]}]}