Assigned: 2019-09-05
Due Date: 2019-09-10 by 11:59PM U.S. Central Time
What a save!
What a save!
What a save!
Chat disabled for 4 seconds
— Rocket League
It's your first day on the job at Sportsbridge Analytica, a popular data analysis firm, and your boss is already breathing down your neck: he wants to make a strong impression on some potential investors, so he's tasked you (lucky, lucky!) to analyze a file that he says describes every play made during a soccer game. He wants to you get back to him with "some statistics," whatever that means. Fortunately for you, we're here to help you through it!
Upon closer inspection, you realize that the file is just JSON. Hooray! Intrepid CS 126 student that you are, you know that if you use Google's GSON to turn the JSON into Java objects, you can easily analyze the data and provide your boss the statistics he needs to amaze his investors! And secure the Epic Victory Royale!
Serializing (or marshalling) is the process of converting objects in code into a different representation for storage, whether that's JSON, YAML, binary data, or something else. Deserializing (or unmarshalling) is the reverse: converting serialized data into actual objects in your code. In this case, we are transmitting serialized data about a soccer game to you, so that you can deserialize it into Java objects for processing.
A schema is a definition of how to represent some data. For example, if we want to describe a course at UIUC in words we might say the following:
There is a natural translation between a schema describing objects stored in JSON and objects in Java.
The soccer game data is stored as JSON, a data format popularized by the JavaScript programming language. Here's an example of some JSON, representing a group of courses at UIUC:
{ "courses": [ { "department": "Computer Science", "number": 126, "isDifficult": false, "isTimeConsuming": true, "professors": ["Craig Zilles", "Carl Evans", "Michael Woodley"] }, { "department": "Computer Science", "number": 421, "isDifficult": true, "isTimeConsuming": false, "professors": ["Elsa Gunter", "Mattox Beckman"] } ] }
Things to note about syntactically valid JSON:
{
and }
The JSON we're providing to you is already valid, so you don't need to worry about any of this unless you want to edit or write your own JSON for testing purposes. If you want to check that your JSON is valid, you can use a JSON validator like this one.
Rather than having you parse JSON all by yourself, you're going to use
Google's GSON library to do it for you. GSON is already included in
your project; all you have to do is import
and use it.
If we have some JSON like above, we need to define some Java classes that match the schema so that GSON can deserialize the JSON into instances of those objects.
First, we define the outermost class with its fields:
public class UiucCourses { private List<Course> courses; // -- Getter methods omitted -- }
Then we define the inner class, with its own fields:
public class Course { private String department; private int number; private boolean isDifficult; private boolean isTimeConsuming; private String[] professors; // -- Getter methods omitted -- }
Finally, we deserialize our JSON into an instance of UiucCourses
:
String myJson = "....."; // Read in JSON from somewhere... Gson gson = new Gson(); // Create an instance of a GSON parser UiucCourses courses = gson.fromJson(myJson, UiucCourses.class);
Note that you can define your collections as either Object[]
or
List<Object>
at your preference, and GSON will convert it to the
appropriate format.
If you need more documentation and examples on how to use GSON, see the User's Guide.
@Before
As with the previous assignment, we expect you to write unit tests as
you develop. We're going to introduce a new feature of JUnit to make
writing some kinds of tests easier for you: the @Before
annotation.
Here's the motivation: your unit tests should be self contained so
that running one test doesn't influence the results of another. When
you have objects that are shared between tests, that can be hard to
guarantee. When you apply the @Before
annotation to a function in
your testing class, it tells JUnit that it should run that function
once before each and every one of your unit tests, so we can use an
@Before
-annotated method to reset any necessary state between test
cases.
Specifically, this is great for tests involving GSON:
public class UiucCoursesTest { private Gson gson; @Before public void setUp() { gson = new Gson(); } @Test public void testCaseOne() { gson.fromJson(/* ... */); } @Test public void testCaseTwo() { gson.fromJson(/* ... */); } }
Now we don't have to repeat the line Gson gson = new Gson()
in all
of our tests, and the GSON instance will be reset before each and
every one of our unit tests. For more information, see JUnit's
documentation.
Get your copy of the assignment by visiting this GitHub link: https://classroom.github.com/a/E0vpSHyB
The JSON data you'll be analyzing is hosted here: https://courses.grainger.illinois.edu/cs126/fa2019/assignments/sportsball.json
You may download a copy of this data to use in your development process and for testing, but you should avoid copy-pasting the JSON into your code.
In order to do anything meaningful with the data in Java, you have to convert it into Java objects. You will do this using Google's GSON, a JSON serializing/deserializing library.
Specifically you should:
Once you have your data as Java objects, you need to be able to filter and process it to get more interesting results. Specifically, you need to create:
At least four different functions that filter collections of information about game based on some criteria. Some examples:
At least four different functions that do some analysis and produce a computed result. Some examples:
You do not have to implement these specific examples.
For the purposes of this assignment, a filtering function takes in a collection and produces another collection with the same number or fewer elements. An analysis function gives you some kind of result, whether that result is a list or a number or a boolean.
The functions should not mutate any of the data they operate on; they should return new collections/numbers/objects as necessary.
This assignment is deliberately open-ended with regards to how you choose to implement the filtering and analysis functions; design decisions like what kinds of classes and functions to write are left up to you. Be creative! We have avoided giving you any starter code to encourage you to reason about how to organize your project.
We have provided you with a single helper method for the purpose of
reading in a file as a String
, which you may freely use in your
development process and tests. There is a unit test demonstrating its
usage.
As always, try to use the best code design and coding style. Continue to focus on writing good names (you have a lot of freedom in naming for this assignment) and think about how to cleanly lay out your code so that it's easy for an outsider (your moderator) to follow. You might find Chapter 4 of the textbook and Section 4 of the Google Java Style Guide to be good resources for this.
As you work on this project, you should commit small pieces of functionality as you write them. Don't make a single mega-commit at the very end! We expect your commit history to demonstrate you following some sort of iterative design process. For example: writing some tests, writing some code, changing some tests, fixing a test, writing more code, etc. Commits are cheap. Make lots of them!
Specific things we will be checking for: