The Getting Started vignette covered how to use the GetSession()
function to create a Session object and how to use that Session object in other firstapiR functions. This vignette provides an overview of the remaining firstapiR functions. For detailed information on each function, type help(function_name)
at the console or in the RStudio help view search box.
This guide is for version 2.0.1 of the firstapiR package. Guidance for version 1.0.0 of firstapiR is located here.
There are several functions that take no arguments other than the Session
argument.
GetServerStatus(session)
GetSeason(session)
GetDistricts(session)
GetAwardsList(session)
All other firstapiR functions take at least a few additional arguments. Most of the additional arguments are optional and, usually, only one or two of the additional arguments are used at any one time.
GetEvents(session, event, team, district, exclude_district)
GetTeams(session, team, event, district, state, page)
GetSchedule(session, event, level, team, start, end)
GetHybridSchedule(session, event, level, start, end)
GetMatchResults(session, event, level, team, match, start, end)
GetScores(session, event, level, team, match, start, end)
GetAlliances(session, event)
GetRankings(session, event, team, top)
GetAwards(session, event, team)
Many of the same arguments are used in several different firstapiR functions.
The four digit FRC team number.
A code representing a FIRST district. Use GetDistricts() to obtain the district codes that can be used in other firstapiR functions:
An event code, such as WAAMV (disctrict competition held at Auburn MountainView High School in Washington State) or PNCMP (Pacific Northwest District Championships). Use the GetEvents() function to get the event codes:
sn <- GetSession("username", "key")
PNW_events <- GetEvents(sn, district = "PNW")
PNW_events[, c("code", "name")]
## code name
## 1 ORORE PNW District - Clackamas Academy of Industrial Science Event
## 2 ORPHI PNW District - Philomath Event
## 3 ORWIL PNW District - Wilsonville Event
## 4 PNCMP Pacific Northwest District Championship sponsored by Autodesk
## 5 WAAHS PNW District - Auburn Event
## 6 WAAMV PNW District - Auburn Mountainview Event
## 7 WAELL PNW District - Central Washington University Event
## 8 WAMOU PNW District - Mount Vernon Event
## 9 WASNO PNW District - Glacier Peak Event
## 10 WASPO PNW District - West Valley Event
## code dateStart
## 1 ORORE 2016-03-31T00:00:00
## 2 ORPHI 2016-03-24T00:00:00
## 3 ORWIL 2016-03-10T00:00:00
## 4 PNCMP 2016-04-06T00:00:00
## 5 WAAHS 2016-04-01T00:00:00
## 6 WAAMV 2016-03-03T00:00:00
## 7 WAELL 2016-03-17T00:00:00
## 8 WAMOU 2016-03-18T00:00:00
## 9 WASNO 2016-03-11T00:00:00
## 10 WASPO 2016-03-03T00:00:00
Either “playoff” or “qual”. Defaults to “qual”.
Integers specifying the range of matches that will be included in the returned data.
There is one firstapiR function, GetTeams()
, that accepts the page
argument. When requesting data on FRC teams, the FIRST API will split the results into multiple pages if there are more than 65 teams in the response, requiring a separate HTTP request for each page. Users that are requesting the data frame format can ignore the page
argument because GetTeams
will automatically detect if there are multiple pages in the response, conduct a separate HTTP request for each page, and merge the results into a single data frame. This feature is not available when XML or JSON formats are sepecifed in the Session$format
parameter. Users requesting XML or JSON formatted data will have to call GetTeams() for each page of data, incrementing the page
argument for each request.
There are two additional arguments that can be passed to almost all firstapiR functions (only GetSession()
and GetServerStatus()
do not accept them). The two arguments, which are always optional, are mod_since
and only_mod_since
. These two arguments help to reduce the load on the FIRST API server by allowing the server to skip the database query and send only a short HTTP response when the FIRST API server data has not changed since the user last queried the server.
Both of these arguments accept a character vector containing an HTTP formatted date and time string. If the user includes the mod_since
argument, and no data has changed on the FIRST API server since the date and time specified in the argument, the FIRST API server will provide an HTTP 304 response with no content. When this happens, irstapiR functions will return a logical character vector with the value NA
. Here is an example:
# Create an HTTP date-time string set to midnight GMT yesterday
mod_date <- httr::http_date(as.POSIXct(Sys.Date() - 1))
# Request recently changed data from the server
match_results <- firstapiR::GetMatchResults(sn, event = "PNCMP",
mod_since = mod_date)
# Assuming there have been no updates to the data since yesterday, this
# returns TRUE
is.na(match_results)
# The value passed to mod_since returned as an attribute, even when the
# result is NA
print(attr(match_results, "mod_since"))
If the user includes the only_mod_since
argument, the FIRST API server will return only the data that has changed since the date and time specified in the only_mod_since
argument. In no changes have been made, the FIRST API server provides a 304 response and firstapiR functions return a logical vector set to NA
.
# Create an HTTP date-time string set to midnight GMT yesterday
mod_date <- httr::http_date(as.POSIXct(Sys.Date() - 1))
# Request recently changed data from the server
match_results <- firstapiR::GetMatchResults(sn, event = "PNCMP",
only_mod_since = mod_date)
# Assuming there have been no updates to the data since yesterday, this
# returns TRUE
is.na(match_results)
# The value passed to mod_since returned as an attribute, even when the
# result is NA
print(attr(match_results, "only_mod_since"))
If the mod_since
or only_mod_since
arguments are not specified, the corresponding mod_since
or only_mod_sinceattribute attached to the return value will be set to
NULL`.
Users can keep track of the date and time provided in the last_modified
attribute, which corresponds to the most recent date and time that the information changed on the FIRST API server, and use this date and time to request only new data from the server. If a user repeats a firstapiR function call with the same arguments and sets the mod_since
or only_mod_since
argument to the last_modified
attribute value from the intial firstapiR function call, the FIRST API server will return all requested data – the same data that was provided in the first function call. Users who would rather receive a 304 response in this situation should either add at least a second to the last_modified
value, or should instead use the time_downloaded
attribute value to set the mod_since
or only_mod_since
arguments.
The functions GetSchedule()
, GetHybridSchedule()
, and GetMatchResults()
return data frames with one row per team. For example, let’s take a look at the first two qualification matches from the 2016 Pacific Northwest District Championships:
sn <- firstapiR::GetSession("username", "key")
match_results <- firstapiR::GetMatchResults(sn, "PNCMP", level = "qual")
match_results[1:12, c("match", "alliance", "station", "team", "scoreAuto",
"scoreFinal")]
## match alliance station team scoreAuto scoreFinal
## q.1.blue1 1 Blue Blue1 4915 30 102
## q.1.blue2 1 Blue Blue2 3674 30 102
## q.1.blue3 1 Blue Blue3 4125 30 102
## q.1.red1 1 Red Red1 1318 32 107
## q.1.red2 1 Red Red2 2907 32 107
## q.1.red3 1 Red Red3 2944 32 107
## q.2.blue1 2 Blue Blue1 2374 30 126
## q.2.blue2 2 Blue Blue2 2557 30 126
## q.2.blue3 2 Blue Blue3 5920 30 126
## q.2.red1 2 Red Red1 1595 30 103
## q.2.red2 2 Red Red2 1425 30 103
## q.2.red3 2 Red Red3 2147 30 103
There is one team listed in each row, and it takes six rows to provide all of the information from a single match. This is called team shape. This format is useful for calculating summary statistics for individual teams. For example, to see average scores for the ten teams with the highest scores:
agg_scores <- aggregate(match_results[c("scoreFinal", "scoreAuto",
"scoreFoul")],
list("team" = match_results$team), mean)
agg_scores[order(agg_scores$scoreFinal, decreasing = TRUE), ][1:10, ]
## team scoreFinal scoreAuto scoreFoul
## 12 1983 123.1667 32.16667 4.166667
## 19 2557 121.1667 28.16667 2.916667
## 1 360 118.6667 30.83333 4.166667
## 9 1540 118.1667 27.33333 3.750000
## 46 4131 114.5833 25.41667 4.583333
## 60 5803 114.5000 28.33333 2.500000
## 49 4450 114.2500 28.75000 3.750000
## 6 1318 114.0000 28.50000 3.750000
## 63 5942 112.9167 27.50000 1.666667
## 7 1425 111.7500 24.33333 1.666667
Data frames in team shape will have their shape attribute set to “team”.
## [1] "team"
For some calculations, such as offensive power rating (OPR), the alliance shape, with three teams per row and two rows per match (one row each for the red and blue alliances), is more suitable. The function ToAllianceShape()
will reshape Schedule, HybridSchedule, or MatchResults data frames from team to alliance shape.
mresults_alliance <- firstapiR::ToAllianceShape(match_results)
mresults_alliance[1:4, c("match", "alliance", "team.1", "team.2", "team.3",
"scoreAuto", "scoreFinal")]
## match alliance team.1 team.2 team.3 scoreAuto scoreFinal
## 1.blue 1 Blue 4915 3674 4125 30 102
## 1.red 1 Red 1318 2907 2944 32 107
## 2.blue 2 Blue 2374 2557 5920 30 126
## 2.red 2 Red 1595 1425 2147 30 103
Data frames in alliance shape will have their shape attribute set to “alliance”.
## [1] "alliance"
Finally, Schedule, HybridSchedule, and MatchResults data frames may be converted from team to match shape.
mresults_match <- firstapiR::ToMatchShape(match_results)
mresults_match[1:2, c("match", "team.Red1", "team.Red2", "team.Red3",
"team.Blue1", "team.Blue2", "team.Blue3",
"scoreFinal.Blue", "scoreFinal.Red")]
## match team.Red1 team.Red2 team.Red3 team.Blue1 team.Blue2 team.Blue3
## 1 1 1318 2907 2944 4915 3674 4125
## 2 2 1595 1425 2147 2374 2557 5920
## scoreFinal.Blue scoreFinal.Red
## 1 102 107
## 2 126 103
The ToTeamShape()
function will convert match and alliance data frames back to team shape. This function depends on the ReshapeWide attribute, which is added to the match and alliance data frames by R’s reshape()
function. ToTeamShape()
will not work if the ReshapeWide attribute is deleted.
To convert a data frame from match to alliance shape or vice-versa, first convert the data frame back to team shape.
Use firstapiR’s SaveData()
function to open a save file dialog box and save data to an RDS data file. The ReadData()
function opens an open file dialog and returns the value saved in the RDS file. Refer to R’s documentation on the saveRDS()
and `readRDS()’ functions for more information on RDS data files.
Sometimes it’s handy to get all the available information for an FRC competition with single command. The GetAll()
function retrieves all data for a specific event and stores the data in a list. I recommend not using this function during competitions to avoid overloading the server. Also, save the event data to a file so it only needs to be downloaded once.
Version 2.0.1 of firstapiR includes all competition data for the 2016 FRC championships in St. Louis. Data for each subdivision and the finals are available in R lists named archimedes2016
, carson2016
, carver2016
, curie2016
, galileo2016
, hopper2016
, newton2016
, tesla2016
, and einstein2016
.
## [1] "season" "event" "teams" "schedule.qual"
## [5] "schedule.playoff" "hybrid.qual" "hybrid.playoff" "matches.qual"
## [9] "matches.playoff" "scores.qual" "scores.playoff" "results.qual"
## [13] "results.playoff" "rankings" "alliances" "awards"
## number name captain round1 round2 round3 backup backupReplaced
## 1 1 Alliance 1 3546 166 858 3618 NA NA
## 2 2 Alliance 2 1089 1983 4469 836 NA NA
## 3 3 Alliance 3 25 2848 4329 1885 NA NA
## 4 4 Alliance 4 5803 3310 2168 5940 NA NA
## 5 5 Alliance 5 5406 3641 1261 2883 NA NA
## 6 6 Alliance 6 639 3990 1662 287 NA NA
## 7 7 Alliance 7 3005 876 2557 4061 NA NA
## 8 8 Alliance 8 694 3339 379 1511 NA NA
The GetScores()
function retrieves detailed performance data for for both the red and blue alliances for each match. However the Scores data frame does not list the teams that were assigned to each alliance. The function MergeResults()
merges a HybridResults data frame with a Scores data frame to create a Results data frame that contains both the detailed match performance data and the teams that were assigned to each match.
# Merge MatchResults and Scores data frames
curie_results <- firstapiR::MergeResults(firstapiR::curie2016$hybrid.qual,
firstapiR::curie2016$scores.qual)
# Show structure of resulting data frame
str(curie_results)
## Classes 'Results' and 'data.frame': 750 obs. of 49 variables:
## $ match : int 1 1 1 1 1 1 2 2 2 2 ...
## $ level : Factor w/ 1 level "Qualification": 1 1 1 1 1 1 1 1 1 1 ...
## $ alliance : Factor w/ 2 levels "Blue","Red": 1 1 1 2 2 2 1 1 1 2 ...
## $ description : chr "Qualification 1 (B)" "Qualification 1 (B)" "Qualification 1 (B)" "Qualification 1 (B)" ...
## $ start : chr "2016-04-28T08:30:00" "2016-04-28T08:30:00" "2016-04-28T08:30:00" "2016-04-28T08:30:00" ...
## $ actualStart : chr "2016-04-28T08:31:22.123" "2016-04-28T08:31:22.123" "2016-04-28T08:31:22.123" "2016-04-28T08:31:22.123" ...
## $ team : Factor w/ 75 levels "8","25","166",..: 34 6 12 29 74 54 7 65 45 8 ...
## $ station : Factor w/ 6 levels "Blue1","Blue2",..: 1 2 3 4 5 6 1 2 3 4 ...
## $ surrogate : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ disqualified : logi FALSE FALSE FALSE FALSE FALSE FALSE ...
## $ AudienceGroup : Factor w/ 4 levels "GroupA","GroupB",..: 2 2 2 2 2 2 2 2 2 2 ...
## $ robot1Auto : Factor w/ 3 levels "Crossed","None",..: 1 1 1 3 3 3 1 1 1 3 ...
## $ robot2Auto : Factor w/ 3 levels "Crossed","None",..: 3 3 3 1 1 1 1 1 1 3 ...
## $ robot3Auto : Factor w/ 3 levels "Crossed","None",..: 1 1 1 3 3 3 1 1 1 1 ...
## $ autoBouldersLow : int 0 0 0 0 0 0 0 0 0 0 ...
## $ autoBouldersHigh : int 1 1 1 0 0 0 0 0 0 1 ...
## $ teleopBouldersLow : int 6 6 6 6 6 6 5 5 5 4 ...
## $ teleopBouldersHigh : int 4 4 4 0 0 0 12 12 12 1 ...
## $ towerFaceA : Factor w/ 4 levels "Challenged","None",..: 1 1 1 2 2 2 1 1 1 1 ...
## $ towerFaceB : Factor w/ 4 levels "Challenged","None",..: 1 1 1 4 4 4 3 3 3 3 ...
## $ towerFaceC : Factor w/ 4 levels "Challenged","None",..: 1 1 1 4 4 4 2 2 2 1 ...
## $ towerEndStrength : int 5 5 5 -1 -1 -1 4 4 4 -6 ...
## $ teleopTowerCaptured : logi TRUE TRUE TRUE FALSE FALSE FALSE ...
## $ teleopDefensesBreached: logi TRUE TRUE TRUE TRUE TRUE TRUE ...
## $ position1crossings : int 2 2 2 2 2 2 2 2 2 2 ...
## $ position2 : Factor w/ 7 levels "A_ChevalDeFrise",..: 6 6 6 1 1 1 6 6 6 6 ...
## $ position2crossings : int 2 2 2 1 1 1 2 2 2 2 ...
## $ position3 : Factor w/ 5 levels "A_ChevalDeFrise",..: 3 3 3 3 3 3 3 3 3 3 ...
## $ position3crossings : int 2 2 2 2 2 2 2 2 2 2 ...
## $ position4 : Factor w/ 8 levels "A_ChevalDeFrise",..: 7 7 7 6 6 6 7 7 7 1 ...
## $ position4crossings : int 2 2 2 2 2 2 2 2 2 2 ...
## $ position5 : Factor w/ 8 levels "A_ChevalDeFrise",..: 1 1 1 7 7 7 1 1 1 7 ...
## $ position5crossings : int 2 2 2 2 2 2 2 2 2 2 ...
## $ foulCount : int 0 0 0 0 0 0 0 0 0 0 ...
## $ techFoulCount : int 0 0 0 1 1 1 1 1 1 0 ...
## $ autoPoints : int 32 32 32 14 14 14 30 30 30 24 ...
## $ autoReachPoints : int 2 2 2 4 4 4 0 0 0 4 ...
## $ autoCrossingPoints : int 20 20 20 10 10 10 30 30 30 10 ...
## $ autoBoulderPoints : int 10 10 10 0 0 0 0 0 0 10 ...
## $ teleopPoints : int 87 87 87 52 52 52 125 125 125 83 ...
## $ teleopCrossingPoints : int 40 40 40 40 40 40 35 35 35 45 ...
## $ teleopBoulderPoints : int 32 32 32 12 12 12 70 70 70 13 ...
## $ teleopChallengePoints : int 15 15 15 0 0 0 5 5 5 10 ...
## $ teleopScalePoints : int 0 0 0 0 0 0 15 15 15 15 ...
## $ breachPoints : int 0 0 0 0 0 0 0 0 0 0 ...
## $ capturePoints : int 0 0 0 0 0 0 0 0 0 0 ...
## $ adjustPoints : int 0 0 0 0 0 0 0 0 0 0 ...
## $ foulPoints : int 5 5 5 0 0 0 0 0 0 5 ...
## $ totalPoints : int 124 124 124 66 66 66 155 155 155 112 ...
## - attr(*, "url")= chr "https://frc-api.firstinspires.org/v2.0/2016/schedule/CURIE/qual/hybrid" "https://frc-api.firstinspires.org/v2.0/2016/scores/CURIE/qual"
Actually, using MergeResults()
is not necessary for preloaded data (such as curie2016
or for any data structures created with the GetAll()
function. These lists already contain merged data frames – see curie2016$results.qual
and curie2016$results.playoff
for examples. I used the preloaded data to demonstrate the MergeResults()
function because that’s an easy way to do it.
There are several functions provide data for either qualification or playoff matches, but not both. Use R’s rbind()
function to merge this data into a single data frame.
## [1] 750
## [1] 102
# Merge qualification and playoff data into a single table
all_matches <- rbind(firstapiR::curie2016$matches.qual,
firstapiR::curie2016$matches.playoff)
# Total Matches
nrow(all_matches)
## [1] 852
Post an issue on the firstapiR github repository if you have questions, find bugs or have recommendations for the next version.