Getting Started with firstapiR

Version 1.0.0

For guidance on version 2.0.0 of firstapiR, click here

Stacy Irwin

2016-09-20

The firstapiR package provides R functions that download FIRST Robotics Competition (FRC) data from the FIRST API server via hypertext transfer protocol (HTTP) requests. The firstapiR package formats the resulting data as JSON text, XML text, or as R data frames.

FIRST - For Inspiration and Recognition in Science and Technology

FIRST engages kids in kindergarten through high school in exciting, mentor-based, research and robotics programs that help them become science and technology leaders, as well as well-rounded contributors to society. Learn more about FIRST by visiting their website.

FRC is one of four FIRST programs. In FRC, high-school students, in cooperation with adult mentors, design and build robots and operate them in competitions. The competitions have detailed rules (check out the 2016 game manual) and an extensive amount of data is generated at each competition. All scheduling, team, scoring, and ranking data is stored in FIRST servers and is made available to users via the FIRST API.

Getting Access to the FIRST API

To see what the FIRST API can do, visit the FIRST API documentation page. The documentation page provides detailed information on the formats for HTTP request and authorization headers, as well as detailed descriptions of the data provided by each type of API call.

To use the FIRST API (via firatapiR functions or via HTTP requests that you build yourself), you must have a username and authorization key issued by FIRST. To get a username and authorization key, go to the FIRST Community Developers page on TeamForge. Follow the instructions on the page to join the project and FIRST will email you a username and authorization key. Make sure you keep your authorization key secret - don’t post the key anywhere that is publicly accessible.

Learning R

R is a functional language intended for statistical computing, data analysis and plotting. I initially considered building this package in Python, but in the end I wanted to learn to use R, so here we are. Compared to other languages like Java or Python, R does seem a bit quirky at first, but it has some useful, built-in features for working with data. R has an extensive array of free add-in packages for manipulating and visualizing data, plus there is an excellent and free IDE available for R, RStudio.

If you are new to R, experimenting with firstapiR isn’t the worst way to get started, but there are some resources you should check out:

  1. Download and use the free version of RStudio.
  2. To learn R, I recommend starting with the Quick R Website
  3. Next, check out the R introduction on the main R documentation page
  4. Everything written by Hadley Wickham is excellent. His Advanced R website, R package website and his testthat and devtools packages were essential to the development of the firstapiR package.

Getting started - Creating a Session Object

Every HTTP request to the FIRST API requires a username, an authorization key, a four digit year that identifies the season of interest, and a header that specifies whether the data should be returned as XML or JSON. Having to type all of these parameters into every function call would make firstapiR very cumbersome to use, especially from the R console. The firstapiR package solves this problem with the GetSession() function, which returns a Session object that contains all of the parameters listed above. All other firstapiR functions require a Session object as the first parameter. Here’s an example:

# Create a Session object
sn <- firstapiR::GetSession("username", "key")

# Display the Session object.
sn
## $username
## [1] "username"
## 
## $key
## [1] "key"
## 
## $staging
## [1] FALSE
## 
## $season
## [1] 2016
## 
## $format
## [1] "data.frame"
## 
## attr(,"class")
## [1] "list"    "Session"

As you can see the Session object is really just an R list. It’s also an an instance of class “Session”, which will be useful to users who want to do some type checking.

In addition to the username and key, the Session object specifies the season, data format (“data.frame”, “xml”, or “json”) and whether the staging server should be used instead of the production server. Any of these parameters can be included as a named argument when calling GetSession(), or they can be modified later. For example:

# Create a Session and specify XML format
sn <- firstapiR::GetSession("username", "key", format = "xml")

# Change the season to 2015
sn$season <- 2015

# Display the Session object
sn
## $username
## [1] "username"
## 
## $key
## [1] "key"
## 
## $staging
## [1] FALSE
## 
## $season
## [1] 2015
## 
## $format
## [1] "xml"
## 
## attr(,"class")
## [1] "list"    "Session"

Using the Session Object

The following example shows how the session object is passed to a firstapiR function:

# Create a Session and use it in a firstapiR function
sn <- firstapiR::GetSession("username", "key")
dist <- firstapiR::GetDistricts(sn)

# Display the class of the object returned by GetDistricts()
class(dist)
## [1] "data.frame" "Districts"
# Display the data frame
dist
##   code                  name districtCount
## 1   IN          IndianaFIRST             8
## 2  CHS      FIRST Chesapeake             8
## 3   NC        North Carolina             8
## 4  MAR Mid-Atlantic Robotics             8
## 5  PCH             Peachtree             8
## 6  PNW     Pacific Northwest             8
## 7   NE           New England             8
## 8  FIM     FIRST In Michigan             8

By default, GetSession creates a Session object with the current year, format = "data.frame", and staging = TRUE. etDistricts() returns a data frame that is also an instance of class “Districts”. GetDistricts() is useful because the three-letter district codes are used as arguments to several other firatapiR functions.

Note: If you run the example above, passing the string “key” to GetSession(), firstapiR skips the HTTP request and pulls data from a local cache. See Why These Examples Work: Local verses HTTP Data below for an explanation of this feature.

Extracting Data from a Data Frame

