{"id":"charts-line-chart","slug":"line-chart","title":"A first line chart","text":"A **line chart** shows how a value changes: the x axis goes across (often time: days, weeks, months), the y axis goes up (the value), and a line joins the points. A class grows a corn seedling on its windowsill and measures it once a week:\n\n```java\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        NumberAxis weeks = new NumberAxis();\n        NumberAxis height = new NumberAxis();\n        LineChart<Number, Number> chart = new LineChart<>(weeks, height);\n\n        XYChart.Series<Number, Number> corn = new XYChart.Series<>();\n        corn.getData().add(new XYChart.Data<>(1, 3));\n        corn.getData().add(new XYChart.Data<>(2, 7));\n        corn.getData().add(new XYChart.Data<>(3, 14));\n        corn.getData().add(new XYChart.Data<>(4, 26));\n        corn.getData().add(new XYChart.Data<>(5, 41));\n        chart.getData().add(corn);\n\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Corn\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Corn\",\"scene\":{\"root\":{\"n\":1,\"type\":\"LineChart\",\"title\":null,\"xAxis\":{\"type\":\"NumberAxis\",\"label\":null,\"autoRanging\":true,\"lowerBound\":0,\"upperBound\":100,\"tickUnit\":5,\"forceZeroInRange\":true,\"minorTickVisible\":true},\"yAxis\":{\"type\":\"NumberAxis\",\"label\":null,\"autoRanging\":true,\"lowerBound\":0,\"upperBound\":100,\"tickUnit\":5,\"forceZeroInRange\":true,\"minorTickVisible\":true},\"series\":[{\"name\":null,\"data\":[[1,3],[2,7],[3,14],[4,26],[5,41]]}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Corn\\\"\\n  LineChart without a title\\n    x axis NumberAxis\\n    y axis NumberAxis\\n    series without a name: (1, 3) (2, 7) (3, 14) (4, 26) (5, 41)\"}\n```\n\nThe classes are in the package `javafx.scene.chart`. Part by part:\n\n- `NumberAxis` is an **axis** for numbers. A chart has two: the first one given is the x axis, the second the y axis.\n- `LineChart<Number, Number>` is a line chart whose x values and y values are both numbers. Like the classes of module 44, the chart has type parameters: the type of its x values, then of its y values. **Number** is a class of `java.lang` that Integer and Double both extend, so a chart of Numbers takes whole numbers and decimals alike. `new LineChart<>(weeks, height)` gives the chart its two axes.\n- `XYChart.Series` is one **series**: a set of points that the chart joins with a line. Its name has a dot because Series is a class written inside the class XYChart (the class that every chart with an x and a y axis extends). The import of `javafx.scene.chart.XYChart` covers it.\n- `new XYChart.Data<>(1, 3)` is one **data point**: x is 1 (week 1) and y is 3 (cm). `corn.getData()` is the series's list of points, and `add` adds one at the end.\n- `getXValue()` and `getYValue()` read a point's values, `setYValue(...)` changes one, and the series holds the point objects themselves, so a change to a point you kept shows in the series.\n- `chart.getData()` is the chart's list of series. A series shows only once it's added to the chart.\n- A chart is a node, like a label or a VBox: here it's the scene's root, and it could just as well be in a layout.\n\nA `new NumberAxis()` is **auto-ranging**: it picks its range from the data, so that every point fits. By default it also includes 0, so the y axis here starts at 0. The page draws an auto-ranging axis with a range it works out the way JavaFX does, approximately.\n\n### Titles, labels and fixed bounds\n\nA chart that nobody can read is no use. The same chart with a title, labels on its axes and a fixed range for the weeks:\n\n```java\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        NumberAxis weeks = new NumberAxis(\"Week\", 1, 6, 1);\n        NumberAxis height = new NumberAxis();\n        height.setLabel(\"Height (cm)\");\n        LineChart<Number, Number> chart = new LineChart<>(weeks, height);\n        chart.setTitle(\"A corn plant grows\");\n        chart.setLegendVisible(false);\n\n        XYChart.Series<Number, Number> corn = new XYChart.Series<>();\n        corn.setName(\"Corn\");\n        corn.getData().add(new XYChart.Data<>(1, 3));\n        corn.getData().add(new XYChart.Data<>(2, 7));\n        corn.getData().add(new XYChart.Data<>(3, 14));\n        corn.getData().add(new XYChart.Data<>(4, 26));\n        corn.getData().add(new XYChart.Data<>(5, 41));\n        corn.getData().add(new XYChart.Data<>(6, 58.5));\n        chart.getData().add(corn);\n\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Corn\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Corn\",\"scene\":{\"root\":{\"n\":1,\"type\":\"LineChart\",\"title\":\"A corn plant grows\",\"legendVisible\":false,\"xAxis\":{\"type\":\"NumberAxis\",\"label\":\"Week\",\"autoRanging\":false,\"lowerBound\":1,\"upperBound\":6,\"tickUnit\":1,\"forceZeroInRange\":true,\"minorTickVisible\":true},\"yAxis\":{\"type\":\"NumberAxis\",\"label\":\"Height (cm)\",\"autoRanging\":true,\"lowerBound\":0,\"upperBound\":100,\"tickUnit\":5,\"forceZeroInRange\":true,\"minorTickVisible\":true},\"series\":[{\"name\":\"Corn\",\"data\":[[1,3],[2,7],[3,14],[4,26],[5,41],[6,58.5]]}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Corn\\\"\\n  LineChart \\\"A corn plant grows\\\" (no legend)\\n    x axis NumberAxis \\\"Week\\\" 1 to 6 by 1\\n    y axis NumberAxis \\\"Height (cm)\\\"\\n    series \\\"Corn\\\": (1, 3) (2, 7) (3, 14) (4, 26) (5, 41) (6, 58.5)\"}\n```\n\n- `new NumberAxis(\"Week\", 1, 6, 1)` is an axis with the label `Week` that goes from 1 (its **lower bound**) to 6 (its **upper bound**), with a tick mark and a number every 1 (its **tick unit**). An axis with bounds isn't auto-ranging: it shows exactly that range, even if a point lies outside it. `new NumberAxis(1, 6, 1)` is the same without a label. `getLowerBound()`, `getUpperBound()` and `getTickUnit()` read them back as doubles (`1.0`, not `1`), and `isAutoRanging()` says whether the axis picks its own range.\n- `height.setLabel(\"Height (cm)\")` labels an axis that stays auto-ranging. A label should say the unit: 58.5 what?\n- `chart.setTitle(...)` is the title above the chart (and `stage.setTitle(...)` still the window's own title).\n- `corn.setName(\"Corn\")` names the series. The chart's **legend**, under the chart, shows each series's name next to its color. With one series the legend says little, so `chart.setLegendVisible(false)` hides it.\n- Week 6 is `58.5`, a Double, in the same series as the Integers: both are Numbers.\n\n### What the page draws, and what's checked\n\nThe drawing above is the page's own, made from what the program told the chart: approximate, like the windows of part 13. What the program decided is listed exactly under it, in \"The window as text\":\n\n```text\nWindow \"Corn\"\n  LineChart \"A corn plant grows\" (no legend)\n    x axis NumberAxis \"Week\" 1 to 6 by 1\n    y axis NumberAxis \"Height (cm)\"\n    series \"Corn\": (1, 3) (2, 7) (3, 14) (4, 26) (5, 41) (6, 58.5)\n```\n\nThese lines are what the checks of the challenges compare: the kind of chart, its title, whether the legend shows, each axis (its class and label, and its bounds and tick unit when you set them), and each series, with its name and its points in the order they were added. So a task says all of these exactly, and when it says that an axis is auto-ranging, its line shows no bounds. The colors, the sizes and the range that an auto-ranging axis picks aren't compared. Numbers are written without a `.0` at the end, so 58.5 is `58.5` and 41.0 would be `41`.\n\n### From a file\n\nThe class keeps the heights in a file, with a `-` for a week when nobody measured:\n\n```file corn.csv\nweek,cm\n1,3\n2,7\n3,-\n4,26\n5,41\n6,58.5\n```\n\n`start` reads it as step 1 did. `start` may declare `throws Exception` (module 48 did), so the reading needs no `try`:\n\n```java\nimport java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) throws Exception {\n        NumberAxis weeks = new NumberAxis(\"Week\", 1, 6, 1);\n        NumberAxis height = new NumberAxis();\n        height.setLabel(\"Height (cm)\");\n        LineChart<Number, Number> chart = new LineChart<>(weeks, height);\n        chart.setTitle(\"A corn plant grows\");\n        chart.setLegendVisible(false);\n\n        XYChart.Series<Number, Number> corn = new XYChart.Series<>();\n        corn.setName(\"Corn\");\n        List<String> lines = Files.readAllLines(Paths.get(\"corn.csv\"));\n        for (int i = 1; i < lines.size(); i++) {\n            String[] parts = lines.get(i).split(\",\");\n            if (!parts[1].equals(\"-\")) {\n                int week = Integer.valueOf(parts[0]);\n                double cm = Double.valueOf(parts[1]);\n                corn.getData().add(new XYChart.Data<>(week, cm));\n            }\n        }\n        chart.getData().add(corn);\n        System.out.println(corn);\n        System.out.println(corn.getData().size() + \" points\");\n        System.out.println(corn.getData().get(2));\n\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Corn\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n```\n\n```window\n{\"events\":[],\"window\":{\"windows\":[{\"title\":\"Corn\",\"scene\":{\"root\":{\"n\":1,\"type\":\"LineChart\",\"title\":\"A corn plant grows\",\"legendVisible\":false,\"xAxis\":{\"type\":\"NumberAxis\",\"label\":\"Week\",\"autoRanging\":false,\"lowerBound\":1,\"upperBound\":6,\"tickUnit\":1,\"forceZeroInRange\":true,\"minorTickVisible\":true},\"yAxis\":{\"type\":\"NumberAxis\",\"label\":\"Height (cm)\",\"autoRanging\":true,\"lowerBound\":0,\"upperBound\":100,\"tickUnit\":5,\"forceZeroInRange\":true,\"minorTickVisible\":true},\"series\":[{\"name\":\"Corn\",\"data\":[[1,3],[2,7],[4,26],[5,41],[6,58.5]]}]}}}],\"problems\":[]},\"outline\":\"Window \\\"Corn\\\"\\n  LineChart \\\"A corn plant grows\\\" (no legend)\\n    x axis NumberAxis \\\"Week\\\" 1 to 6 by 1\\n    y axis NumberAxis \\\"Height (cm)\\\"\\n    series \\\"Corn\\\": (1, 3) (2, 7) (4, 26) (5, 41) (6, 58.5)\"}\n```\n\n```output\nSeries[Corn]\n5 points\nData[4,26.0,null]\n```\n\n- Week 3 has no point, so the line goes straight from week 2 to week 4. A reader can easily miss that a week is missing: only the missing mark at week 3 shows it, while the window as text and the `5 points` above say it plainly.\n- Printing a series shows its name, and printing a point shows its x and its y. The third value, `null`, is an extra value that JavaFX lets a point carry; this course doesn't use it. The third point is week 4's: the index counts the points of the series, not the rows of the file.\n- `cm` is a double, so even `26` from the file became `26.0`. In the window as text it's `26`, since that leaves out the `.0`.\n","task":"The school library wants its loans as a line chart. `loans.csv` has the month's number and the loans:\n\n```text\nmonth,loans\n1,412\n2,388\n3,455\n4,390\n5,301\n6,120\n```\n\nFill in the blanks. The chart's title is `School library loans`, its x axis is labeled `Month` and goes from 1 to 12 with a tick every 1, its y axis is labeled `Loans` and auto-ranging, and its one series, `Loans`, has a point for each row of the file. The legend is hidden.\n","kind":"fill","seed":"import java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) throws Exception {\n        NumberAxis months = new NumberAxis(\"Month\", 1, 12, [[1]]);\n        NumberAxis loans = new NumberAxis();\n        loans.setLabel(\"Loans\");\n        LineChart<Number, Number> chart = new [[LineChart]]<>(months, loans);\n        chart.setTitle(\"School library loans\");\n        chart.setLegendVisible(false);\n\n        XYChart.Series<Number, Number> series = new XYChart.Series<>();\n        series.setName(\"Loans\");\n        List<String> lines = Files.readAllLines(Paths.get(\"loans.csv\"));\n        for (int i = 1; i < lines.size(); i++) {\n            String[] parts = lines.get(i).split(\",\");\n            series.getData().add(new XYChart.[[Data]]<>(Integer.valueOf(parts[0]), Integer.valueOf(parts[1])));\n        }\n        chart.getData().[[add]](series);\n\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Library\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","solution":"import java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) throws Exception {\n        NumberAxis months = new NumberAxis(\"Month\", 1, 12, 1);\n        NumberAxis loans = new NumberAxis();\n        loans.setLabel(\"Loans\");\n        LineChart<Number, Number> chart = new LineChart<>(months, loans);\n        chart.setTitle(\"School library loans\");\n        chart.setLegendVisible(false);\n\n        XYChart.Series<Number, Number> series = new XYChart.Series<>();\n        series.setName(\"Loans\");\n        List<String> lines = Files.readAllLines(Paths.get(\"loans.csv\"));\n        for (int i = 1; i < lines.size(); i++) {\n            String[] parts = lines.get(i).split(\",\");\n            series.getData().add(new XYChart.Data<>(Integer.valueOf(parts[0]), Integer.valueOf(parts[1])));\n        }\n        chart.getData().add(series);\n\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Library\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","hints":["NumberAxis's four-argument constructor takes the label, the lower bound, the upper bound and the tick unit: how far apart are the months' ticks? Which chart class draws points joined by a line, which class is one point, and how does a series get into the chart's list?","`new NumberAxis(\"Month\", 1, 12, 1)` has a tick every 1. The chart is a `LineChart`, made with its two axes. A point is an `XYChart.Data`, and the series shows only once it's added to the chart's list: `chart.getData().add(series)`."],"tests":[{"name":"Test 1","stdin":"","files":{"loans.csv":"month,loans\n1,412\n2,388\n3,455\n4,390\n5,301\n6,120\n"},"expect":"","hidden":false,"events":[],"window":{"windows":[{"title":"Library","scene":{"root":{"n":1,"type":"LineChart","title":"School library loans","legendVisible":false,"xAxis":{"type":"NumberAxis","label":"Month","autoRanging":false,"lowerBound":1,"upperBound":12,"tickUnit":1,"forceZeroInRange":true,"minorTickVisible":true},"yAxis":{"type":"NumberAxis","label":"Loans","autoRanging":true,"lowerBound":0,"upperBound":100,"tickUnit":5,"forceZeroInRange":true,"minorTickVisible":true},"series":[{"name":"Loans","data":[[1,412],[2,388],[3,455],[4,390],[5,301],[6,120]]}]}}}],"problems":[]},"outline":"Window \"Library\"\n  LineChart \"School library loans\" (no legend)\n    x axis NumberAxis \"Month\" 1 to 12 by 1\n    y axis NumberAxis \"Loans\"\n    series \"Loans\": (1, 412) (2, 388) (3, 455) (4, 390) (5, 301) (6, 120)"},{"name":"Test 2","stdin":"","files":{"loans.csv":"month,loans\n8,95\n9,520\n10,610\n11,575\n12,240\n"},"expect":"","hidden":true,"events":[],"window":{"windows":[{"title":"Library","scene":{"root":{"n":1,"type":"LineChart","title":"School library loans","legendVisible":false,"xAxis":{"type":"NumberAxis","label":"Month","autoRanging":false,"lowerBound":1,"upperBound":12,"tickUnit":1,"forceZeroInRange":true,"minorTickVisible":true},"yAxis":{"type":"NumberAxis","label":"Loans","autoRanging":true,"lowerBound":0,"upperBound":100,"tickUnit":5,"forceZeroInRange":true,"minorTickVisible":true},"series":[{"name":"Loans","data":[[8,95],[9,520],[10,610],[11,575],[12,240]]}]}}}],"problems":[]},"outline":"Window \"Library\"\n  LineChart \"School library loans\" (no legend)\n    x axis NumberAxis \"Month\" 1 to 12 by 1\n    y axis NumberAxis \"Loans\"\n    series \"Loans\": (8, 95) (9, 520) (10, 610) (11, 575) (12, 240)"},{"name":"Test 3","stdin":"","files":{"loans.csv":"month,loans\n1,0\n"},"expect":"","hidden":true,"events":[],"window":{"windows":[{"title":"Library","scene":{"root":{"n":1,"type":"LineChart","title":"School library loans","legendVisible":false,"xAxis":{"type":"NumberAxis","label":"Month","autoRanging":false,"lowerBound":1,"upperBound":12,"tickUnit":1,"forceZeroInRange":true,"minorTickVisible":true},"yAxis":{"type":"NumberAxis","label":"Loans","autoRanging":true,"lowerBound":0,"upperBound":100,"tickUnit":5,"forceZeroInRange":true,"minorTickVisible":true},"series":[{"name":"Loans","data":[[1,0]]}]}}}],"problems":[]},"outline":"Window \"Library\"\n  LineChart \"School library loans\" (no legend)\n    x axis NumberAxis \"Month\" 1 to 12 by 1\n    y axis NumberAxis \"Loans\"\n    series \"Loans\": (1, 0)"}],"require":[],"forbid":[],"more":[{"task":"A weather station sends its rain for the year in `rain.csv`. Its first line is the station's name, then come the header and a row for each month, with a `-` for a month without a measurement:\n\n```text\nHilltop\nmonth,mm\n1,52\n2,41\n3,-\n4,38\n5,45\n6,60\n7,72\n8,81\n9,64\n10,77\n11,69\n12,58\n```\n\nWrite `start` so that the window, titled `Rain`, shows a line chart (the scene's root) with:\n\n- the title `Rain at Hilltop`: `Rain at ` and the name from the first line\n- an x axis labeled `Month`, from 1 to 12 with a tick every 1\n- a y axis labeled `Rain (mm)`, auto-ranging\n- one series named `Rain`, with a point (month, mm) for each month that has a measurement, in the order of the file\n- no legend\n\nRead the rain as whole numbers. The task card shows the window for the file above.\n","kind":"code","seed":"import java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) throws Exception {\n        List<String> lines = Files.readAllLines(Paths.get(\"rain.csv\"));\n        LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());\n\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Rain\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","solution":"import java.nio.file.Files;\nimport java.nio.file.Paths;\nimport java.util.List;\nimport javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) throws Exception {\n        List<String> lines = Files.readAllLines(Paths.get(\"rain.csv\"));\n        NumberAxis months = new NumberAxis(\"Month\", 1, 12, 1);\n        NumberAxis rain = new NumberAxis();\n        rain.setLabel(\"Rain (mm)\");\n        LineChart<Number, Number> chart = new LineChart<>(months, rain);\n        chart.setTitle(\"Rain at \" + lines.get(0));\n        chart.setLegendVisible(false);\n\n        XYChart.Series<Number, Number> series = new XYChart.Series<>();\n        series.setName(\"Rain\");\n        for (int i = 2; i < lines.size(); i++) {\n            String[] parts = lines.get(i).split(\",\");\n            if (!parts[1].equals(\"-\")) {\n                series.getData().add(new XYChart.Data<>(Integer.valueOf(parts[0]), Integer.valueOf(parts[1])));\n            }\n        }\n        chart.getData().add(series);\n\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Rain\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","hints":["The name is `lines.get(0)`, and line 1 is the header, so the rows of data start at index 2.","Make the axes first: `new NumberAxis(\"Month\", 1, 12, 1)`, and a `new NumberAxis()` with `setLabel(\"Rain (mm)\")`. Give them to `new LineChart<>(...)`, and skip a row whose `parts[1]` is `\"-\"`."],"tests":[{"name":"Test 1","stdin":"","files":{"rain.csv":"Hilltop\nmonth,mm\n1,52\n2,41\n3,-\n4,38\n5,45\n6,60\n7,72\n8,81\n9,64\n10,77\n11,69\n12,58\n"},"expect":"","hidden":false,"events":[],"window":{"windows":[{"title":"Rain","scene":{"root":{"n":1,"type":"LineChart","title":"Rain at Hilltop","legendVisible":false,"xAxis":{"type":"NumberAxis","label":"Month","autoRanging":false,"lowerBound":1,"upperBound":12,"tickUnit":1,"forceZeroInRange":true,"minorTickVisible":true},"yAxis":{"type":"NumberAxis","label":"Rain (mm)","autoRanging":true,"lowerBound":0,"upperBound":100,"tickUnit":5,"forceZeroInRange":true,"minorTickVisible":true},"series":[{"name":"Rain","data":[[1,52],[2,41],[4,38],[5,45],[6,60],[7,72],[8,81],[9,64],[10,77],[11,69],[12,58]]}]}}}],"problems":[]},"outline":"Window \"Rain\"\n  LineChart \"Rain at Hilltop\" (no legend)\n    x axis NumberAxis \"Month\" 1 to 12 by 1\n    y axis NumberAxis \"Rain (mm)\"\n    series \"Rain\": (1, 52) (2, 41) (4, 38) (5, 45) (6, 60) (7, 72) (8, 81) (9, 64) (10, 77) (11, 69) (12, 58)"},{"name":"Test 2","stdin":"","files":{"rain.csv":"Lakeside\nmonth,mm\n1,-\n2,-\n3,30\n4,22\n5,-\n6,47\n"},"expect":"","hidden":true,"events":[],"window":{"windows":[{"title":"Rain","scene":{"root":{"n":1,"type":"LineChart","title":"Rain at Lakeside","legendVisible":false,"xAxis":{"type":"NumberAxis","label":"Month","autoRanging":false,"lowerBound":1,"upperBound":12,"tickUnit":1,"forceZeroInRange":true,"minorTickVisible":true},"yAxis":{"type":"NumberAxis","label":"Rain (mm)","autoRanging":true,"lowerBound":0,"upperBound":100,"tickUnit":5,"forceZeroInRange":true,"minorTickVisible":true},"series":[{"name":"Rain","data":[[3,30],[4,22],[6,47]]}]}}}],"problems":[]},"outline":"Window \"Rain\"\n  LineChart \"Rain at Lakeside\" (no legend)\n    x axis NumberAxis \"Month\" 1 to 12 by 1\n    y axis NumberAxis \"Rain (mm)\"\n    series \"Rain\": (3, 30) (4, 22) (6, 47)"},{"name":"Test 3","stdin":"","files":{"rain.csv":"Old Harbor\nmonth,mm\n7,104\n8,96\n"},"expect":"","hidden":true,"events":[],"window":{"windows":[{"title":"Rain","scene":{"root":{"n":1,"type":"LineChart","title":"Rain at Old Harbor","legendVisible":false,"xAxis":{"type":"NumberAxis","label":"Month","autoRanging":false,"lowerBound":1,"upperBound":12,"tickUnit":1,"forceZeroInRange":true,"minorTickVisible":true},"yAxis":{"type":"NumberAxis","label":"Rain (mm)","autoRanging":true,"lowerBound":0,"upperBound":100,"tickUnit":5,"forceZeroInRange":true,"minorTickVisible":true},"series":[{"name":"Rain","data":[[7,104],[8,96]]}]}}}],"problems":[]},"outline":"Window \"Rain\"\n  LineChart \"Rain at Old Harbor\" (no legend)\n    x axis NumberAxis \"Month\" 1 to 12 by 1\n    y axis NumberAxis \"Rain (mm)\"\n    series \"Rain\": (7, 104) (8, 96)"}],"require":[],"forbid":[]},{"task":"A herb garden's basil gets a series of its own. What does this program print?\n","kind":"predict","seed":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        XYChart.Series<Number, Number> basil = new XYChart.Series<>();\n        basil.setName(\"Basil\");\n        XYChart.Data<Number, Number> first = new XYChart.Data<>(1, 4);\n        basil.getData().add(first);\n        basil.getData().add(new XYChart.Data<>(2, 9));\n        first.setYValue(5);\n        System.out.println(basil.getData().size());\n        System.out.println(first.getXValue() + \" \" + first.getYValue());\n        System.out.println(basil.getData().get(1));\n        System.out.println(basil);\n\n        LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());\n        chart.getData().add(basil);\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Herbs\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","solution":"import javafx.application.Application;\nimport javafx.scene.Scene;\nimport javafx.scene.chart.LineChart;\nimport javafx.scene.chart.NumberAxis;\nimport javafx.scene.chart.XYChart;\nimport javafx.stage.Stage;\n\npublic class Main extends Application {\n\n    @Override\n    public void start(Stage stage) {\n        XYChart.Series<Number, Number> basil = new XYChart.Series<>();\n        basil.setName(\"Basil\");\n        XYChart.Data<Number, Number> first = new XYChart.Data<>(1, 4);\n        basil.getData().add(first);\n        basil.getData().add(new XYChart.Data<>(2, 9));\n        first.setYValue(5);\n        System.out.println(basil.getData().size());\n        System.out.println(first.getXValue() + \" \" + first.getYValue());\n        System.out.println(basil.getData().get(1));\n        System.out.println(basil);\n\n        LineChart<Number, Number> chart = new LineChart<>(new NumberAxis(), new NumberAxis());\n        chart.getData().add(basil);\n        stage.setScene(new Scene(chart));\n        stage.setTitle(\"Herbs\");\n        stage.show();\n    }\n\n    public static void main(String[] args) {\n        launch(Main.class);\n    }\n}\n","hints":["The series holds the point objects themselves, so `first.setYValue(5)` changes the first point of the series. `getXValue()` and `getYValue()` give a point's x and y.","Printing a point gives `Data[x,y,null]`, and printing a series gives `Series[` and its name, then `]`."],"tests":[{"name":"Output","stdin":"","expect":"2\n1 5\nData[2,9,null]\nSeries[Basil]","hidden":false}],"require":[],"forbid":[],"lines":["2","1 5","Data[2,9,null]","Series[Basil]"]}]}