R provides numerous methods for extracting, filtering, and manipulating data in data frames. Refer to the R resources listed in this vignette for additional information. Individual data elements can be extracted from a data frame using the syntax data_frame$column_name[[row_number]]. For example:

# Retrieve the item in th 6th row of the column named "code"
dist$code[[6]]
## [1] "PNW"

Here’s one of many slick techniques that are available in R:

# Retrieve the name of any district with code == "PNW"
dist$name[dist$code == "PNW"]
## [1] "Pacific Northwest"

Next Steps

This package provides a detailed help file for every firstapiR function. In RStudio, just type the name of the function in the help view search box. Or type help(function_name) at the R console command prompt. Here are the firstapiR functions:

External Functions in firstapiR Package
GetSession() GetServerStatus() GetSeason() GetDistricts()
GetEvents() GetTeams() GetSchedule() GetHybridSchedule()
GetMatchResults() GetScores() GetAlliances() GetRankings()
GetAwards() GetAwardsList()

In addition to help documents on each function, this package contains one other vignette: Overview of firstapiR Functions.

Advanced Topics

Why These Examples Work: Local verses HTTP Data

Hopefully you were able to figure out that “username” and “key” are not affiliated with a valid FIRST API account. These examples work because for all firstapiR functions, if the key value in the Session object is the literal value “key”, firstapiR skips the HTTP requests and extracts cached JSON or XML data from the R/sysdata.rda file. If you insert any other random value into the key parameter, or the username does not match an actual FIRST API username, the FIRST API will return a 401 status code and the firstapiR function will throw an error.

I added the local data feature for several reasons.

Attributes of Returned firstapiR Objects

All of the firstapiR functions add attributes to whatever data they return. These attributes allow you to identify whether the data is local or was extracted directly from the FIRST API server, when the data was extracted from the FIRST API server, and the URL that was sent to the server. To demonstrate, we’ll analyze the Districts data frame using R’s str() function, which displays the structure of any object:

# Display the structure and attributes of the dist object
str(dist)
## Classes 'Districts' and 'data.frame':    8 obs. of  3 variables:
##  $ code         : chr  "IN" "CHS" "NC" "MAR" ...
##  $ name         : chr  "IndianaFIRST" "FIRST Chesapeake" "North Carolina" "Mid-Atlantic Robotics" ...
##  $ districtCount: int  8 8 8 8 8 8 8 8
##  - attr(*, "url")= chr "https://frc-api.firstinspires.org/v2.0/2016/districts"
##  - attr(*, "local_test_data")= logi TRUE
##  - attr(*, "local_url")= chr "https://frc-api.firstinspires.org/v2.0/2016/districts"
##  - attr(*, "time_downloaded")= POSIXct, format: "2016-09-17 08:52:14"
##  - attr(*, "last_modified")= chr "Thu, 10 Dec 2015 01:34:23 GMT"

The attribute local_test_data is set to TRUE if the object was created from cached data in the R/sysdata.rda file. The local_url attribute contains the actual URL that was sent to the FIRST API server to request the data, and the time_downloaded attribute shows when the data was downloaded from the server.

For non-local, HTTP data, local_test_data will be set to FALSE, and local_url will be NULL. The time_downloaded attribute will contain the time that the HTTP request was received, based on the local system time.

There is also a url attribute. This attribute always contains the URL that is constructed from the arguments passed to the firstapiR function. Normally, this is the actual URL that is sent to the FIRST API server, but when extracting local data, this URL is mostly ignored. In the GetDistricts() example, local_url matches url because GetDistricts has no optional parameters and there is only one way to call this function. Most other firstapiR functions have many optional parameters and a multitude of possible return values. Since it’s not practical to cache the entire FIRST API server, when requesting local data (by setting the key parameter to “key”), firstapiR ignores the optional parameters. The local data will be of the same type and format as what was requested. In these situations the url attribute will represent was was requested, and the local_url attribute will describe what was cached and returned.

Use the attr(object, attribute_name) function and syntax to retrive an attribute from an object.

Open the data-raw/data.R folder (only available in the firstapiR github repository) to see the firstapiR commands that were used to generate the local data.

Testing firstapiR on Your System

The firstapiR package includes several automated tests in the tests/testthat folder. Users can run these tests if they have the testthat package installed on their system. Run all of the tests by running testthat::test_dir(path_to_tests/testthat_folder) at the R console.

If you run the test_dir command, you’ll probably notice that several tests are skipped. The tests are set up such that most of them can run without an internet connection or a FIRST API account. This is OK because local data requests use almost all of the firstapiR code that would be used for an actual HTTP request, including evaluation of the function arguments, constructing the URL and HTTP headers, and creating and formatting the data frame from JSON text. (If you specify the data frame format, firstapiR actually requests JSON text from the FIRST API server, because JSON is more compact than XML.) Only the actual HTTP request is skipped.

If you have a username and authorization key assigned by FIRST, then you can run all tests. Store your username and key in character vectors named “username” and “key”. Then run test_dir from the R console. The tests will detect that the variables username and key exist and will run tests that make actual HTTP calls to the FIRST API server. If either your username or key are incorrect, the tests will fail due to an HTTP 401 error.

Ask Questions

Post an issue on the firstapiR github repository if you have questions, find bugs or have recommendations for the next version.

Next Vignette

Overview of firstapiR Functions