intro.Rmd
Hello, friends.
You, like me, might be a big college football fan who is interested in statistics and analytics, wanting to get into the game for yourself. This simple tutorial is just the way to do that!
The cfbscrapR
package is just the way to get started with analytics. cfbscrapR
is a wrapper for the CollegeFootballData.com API, which lets you pull data directly from the site into the statistical software R for analysis. What kind of data can you get with cfbscrapR
?
We’ll learn how to do three things in this document:
I hope you enjoy! Know that there is a learning curve to all this! It’s difficult, and at times can be frustrating. The best way to learn this stuff is to play around with it, understand the syntax, and beat your head against the wall for a little bit until it works.
-Parker Fleming | [@statsowar](twitter.com/statsowar)
First things first, you need to install R and download R Studio. I’ll direct you to this link. Go do that now, then come back.
Now that we have R and R Studio all put together, it’s time to get organized. That’s often the first step of any project working with data, and the more organized you can be, the easier of a time you’ll have trying to wrangle and analyze the data.
Notice there are four quadrants to your R Studio setup: the top right is the Environment tab, which shows you the data, values, and functions you currently have loaded. The bottom right is where you’ll see your charts and graphs in the viewer or plots tab. The bottom left is the console, where output goes. When you execute code, the terminal responds and shows you some stuff down there. The top left is the place you’ll live; it’s where you can edit scripts. We’ll load a new project and then get started.
In the top right of your R Studio window, there will be a small drop-down menu that says “None”. Click it, and select “New Project.” Title your new folder something like “CFB Analysis”.
This takes care of setting your working directory, so everything you create and output will be saved in that folder.
What should pop up then is a completely fresh R project. Click the white square with a green plus sign in the top left of the window and select “New R Script”. A script is the place you will write your commands before you execute them. You can work in the console, which is just below the scripts and where output is displayed, but I find it easier to stick to scripts - that way, you can save what you’ve done and replicate it easily, like I do with the EPA rankings, for example.
Throughout this document, I’ll have lines of code interspersed with commentary. What I’d advise is that you read the commentary, then copy the code into your script and then run the code from there. Then, at the end, you’ll have a complete script that will guide you through CFB Data analysis.
What we’ll do here is a template for an initial data ingest.
To use the packages, we need to do two things. First, one time only on your machine, you need to install the packages. Then, every time you open up R Studio, you will need to load the packages.
To install the packages, simply run each line of code below once (without the #
at the beginning):
#install.packages('tidyverse')
#installpackages('easypackages')
#install.packages("devtools")
#devtools::install_github("meysubb/cfbscrapR")
#install.packages('ggimage')
#install.packages('gt')
Don’t worry about what all that means for now. Now, after running those lines of code, you have all the packages you need to get started with college football analytics. Let’s load the packages and download the play-by-play data for 2019. First we load the three necessary packages, then we’re going to run a loop over the number of weeks in the season and use the cfb_pbp_data()
function, which pulls the play-by-play.
We’re going to pull the data, clean it, then select some relevant variables, and then we’ll go forward with moving the data.
Note in the code how we defined what pbp_2019
is: we used the little arrow (<-
). If you’re on mac, you can press option and the dash key to pull one of those little guys up. That’s just R’s fun way of saying “name that thing this”.
easypackages::libraries('tidyverse', 'cfbscrapR', 'ggimage', 'gt')
pbp_2019 <- data.frame()
seasons <- 2019
pbp_2019 <- purrr::map_df(seasons, function(x) {
readRDS(
url(
glue::glue("https://raw.githubusercontent.com/saiemgilani/cfbscrapR-data/master/data/rds/pbp_players_pos_{x}.rds")
)
)
})
cfb_pbp_data()
function
week_vector = 1:15
year_vector = 2019
weekly_year_df = expand.grid(year = year_vector, week = week_vector)
### scrape yearly
year_split = split(weekly_year_df, weekly_year_df$year)
### starting time
yr_epa_start_time <- proc.time()
for (i in 1:length(year_split)) {
print(paste0("Working on ", year_split[[i]][1,1]))
year_split[[i]] = year_split[[i]] %>%
mutate(
pbp = purrr::map2(
.x = year,
.y = week,
cfb_pbp_data,
season_type = 'both',
epa_wpa=TRUE
))
Sys.sleep(1)
}
### calculate time elapsed
yr_epa_season_run <- proc.time() - yr_epa_start_time
print(yr_epa_season_run['elapsed']/60)
year_split19 = lapply(year_split, function(x) {
x %>% tidyr::unnest(pbp)
})
pbp_2019 = bind_rows(year_split19)
This code will take a few minutes (~8:10) to run - it’s pulling a lot of data from the API at once. Give your R console a break until it finishes! You’ll know it’s done running when you can see pbp_2019
in the “Environment” window in the top right of your R console (and when the little caret >
pops up in your terminal, at the bottom left).
Now, we have the entire season’s worth of play-by-play data stored in an object called pbp_2019
. All of that text in the cfb_pbp_data()
is customizable: you could select only a specific week, you could pull data from bowl games by changing season_type to “both”.
Let’s pull the game data, using the cfb_game_info()
function, and merge the two. Then, we’ll make use of the dplyr::filter
and dplyr::mutate
functions from the tidyverse
.
#Game level data
games_19 <- cfb_game_info(2019)
#Join Games and Play-by-Play
plays19 <- left_join(pbp_2019, games_19, by = c("game_id" = "game_id"))
Above, we pulled 2019 game data from the API into an object called games_19
, and then we used dplyr::left_join
to merge each play to the information of the game it happened in, an object called plays19
. We matched the plays to the games by telling R that the column game_id
in pbp_2019
was the same as the column id
in the games_19
object.
Before we break down what we did to create the pbp object, we need to discuss two things:
Filtering on conditions: We will use the double equality (==
) to identify conditions we need to meet for our filter function. We can also use !=, “not equals”, to select values on that condition (i.e. offense_play != "TCU"
would remove TCU from the data), and we can use the standard greater than > and less than <. You might have to stop and think a bit before you write your filter function, so just make sure you know what it is you are actually selecting.
the pipe: %>%
is the magrittr pipe. The pipe is extremely handy. Instead of us having to type a function and select the data we want to apply that function to over and over again, the pipe tells R what to do in the structure of : “get this thing and then do this to it.”
I’m naming our dataset of play by play data filtered pbp
. I don’t like to overwrite my data once I’ve imported it, so I’m going to give it a new name. That way, if I mess something up along the way, I can go back to the start and clean up without too much hassle.
We’ll use the indicator variables rush
and pass
to select every play categorized as rushes or passes. (Yes, this leaves out special teams and yes this leaves out penalties. We’re starting small, and can always go back later.)
Also note we use the |
symbol to denote “or” in our filter function. We’ll filter the data for any observations that are runs (rush == 1
) or passes (pass == 1
), and store it in a new object called plays.
But we won’t stop there! The beauty of the pipe is that we can do multiple operations, all strung together. So, in the code below, we’ll create a new object called “pbp”. To create this object, we’ll do three things:
plays19
, remove all plays that aren’t rushes or passes: dplyr::filter(rush == 1 | pass == 1)
AND THENdplyr::filter()
, I tell R to select all observations that are not (!) missing the variable home_conference or away_conference. As all FBS teams have a conference in the data, this will remove all FCS teams. Note: is.na(x)
means “is missing variable x”, so !is.na(x)
means “is not missing variable x.”dplyr::mutate()
is R’s weird way of saying “make a new variable!” So, we’ll create three new variables:abs_diff
is the absolute value of the score difference, created using the abs()
function. This variable helps us define the garbage time filter.garbage
is an indicator variable for whether a play is in garbage time, as defined by our friend Bill Connelly. Garbage time is when the score difference is greater than 43 in the first quarter, 37 in the second quarter, 27 in the third quarter, and 22 in the fourth quarter. To create this variable, we use the ifelse()
, which takes three arguments: a condition, yes, and no. ifelse basically says “if this condition is met, then make this variable this value, or do something else.” We’ve strung multiple ifelse()
conditions together to cover all of our bases.success
: We use the same ifelse()
logic to create a binary variable that indicates whether a play was successful or not, again, as defined by Bill C.
#Create Garbage time filter, eliminate FCS games,
#filter for only rushes and passes, create success variable
pbp <- plays19 %>% filter(rush == 1| pass == 1) %>%
filter(!is.na(home_conference) & !is.na(away_conference)) %>%
mutate(abs_diff = abs(score_diff),
garbage = ifelse(period == 1 & abs_diff > 43, 1,
ifelse(period == 2 & abs_diff > 37, 1,
ifelse(period == 3 & abs_diff > 27, 1,
ifelse(period == 4 & abs_diff > 22, 1, 0)))),
success = ifelse(down == 1 & yards_gained > .5*distance, 1,
ifelse(down == 2 & yards_gained > .7*distance, 1,
ifelse((down == 3 | down == 4) & yards_gained >=distance, 1, 0))))
Now we have a clean dataset of every rush and pass that happened in 2019. (Quick note: unfortunately, due to the way the pbp data is generated on ESPN, QB scrambles from dropbacks are coded as rushes. It’s not ideal, but it’s not a deal-breaker; just something to remember as you do your analysis).
Let’s look at it!
glimpse(pbp)
## Rows: 101,383
## Columns: 354
## $ year <int> 2019, 2019, 2019, 2019, 2019, 2019...
## $ week.x <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ id_play <dbl> 4.011107e+17, 4.011107e+17, 4.0111...
## $ game_id <int> 401110720, 401110720, 401110720, 4...
## $ game_play_number <int> 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, ...
## $ half_play_number <int> 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, ...
## $ drive_play_number <int> 2, 3, 4, 1, 2, 3, 1, 2, 1, 2, 3, 4...
## $ pos_team <chr> "Alabama", "Alabama", "Alabama", "...
## $ def_pos_team <chr> "Duke", "Duke", "Duke", "Alabama",...
## $ pos_team_score <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ def_pos_team_score <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ half <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ period <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ clock.minutes <int> 14, 14, 13, 12, 12, 11, 11, 11, 11...
## $ clock.seconds <int> 46, 15, 30, 50, 27, 55, 42, 24, 11...
## $ play_type <chr> "Rush", "Pass Reception", "Sack", ...
## $ play_text <chr> "Jerome Ford run for 1 yd to the A...
## $ down <int> 1, 2, 3, 1, 2, 3, 1, 2, 1, 2, 3, 1...
## $ distance <int> 10, 9, 7, 10, 11, 7, 10, 4, 10, 5,...
## $ yards_to_goal <int> 78, 77, 75, 55, 56, 52, 83, 77, 26...
## $ yards_gained <int> 1, 2, -6, -1, 4, 0, 6, 3, 5, 0, 5,...
## $ EPA <dbl> -0.75165109, -0.71866524, -1.95835...
## $ ep_before <dbl> 0.5592779, -0.1923732, -0.9110384,...
## $ ep_after <dbl> -0.1923732, -0.9110384, -2.8693887...
## $ wpa <dbl> -0.0207255, -0.0163692, -0.0692158...
## $ wp_before <dbl> 0.4836533, 0.4629278, 0.4465586, 0...
## $ wp_after <dbl> 0.4629278, 0.4465586, 0.3773428, 0...
## $ def_wp_before <dbl> 0.5163467, 0.5370722, 0.5534414, 0...
## $ def_wp_after <dbl> 0.5370722, 0.5534414, 0.6226572, 0...
## $ penalty_detail <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_penalty <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ penalty_1st_conv <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ new_series <int> 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1...
## $ firstD_by_kickoff <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ firstD_by_poss <int> 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0...
## $ firstD_by_penalty <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ firstD_by_yards <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1...
## $ def_EPA <dbl> 0.75165109, 0.71866524, 1.95835027...
## $ home_EPA <dbl> -0.75165109, -0.71866524, -1.95835...
## $ away_EPA <dbl> 0.75165109, 0.71866524, 1.95835027...
## $ home_EPA_rush <dbl> -0.7516511, NA, NA, NA, NA, NA, 0....
## $ away_EPA_rush <dbl> NA, NA, NA, -0.98565387, -0.430616...
## $ home_EPA_pass <dbl> NA, -0.71866524, -1.95835027, NA, ...
## $ away_EPA_pass <dbl> NA, NA, NA, NA, NA, -1.8876295, NA...
## $ total_home_EPA <dbl> -1.0255413, -1.7442065, -3.7025568...
## $ total_away_EPA <dbl> 1.0255413, 1.7442065, 3.7025568, -...
## $ total_home_EPA_rush <dbl> -0.7516511, -0.7516511, -0.7516511...
## $ total_away_EPA_rush <dbl> 0.0000000, 0.0000000, 0.0000000, -...
## $ total_home_EPA_pass <dbl> 0.0000000, -0.7186652, -2.6770155,...
## $ total_away_EPA_pass <dbl> 0.000000, 0.000000, 0.000000, 0.00...
## $ net_home_EPA <dbl> -2.0510826, -3.4884131, -7.4051136...
## $ net_away_EPA <dbl> 2.0510826, 3.4884131, 7.4051136, -...
## $ net_home_EPA_rush <dbl> -0.7516511, -0.7516511, -0.7516511...
## $ net_away_EPA_rush <dbl> 0.7516511, 0.7516511, 0.7516511, -...
## $ net_home_EPA_pass <dbl> 0.00000000, -0.71866524, -2.677015...
## $ net_away_EPA_pass <dbl> 0.00000000, 0.71866524, 2.67701551...
## $ success <dbl> 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0...
## $ epa_success <int> 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0...
## $ rz_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1...
## $ scoring_opp <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1...
## $ middle_8 <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ stuffed_run <int> 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0...
## $ change_of_pos_team <int> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0...
## $ downs_turnover <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ turnover <int> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0...
## $ pos_score_diff_start <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ pos_score_pts <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ log_ydstogo <dbl> 2.302585, 2.197225, 1.945910, 2.30...
## $ ExpScoreDiff <dbl> 0.5592779, -0.1923732, -0.9110384,...
## $ ExpScoreDiff_Time_Ratio <dbl> 1.559180e-04, -5.409820e-05, -2.59...
## $ half_clock.minutes <int> 29, 29, 28, 27, 27, 26, 26, 26, 26...
## $ TimeSecsRem <int> 1786, 1755, 1710, 1670, 1647, 1615...
## $ adj_TimeSecsRem <int> 3586, 3555, 3510, 3470, 3447, 3415...
## $ Goal_To_Go <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ Under_two <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ home <chr> "Alabama", "Alabama", "Alabama", "...
## $ away <chr> "Duke", "Duke", "Duke", "Duke", "D...
## $ home_wp_before <dbl> 0.4836533, 0.4629278, 0.4465586, 0...
## $ away_wp_before <dbl> 0.5163467, 0.5370722, 0.5534414, 0...
## $ home_wp_after <dbl> 0.4629278, 0.4465586, 0.3773428, 0...
## $ away_wp_after <dbl> 0.5370722, 0.5534414, 0.6226572, 0...
## $ end_of_half <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ pos_team_receives_2H_kickoff <int> 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1...
## $ lead_pos_team <chr> "Alabama", "Alabama", "Alabama", "...
## $ lead_play_type <chr> "Pass Reception", "Sack", "Punt", ...
## $ lag_pos_team <chr> "Alabama", "Alabama", "Alabama", "...
## $ lag_play_type <chr> "Kickoff", "Rush", "Pass Reception...
## $ orig_play_type <chr> "Rush", "Pass Reception", "Sack", ...
## $ Under_three <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ down_end <int> 2, 3, 4, 2, 3, 4, 2, 1, 2, 3, 1, 2...
## $ distance_end <int> 9, 7, 13, 11, 7, 7, 4, 10, 5, 5, 1...
## $ log_ydstogo_end <dbl> 2.197225, 1.945910, 2.564949, 2.39...
## $ yards_to_goal_end <int> 77, 75, 81, 56, 52, 52, 77, 26, 21...
## $ TimeSecsRem_end <int> 1755, 1710, 1677, 1647, 1615, 1609...
## $ Goal_To_Go_end <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ Under_two_end <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ offense_score_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ defense_score_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ ppa <dbl> -0.51421953, -0.22726486, -0.33794...
## $ yard_line <int> 22, 23, 25, 55, 56, 52, 17, 23, 26...
## $ scoring <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ pos_team_timeouts_rem_before <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ def_pos_team_timeouts_rem_before <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ pos_team_timeouts <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ def_pos_team_timeouts <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ pos_score_diff <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ pos_score_diff_start_end <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ offense_play <chr> "Alabama", "Alabama", "Alabama", "...
## $ defense_play <chr> "Duke", "Duke", "Duke", "Alabama",...
## $ offense_receives_2H_kickoff <int> 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1...
## $ change_of_poss <int> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0...
## $ score_pts <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ score_diff_start <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ score_diff <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ offense_score <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ defense_score <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ offense_conference <chr> "SEC", "SEC", "SEC", "ACC", "ACC",...
## $ defense_conference <chr> "ACC", "ACC", "ACC", "SEC", "SEC",...
## $ off_timeout_called <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ def_timeout_called <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ offense_timeouts <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ defense_timeouts <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ off_timeouts_rem_before <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ def_timeouts_rem_before <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ rusher_player_name <chr> "Jerome Ford", NA, NA, "Deon Jacks...
## $ yds_rushed <int> 1, NA, NA, -1, 4, NA, 6, 3, 5, 0, ...
## $ passer_player_name <chr> NA, "Tua Tagovailoa", "Tua Tagovai...
## $ receiver_player_name <chr> NA, "Jerome Ford", NA, NA, NA, "De...
## $ yds_receiving <int> NA, 2, NA, NA, NA, NA, NA, NA, NA,...
## $ yds_sacked <int> NA, NA, -6, NA, NA, NA, NA, NA, NA...
## $ sack_players <chr> NA, NA, "Koby Quansah ", NA, NA, N...
## $ sack_player_name <chr> NA, NA, "Koby Quansah", NA, NA, NA...
## $ sack_player_name2 <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ pass_breakup_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ interception_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_int_return <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ fumble_player_name <chr> NA, NA, NA, NA, NA, NA, NA, "Jerom...
## $ fumble_forced_player_name <chr> NA, NA, NA, NA, NA, NA, NA, "Edgar...
## $ fumble_recovered_player_name <chr> NA, NA, NA, NA, NA, NA, NA, "Duke ...
## $ yds_fumble_return <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ punter_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_punted <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ punt_returner_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_punt_return <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_punt_gained <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ punt_block_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ punt_block_return_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ fg_kicker_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_fg <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ fg_block_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ fg_return_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ kickoff_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_kickoff <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ kickoff_returner_player_name <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ yds_kickoff_return <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ new_id <int> 101855301, 101858401, 101866901, 1...
## $ orig_drive_number <int> 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4...
## $ drive_number <int> 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4...
## $ drive_result_detailed <chr> "Punt", "Punt", "Punt", "Punt", "P...
## $ new_drive_pts <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ drive_id <dbl><PHONE_NUMBER>,<PHONE_NUMBER>,<PHONE_NUMBER>...
## $ drive_result <chr> "PUNT", "PUNT", "PUNT", "PUNT", "P...
## $ drive_start_yards_to_goal <int> 78, 78, 78, 55, 55, 55, 83, 83, 26...
## $ drive_end_yards_to_goal <int> 81, 81, 81, 52, 52, 52, 77, 77, 7,...
## $ drive_yards <int> -3, -3, -3, 3, 3, 3, 9, 9, 19, 19,...
## $ drive_scoring <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ drive_pts <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ drive_start_period <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ drive_end_period <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ drive_time_minutes_start <int> 15, 15, 15, 12, 12, 12, 11, 11, 11...
## $ drive_time_seconds_start <int> 0, 0, 0, 57, 57, 57, 49, 49, 24, 2...
## $ drive_time_minutes_end <int> 12, 12, 12, 11, 11, 11, 11, 11, 8,...
## $ drive_time_seconds_end <int> 57, 57, 57, 49, 49, 49, 24, 24, 28...
## $ drive_time_minutes_elapsed <int> 2, 2, 2, 1, 1, 1, 0, 0, 2, 2, 2, 2...
## $ drive_time_seconds_elapsed <int> 3, 3, 3, 8, 8, 8, 25, 25, 56, 56, ...
## $ drive_numbers <int> 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0...
## $ number_of_drives <int> 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4...
## $ pts_scored <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ drive_result_detailed_flag <chr> NA, NA, NA, NA, NA, NA, NA, "Fumbl...
## $ drive_result2 <chr> "PUNT", "PUNT", "PUNT", "PUNT", "P...
## $ drive_num <int> 1, 1, 1, 2, 2, 2, 3, 3, 4, 4, 4, 4...
## $ lag_drive_result_detailed <chr> "Punt", "Punt", "Punt", "Punt", "P...
## $ lead_drive_result_detailed <chr> "Punt", "Punt", "Punt", "Punt", "P...
## $ lag_new_drive_pts <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ id_drive <dbl><PHONE_NUMBER>,<PHONE_NUMBER>,<PHONE_NUMBER>...
## $ rush <int> 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1...
## $ rush_td <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ pass <int> 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0...
## $ pass_td <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ completion <int> 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ pass_attempt <int> 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0...
## $ target <int> 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0...
## $ sack_vec <int> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ sack <int> 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ int <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ int_td <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ turnover_vec <int> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0...
## $ turnover_vec_lag <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0...
## $ turnover_indicator <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ kickoff_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ receives_2H_kickoff <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ missing_yard_flag <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ scoring_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ td_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ touchdown <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ safety <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ fumble_vec <int> 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0...
## $ kickoff_tb <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ kickoff_onside <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ kickoff_oob <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ kickoff_fair_catch <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ kickoff_downed <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ kickoff_safety <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ kick_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt_tb <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt_oob <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt_fair_catch <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt_downed <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt_safety <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ punt_blocked <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ penalty_safety <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ fg_inds <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ fg_made <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ fg_make_prob <dbl> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ No_Score_before <dbl> 0.002222828, 0.002621234, 0.003070...
## $ FG_before <dbl> 0.13957973, 0.12765729, 0.10311895...
## $ Opp_FG_before <dbl> 0.11677911, 0.13178555, 0.14795416...
## $ Opp_Safety_before <dbl> 0.0039577322, 0.0042226245, 0.0044...
## $ Opp_TD_before <dbl> 0.33202649, 0.37797217, 0.42432964...
## $ Safety_before <dbl> 0.003012376, 0.003185186, 0.003409...
## $ TD_before <dbl> 0.4024217, 0.3525560, 0.3136880, 0...
## $ No_Score_after <dbl> 0.002621234, 0.003070324, 0.003348...
## $ FG_after <dbl> 0.12765729, 0.10311895, 0.04506741...
## $ Opp_FG_after <dbl> 0.13178555, 0.14795416, 0.19444891...
## $ Opp_Safety_after <dbl> 0.0042226245, 0.0044297950, 0.0064...
## $ Opp_TD_after <dbl> 0.37797217, 0.42432964, 0.54616761...
## $ Safety_after <dbl> 0.003185186, 0.003409132, 0.003372...
## $ TD_after <dbl> 0.3525560, 0.3136880, 0.2011527, 0...
## $ position_reception <chr> NA, "RB", NA, NA, NA, NA, NA, NA, ...
## $ position_target <chr> NA, "RB", NA, NA, NA, "RB", NA, NA...
## $ position_completion <chr> NA, "QB", NA, NA, NA, NA, NA, NA, ...
## $ position_incompletion <chr> NA, NA, NA, NA, NA, "QB", NA, NA, ...
## $ position_sack_taken <chr> NA, NA, "QB", NA, NA, NA, NA, NA, ...
## $ position_sack <chr> NA, NA, "LB", NA, NA, NA, NA, NA, ...
## $ position_interception_thrown <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ position_interception <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ position_fumble <chr> NA, NA, NA, NA, NA, NA, NA, "RB", ...
## $ position_fumble_forced <chr> NA, NA, NA, NA, NA, NA, NA, "DT", ...
## $ position_fumble_recovered <chr> NA, NA, NA, NA, NA, NA, NA, "DE", ...
## $ position_pass_breakup <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ position_rush <chr> "RB", NA, NA, "RB", "RB", NA, "RB"...
## $ position_touchdown <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ season.x <int> 2019, 2019, 2019, 2019, 2019, 2019...
## $ opponent <chr> "Duke", "Duke", "Alabama", "Alabam...
## $ team_score <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ opponent_score <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ rush_player_id <int> 4372019, NA, NA, 4240455, 4240455,...
## $ rush_player <chr> "Jerome Ford", NA, NA, "Deon Jacks...
## $ rush_yds <int> 1, NA, NA, -1, 4, NA, 6, 3, 5, 0, ...
## $ reception_player_id <int> NA, 4372019, NA, NA, NA, NA, NA, N...
## $ reception_player <chr> NA, "Jerome Ford", NA, NA, NA, NA,...
## $ reception_yds <int> NA, 2, NA, NA, NA, NA, NA, NA, NA,...
## $ completion_player_id <int> NA, 4241479, NA, NA, NA, NA, NA, N...
## $ completion_player <chr> NA, "Tua Tagovailoa", NA, NA, NA, ...
## $ completion_yds <int> NA, 2, NA, NA, NA, NA, NA, NA, NA,...
## $ interception_player_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ interception_player <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ interception_stat <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ interception_thrown_player_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ interception_thrown_player <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ interception_thrown_stat <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ touchdown_player_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ touchdown_player <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ touchdown_stat <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ incompletion_player_id <int> NA, NA, NA, NA, NA, 3917793, NA, N...
## $ incompletion_player <chr> NA, NA, NA, NA, NA, "Quentin Harri...
## $ incompletion_stat <int> NA, NA, NA, NA, NA, 1, NA, NA, NA,...
## $ target_player_id <int> NA, NA, NA, NA, NA, 4240455, NA, N...
## $ target_player <chr> NA, NA, NA, NA, NA, "Deon Jackson"...
## $ target_stat <int> NA, NA, NA, NA, NA, 1, NA, NA, NA,...
## $ fumble_recovered_player_id <int> NA, NA, NA, NA, NA, NA, NA, 403604...
## $ fumble_recovered_player <chr> NA, NA, NA, NA, NA, NA, NA, "Tre H...
## $ fumble_recovered_stat <int> NA, NA, NA, NA, NA, NA, NA, 1, NA,...
## $ fumble_forced_player_id <int> NA, NA, NA, NA, NA, NA, NA, 311657...
## $ fumble_forced_player <chr> NA, NA, NA, NA, NA, NA, NA, "Edgar...
## $ fumble_forced_stat <int> NA, NA, NA, NA, NA, NA, NA, 1, NA,...
## $ fumble_player_id <int> NA, NA, NA, NA, NA, NA, NA, 437201...
## $ fumble_player <chr> NA, NA, NA, NA, NA, NA, NA, "Jerom...
## $ fumble_stat <int> NA, NA, NA, NA, NA, NA, NA, 1, NA,...
## $ sack_player_id <int> NA, NA, 4036041, NA, NA, NA, NA, N...
## $ sack_player <chr> NA, NA, "Koby Quansah", NA, NA, NA...
## $ sack_stat <int> NA, NA, 1, NA, NA, NA, NA, NA, NA,...
## $ sack_taken_player_id <int> NA, NA, 4241479, NA, NA, NA, NA, N...
## $ sack_taken_player <chr> NA, NA, "Tua Tagovailoa", NA, NA, ...
## $ sack_taken_stat <int> NA, NA, 6, NA, NA, NA, NA, NA, NA,...
## $ pass_breakup_player_id <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ pass_breakup_player <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ pass_breakup_stat <int> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ play_id <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ penalty_flag <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ penalty_declined <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ penalty_no_play <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ penalty_offset <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ penalty_text <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ penalty_play_text <chr> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ row <int> 2, 3, 4, 6, 7, 8, 10, 11, 12, 13, ...
## $ drive_event_number <int> 2, 3, 4, 1, 2, 3, 1, 2, 1, 2, 3, 4...
## $ lag_play_type2 <chr> NA, "Kickoff", "Rush", "Sack", "Pu...
## $ lag_play_type3 <chr> NA, NA, "Kickoff", "Pass Reception...
## $ lag_play_text <chr> "AJ Reed kickoff for 65 yds , Henr...
## $ lag_play_text2 <chr> NA, "AJ Reed kickoff for 65 yds , ...
## $ lead_play_text <chr> "Tua Tagovailoa pass complete to J...
## $ lag_first_by_penalty <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ lag_first_by_penalty2 <int> NA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ lag_first_by_yards <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1...
## $ lag_first_by_yards2 <int> NA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
## $ first_by_penalty <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ first_by_yards <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0...
## $ play_after_turnover <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0...
## $ lag_change_of_poss <int> 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0...
## $ lag_change_of_pos_team <int> 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0...
## $ lag_change_of_pos_team2 <int> 0, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0...
## $ lag_kickoff_play <int> 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ lag_punt <int> 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0...
## $ lag_punt2 <int> 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0...
## $ lag_scoring_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ lag_turnover_vec <int> 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0...
## $ lag_downs_turnover <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ lag_defense_score_play <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ season.y <int> 2019, 2019, 2019, 2019, 2019, 2019...
## $ week.y <int> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1...
## $ season_type <chr> "regular", "regular", "regular", "...
## $ start_date <chr> "2019-08-31T19:30:00.000Z", "2019-...
## $ start_time_tbd <lgl> NA, NA, NA, NA, NA, NA, NA, NA, NA...
## $ neutral_site <lgl> TRUE, TRUE, TRUE, TRUE, TRUE, TRUE...
## $ conference_game <lgl> FALSE, FALSE, FALSE, FALSE, FALSE,...
## $ attendance <int> 71916, 71916, 71916, 71916, 71916,...
## $ venue_id <int> 5348, 5348, 5348, 5348, 5348, 5348...
## $ venue <chr> "Mercedes-Benz Stadium", "Mercedes...
## $ home_id <int> 333, 333, 333, 333, 333, 333, 333,...
## $ home_team <chr> "Alabama", "Alabama", "Alabama", "...
## $ home_conference <chr> "SEC", "SEC", "SEC", "SEC", "SEC",...
## $ home_points <int> 42, 42, 42, 42, 42, 42, 42, 42, 42...
## $ home_post_win_prob <chr> "0.999990884676356", "0.9999908846...
## $ away_id <int> 150, 150, 150, 150, 150, 150, 150,...
## $ away_team <chr> "Duke", "Duke", "Duke", "Duke", "D...
## $ away_conference <chr> "ACC", "ACC", "ACC", "ACC", "ACC",...
## $ away_points <int> 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3...
## $ away_post_win_prob <chr> "0.00000911532364400447", "0.00000...
## $ excitement_index <chr> "0.4601882762", "0.4601882762", "0...
## $ abs_diff <int> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
## $ garbage <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0...
Ok, wow! We have more than 100,000 observations in our dataset, and 354 variables. These variables include play details, like down, distance, and yard line (yards_to_goal
), as well as results - was it a rush or a pass? How many yards were gained? Was it a scoring play? For our initial analysis today, we’ll focus on yards gained, success rate, and expected points added, so let’s use the dplyr::select()
function to grab some play and team details, plus those variables.
plays <- pbp %>% select(offense_play, defense_play, down, distance, yards_to_goal, rush, pass, yards_gained, play_text, success, EPA, garbage)
Now we have our relevant data, so let’s make do some stats!
Ok, now let’s play with the tidyverse a little more. We’ve used dplyr::filter()
, which is an extremely useful function. The next most useful functions actually do things to the data: dplyr::group_by()
, and dplyr::summarise()
.
Summarise is the way of creating season-long or game-by-game stats. Let’s start with some season long raw offense numbers, yards per attempt (passing) and yards per rush. We’re going to use the pipe (%>%
) to tell R to grab our plays dataset, group it by offense team, and summarize their yards per attempt and yards per rush in a new object called offense.
To create a conditional mean, like “the mean of yards_gained when pass == 1
”, all you’ll do is add the condition you want in brackets inside your mean()
function.
offense <- plays %>% group_by(offense_play) %>%
summarise(ypa = mean(yards_gained[pass==1]),
ypr = mean(yards_gained[rush==1]))
Now we can ask and answer some fun questions. Who had the best rushing offense, on a per play basis? Who had the best passing offense, on a per-play basis? We will do this using the dplyr::arrange(desc())
function, which tells R to order the data from greatest to least (descending).
offense %>% arrange(desc(ypr))
## # A tibble: 130 x 3
## offense_play ypa ypr
## <chr> <dbl> <dbl>
## 1 Oklahoma 9.18 6.56
## 2 Kentucky 4.63 6.55
## 3 Clemson 8.13 6.50
## 4 Western Michigan 6.54 6.42
## 5 Louisiana 7.11 6.41
## 6 Ohio State 8.28 6.37
## 7 Navy 9.06 6.37
## 8 Oklahoma State 6.51 6.25
## 9 Mississippi State 5.79 6.05
## 10 Ole Miss 6.20 6.01
## # ... with 120 more rows
offense %>% arrange(ypa)
## # A tibble: 130 x 3
## offense_play ypa ypr
## <chr> <dbl> <dbl>
## 1 Northwestern 3.63 4.79
## 2 Akron 3.87 3.39
## 3 Duke 3.93 4.11
## 4 Maryland 3.97 5.83
## 5 UMass 3.97 4.29
## 6 Old Dominion 4.03 4.14
## 7 Bowling Green 4.22 4.17
## 8 New Mexico State 4.28 5.43
## 9 Georgia Tech 4.28 5.13
## 10 Vanderbilt 4.40 4.89
## # ... with 120 more rows
I took out the desc()
part of the function to display the worst offenses, for fun. We see that Oklahoma had the highest yards per rush, followed by Oklahoma, Kentucky, and Louisiana. The top passing teams were Air Force, Alabama, LSU, and Oklahoma. Bonus points if you can tell me why Air Force is ranked that highly!
The worst offenses for rushing and passing were West Virginia, who averaged only 3.15 yards per rush, and Northwestern, who averaged an inconceivable 3.96 yards per passing attempt.
We can easily do the defensive side of the ball as well, grouping plays instead by defense_play. Let’s make a dataset and then use dplyr::left_join()
to put offenses and defenses together, but let’s do EPA instead of yards, because EPA is more fun. (What’s EPA? Glad you asked: An EPA Primer.
If you would like to read more on the expected points model fundamentals, read the cfbscrapR
tutorial on the subject:
For the tutorial, I’ve included the head()
function as a quick way to look at the top values of our data. In your console, though, with the View()
command, you can pull up the data in a traditional spreadsheet kind of format, which can help you parse through and see what you’re working with, or see results you’ve created.
offense <- plays %>% group_by(offense_play) %>%
summarise(epa.pass.off = mean(EPA[pass==1]), epa.rush.off = mean(EPA[rush==1]))
defense <- plays %>% group_by(defense_play) %>%
summarise(epa.pass.def = mean(EPA[pass==1]), epa.rush.def = mean(EPA[rush==1]))
## # A tibble: 6 x 5
## offense_play epa.pass.off epa.rush.off epa.pass.def epa.rush.def
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Air Force 0.561 NA NA NA
## 2 Akron -0.290 -0.297 0.124 -0.0600
## 3 Alabama 0.438 0.0582 -0.132 -0.0579
## 4 Appalachian State 0.142 0.0730 -0.133 -0.0910
## 5 Arizona -0.0108 0.0851 0.141 0.0405
## 6 Arizona State 0.0952 -0.0562 0.109 -0.117
In analytics, we often want to break down situations. Let’s use dplyr::filter
to select only first down plays and see which offenses performed the best on first downs only:
offense <- plays %>% filter(down == 1) %>% group_by(offense_play) %>%
summarise(epa.pass.off = mean(EPA[pass==1]), epa.rush.off = mean(EPA[rush==1]))
defense <- plays %>% filter(down == 1) %>% group_by(defense_play) %>%
summarise(epa.pass.def = mean(EPA[pass==1]), epa.rush.def = mean(EPA[rush==1]))
firstdown.epa <- left_join(offense, defense, by = c("offense_play" = "defense_play"))
head(firstdown.epa)
## # A tibble: 6 x 5
## offense_play epa.pass.off epa.rush.off epa.pass.def epa.rush.def
## <chr> <dbl> <dbl> <dbl> <dbl>
## 1 Air Force 0.842 NA NA -0.217
## 2 Akron -0.235 -0.397 0.138 -0.0805
## 3 Alabama 0.290 0.0949 0.0241 -0.0383
## 4 Appalachian State 0.0656 -0.0549 0.00194 -0.199
## 5 Arizona -0.00498 -0.100 0.0574 0.0997
## 6 Arizona State 0.00235 -0.178 0.160 -0.225
Easy! You can make any kind of filter you can think of, and analyse EPA or yards gained in any situation.
Lastly, let’s do an example of creating some rates and using some advanced filters: We’ll create success rate on early downs and early downs rush rate, filtering out garbage time. We’ll use the same filter, summarise, and mean functions as above!
success <- plays %>% filter(garbage == 0 & down < 3) %>%
group_by(offense_play) %>%
summarise(success.rte = mean(success),
rush.rte = mean(rush))
head(success)
## # A tibble: 6 x 3
## offense_play success.rte rush.rte
## <chr> <dbl> <dbl>
## 1 Air Force 0.428 0.862
## 2 Akron 0.286 0.391
## 3 Alabama 0.481 0.448
## 4 Appalachian State 0.384 0.633
## 5 Arizona 0.36 0.524
## 6 Arizona State 0.392 0.531
We have some pretty data, now let’s learn how to make a basic ggplot2::ggplot()
to visualize our data! We didn’t have to load ggplot2::ggplot()
, it’s included in the tidyverse. We’ll take the success data from above, and start with a basic plot, then add some fancy formatting.
The syntax here is pretty simple: we will grab our dataset and use the pipe to say “open a plot”. Then we’ll tell the plot what the x and y coordinates are, then indicate the markers, in this case a scatterplot with ggplot2::geom_point()
. Notice that we use +
instead of %>%
once we’ve called ggplot2::ggplot()
. The syntax here tells R to take the success
object and open a plot with the x.axis rush.rte
and the y.axis success.rte
, PLUS all these features. That can be a little confusing to keep straightforward, but R will tell you what’s going on with an error if you mix that up!
success %>% ggplot(aes(x=rush.rte, y=success.rte)) + geom_point()
Ok, that’s pretty cool! Let’s dress it up a little bit by adding a title and labeling the axes, using the ggplot2::labs()
option. We will also throw a couple reference lines - a vertical and horizontal line indicating the mean values of each statistic to help us compare. Plus, here are some tweaks I like that make the graph look a little better (all the ggplot2::theme()
stuff).
success %>% ggplot(aes(x=rush.rte, y=success.rte)) + geom_point() +
geom_vline(xintercept = mean(success$rush.rte), linetype = "dashed", color = "red", alpha = 0.5) +
geom_hline(yintercept = mean(success$success.rte), linetype = "dashed", color = "red", alpha = 0.5) +
labs(x = "Early Downs Rush Rate", y= "Success Rate",
title = "2019 FBS Early Downs Rush Rate and Success") +
theme_minimal() +
theme(axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 12),
plot.subtitle = element_text(size = 12),
plot.caption = element_text(size = 12),
panel.grid.minor = element_blank())
If you want to get really fancy, and I know you do, you can include team logos on these graphs. You’ll need to install and load the ggimage
package.
There are probably better/faster ways to do this, but they’re all more complicated. For now, what I’ve done is posted the CSV from CollegeFootballData.com’s team page to my github, and we’re just going to rip the logos from there. Not ideal, but it works. You don’t need to change this line at all to get the logos data! We select school and logo because those are the only two things we need for the graphs.
cfblogos <- read.csv("https://raw.githubusercontent.com/spfleming/CFB/master/logos.csv") %>% select(school, logo)
chartdata <- success %>% left_join(cfblogos, by = c("offense_play" = "school"))
Now, we have our created success object and the team logos in the chartdata object. We’ll make use of our graph from above, telling the plot that we want to use the logo column of chartdata to identify teams instead of a regular ol’ marker. This plot takes a minute to run - this is a consequence of pulling the logos from the web each time. It’s not ideal, but again this is the easiest way to make these graphs, so I opted for simplicity.
It might take up to two minutes to load! Don’t freak out! Don’t close R! Just let it load! You’ll see a white screen in your Plots window, but I promise the graph is coming.
chartdata %>% ggplot(aes(x=rush.rte, y=success.rte)) + geom_image(image = chartdata$logo, asp = 16/9) +
geom_vline(xintercept = mean(chartdata$rush.rte), linetype = "dashed", color = "red", alpha = 0.5) +
geom_hline(yintercept = mean(chartdata$success.rte), linetype = "dashed", color = "red", alpha = 0.5) +
labs(x = "Early Downs Rush Rate", y= "Success Rate",
title = "2019 FBS Early Downs Rush Rate and Success") +
theme_minimal() +
theme(axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 12),
plot.subtitle = element_text(size = 12),
plot.caption = element_text(size = 12),
panel.grid.minor = element_blank())
You can save the graphs with ggplot2::ggsave()
. That gives you a nice, high-res png file that we can post to Twitter or put in a blog post: ggplot2::ggsave('file.png', height = 7, width = 13, dpi = 300)
Another useful visualization might be to see the EPA of each of a team’s plays by location on the field. We will filter the dataset to include only our favorite team, and then plot the EPA of each play to examine outliers.
Here’s the 2019 TCU Offense:
tcu <- plays %>% filter(offense_play == "TCU")
tcu %>%
ggplot(aes(x=yards_to_goal, y=EPA)) +
geom_point() +
labs(x = "Yard Line",
y = "EPA",
title = "Expected Points Added by Field Position",
subtitle = "TCU Offense 2019") +
geom_hline(yintercept = 0, alpha = 0.5, col = "purple") +
theme_minimal() +
theme(axis.title = element_text(size = 12),
axis.text = element_text(size = 10),
plot.title = element_text(size = 12),
plot.subtitle = element_text(size = 12),
plot.caption = element_text(size = 12),
panel.grid.minor = element_blank())
I added a couple fun features here: a ggplot2::geom_hline()
reference line at zero, to help us better understand the graph, and a subtitle to clarify what was on the graph. Notice that TCU’s EPA was spread almost evenly across the field, but you can see some serious negative outliers that weighed them down. We could call those outliers into our console to explore them more:
plays %>% filter(offense_play == "TCU" & EPA < -4) %>% select(offense_play, defense_play, play_text, down, distance, yards_to_goal)
## offense_play defense_play
## 1 TCU SMU
## 2 TCU Texas
## 3 TCU Oklahoma State
## 4 TCU Baylor
## 5 TCU Baylor
## 6 TCU West Virginia
## 7 TCU West Virginia
## play_text
## 1 Max Duggan run for a loss of 4 yards to the TCU 24 Max Duggan fumbled, recovered by SMU Toby Ndukwe
## 2 Max Duggan pass intercepted Brandon Jones return for a loss of 3 yards to the Texas 24 TEXAS Penalty, Illegal Block (12 Yards) to the Texas 12
## 3 Max Duggan pass complete to John Stephens Jr. for 13 yds John Stephens Jr. fumbled, recovered by OKSt Kolby Harvell-Peel
## 4 Max Duggan pass intercepted Grayland Arnold return for no gain to the Bayl 14
## 5 Max Duggan pass intercepted Terrel Bernard return for 20 yds to the TCU 8
## 6 Max Duggan pass intercepted Tykee Smith return for 39 yds to the TCU 14
## 7 Max Duggan pass intercepted Sean Mahone return for 3 yds to the TCU 47
## down distance yards_to_goal
## 1 2 6 71
## 2 1 10 24
## 3 1 10 31
## 4 1 10 24
## 5 1 10 81
## 6 3 4 57
## 7 3 7 59
Lastly, let’s explore the gt
package to list the top ten rushing and passing offenses and defenses in the country. We will take our dataset, sort it by the value we want, add a rank variable using dplyr::mutate()
, then apply gt::gt()
, simply enough.
#Passing
team.epa %>% arrange(desc(epa.pass.off)) %>% mutate(rank = dense_rank(desc(epa.pass.off))) %>%
filter(rank < 10) %>% gt()
| offense_play | epa.pass.off | epa.rush.off | epa.pass.def | epa.rush.def | rank |
|---|---|---|---|---|---|
| Air Force | 0.5611321 | NA | NA | NA | 1 |
| Alabama | 0.4384379 | 0.058178366 | -0.13205767 | -0.057940384 | 2 |
| LSU | 0.3960008 | 0.123705596 | -0.01405588 | -0.100851807 | 3 |
| Ohio State | 0.3233667 | 0.129348535 | -0.34714352 | -0.089347478 | 4 |
| Utah | 0.2797548 | 0.002244881 | -0.25163770 | -0.179036578 | 5 |
| Memphis | 0.2539360 | -0.009126276 | -0.06277236 | 0.003302370 | 6 |
| Iowa State | 0.2101572 | -0.096369138 | -0.02012732 | 0.009894961 | 7 |
| Clemson | 0.2092361 | 0.178108478 | -0.34842118 | -0.181980797 | 8 |
| Louisville | 0.2019797 | -0.011628001 | 0.13666564 | 0.135004239 | 9 |
Now, over in your viewer (bottom right), you should see a sleek table. Ok, well, not so sleek. We will do three things to this table to make it a little more palatable. First, we’ll add a title, second, we’ll switch the order of the variables, and third, we will change the column titles.
team.epa %>% arrange(desc(epa.pass.off)) %>% mutate(rank = dense_rank(desc(epa.pass.off))) %>%
select(rank, offense_play, epa.pass.off) %>%
filter(rank < 11) %>% gt() %>%
tab_header(title = "Best Passing Teams") %>%
cols_label(rank = "Rank", offense_play = "Offense", epa.pass.off = "EPA/Attempt")
| Best Passing Teams | ||
|---|---|---|
| Rank | Offense | EPA/Attempt |
| 1 | Air Force | 0.5611321 |
| 2 | Alabama | 0.4384379 |
| 3 | LSU | 0.3960008 |
| 4 | Ohio State | 0.3233667 |
| 5 | Utah | 0.2797548 |
| 6 | Memphis | 0.2539360 |
| 7 | Iowa State | 0.2101572 |
| 8 | Clemson | 0.2092361 |
| 9 | Louisville | 0.2019797 |
| 10 | Notre Dame | 0.1952758 |
This is just a little taste of what you can do in college football data, thanks to CollegeFootballData.com and cfbscrapR. Please tag our twitter account whenever you publish a graphic or analysis using cfbscrapR
so that we can see it and retweet it!
Let me know of any work you do, resources you can think of, or code you want to share, then I’ll link to it below!
Other Great Resources:
Books I’d Recommend:
cfbscrapR
: the R package that helps you get the college football data. Documentation can be found here:
cfb_pbp_data()
gets you the play by play for a given week or team. Can loop over this to pull the whole season.cfb_game_info()
gets you the home team, away team, game score, and more info about games.plot_pbp_sequencing()
and plot_wpa()
are both built-in graphics you can play with. See documentation.tidyverse
: the set of R data science packages that help you wrangle and analyze data.
dplyr::mutate()
: creates new variablesdplyr::group_by()
and dplyr::summarise()
: groups observation and calculates summary statisticsdplyr::filter()
: keeps observations based on certain conditions (remember to use ==
)dplyr::left_join()
: takes one dataframe and merges it with anotherggplot2::ggplot()
and ggplot2::geom_point()
: graphing functions that set up a graph and plots scatter plotshead()
, tail()
, dplyr::glimpse()
and levels()
: all help you inspect the datagt
: a nice package for getting publication-quality tables
See Tom’s Cookbook to help tweak gt
with all sorts of features.


I am an engineer passionate about Deep learning/AI.The problems that have been solved due to the latest advances in Deep Learning still blow my mind.I am even more excited for what’s to come.While it’s hard to keep up with the fast changes in the field, I am up for that challenge.
I completed my bachelor’s in Computer Science at Indian Institute of Technology, Kanpur. In my free time I try to keep up with latest developments in Space,Tech and Movies.
B. Tech in Computer Science, 2018
IIT Kanpur


Located on the west coast of Scotland, opposite the Isle of Mull.
There is no marina at Oban itself. Oban Marina
is, in fact, on the opposite shore across Kerrera Sound.
( photo of Oban marina from Andrus of S/Y Suwena)
The marina at Dunstaffnage is just 4NM away, NE of the town.
There are visitors' moorings off the town and at Ardantrive, across Kerrera Sound. The latter are more sheltered in strong SW/NW winds.
The "landing" near visitors' buoys (5deg29'.1W) is a substantial pontoon. (For 30 mins £2 charge or free if on a buoy) (Sept 2010).
There are anchorages at Brandystone, Gallanachbeg, Horseshoe Bay, Little Horseshoe Bay and at Dunstaffnage.
Following lobbying by World Cruising Club and local yachtsmen, CalMac, the operators of the Railway Pier in Oban, have agreed to introduce a reduced short stay tariff. The Railway Pier is normally very congested with fishing boats but there is an area kept free for refuelling (diesel only) behind the new CalMac ro-ro extension to the pier.
Short Stay: Pleasure craft requiring a short stay visit to a maximum of 4 hours between 08:00 and 18:00 will be subject to a nominal charge of £5.00, irrespective of length of vessel. (Non commercial activity only.)
Last updated April 2010.


This is Sideflipsaga made by MrBrain295 and Sideflip.
We post pretty much what ever we want when ever we want.
Our GitHub organization:
Things you can download from us
My custom painting pack!(1.16.5) Side's Skyblock
A mad libs like thing


To install the Hadoop to Linux for design
To install the Hadoop to Linux for design
This is a summary of hadoop stuff by Yaotian. If you have question or correction, please infor me. Email<EMAIL_ADDRESS>Preparation:
1.Linux server
2.hadoop 0.20.2 ( It's stable version.)
3.unzip hadoop to /opt/hadoop.0.20.2 and make ln to /opt/hadoop
ln -s /opt/hadoop.0.20.2 /opt/hadoop
4.Install openjdk
Steps:
a. Need sshd and install it
apt-get install ssh
And have a test
ssh localhost
b. To create an account like “hadoop”
useradd -m -U hadoop
passwd hadoop
And have a test
su hadoop
c. To generate the authorizated keys so that user can login the server without password. Before that login as “hadoop” or su to “hadoop”
su hadoop
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
And have a test, which is supposed not need any password
ssh localhost
d. If you run the hadoop as root before, you may need change the owner of the folder so that the hadoop can be run by “hadoop” account
chown -R hadoop:hadoop /opt/hadoop-0.20.2/
e. To update some files of hadoop
conf/hadoop-env.sh and update following:
export JAVA_HOME=/usr/lib/jvm/java-6-openjdk
export HADOOP_HOME=/opt/hadoop
export PATH=$PATH:/opt/hadoop/bin
conf/core-site.xml and add following:
<property>
<name>fs.default.name</name>
<value>hdfs://localhost:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/tmp/hadoop/hadoop-${user.name}</value>
</property>
conf/hdfs-site.xml and add following:
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
conf/mapred-site.xml
<property>
<name>mapred.job.tracker</name>
<value>localhost:9001</value>
</property>
f. To format the namenode
bin/hadoop namenode -format
*If you get the error, maybe you need check if the /tmp/hadoop is the root permission. If that, su to root and delete it.
g. To start hadoop
bin/start-all.sh
And have a test. This is the admin web interface http://localhost:50030/
h. To stop haddop
bin/stop-all.sh


It's a special occasion, and you want to celebrate it with someone special, or offer a token of your esteem. Maybe you just want to be nice, or show that you aren't such a bad guy after all.  She hates it? She's running away? But you had a pet goliath spider when you were a kid - doesn't she know how cuddly they are?
Welcome to Don't You Like It?, a subtrope of My New Gift Is Lame where the gift in question is inadvertently horrifying or disgusting because the giver was raised in an environment where this was considered completely appropriate - but this doesn't match up with the standards of the recipient.
Examples:
- In Land of the Lustrous, primeval-era doctor Rutile vowed to save Padparadscha and has been trying ceaselessly for centuries to do so. There's a lot of angst, romantic subtext, declarations of devotion, etc involved... until some kid takes Pad's comatose body off-world, without Rutile's knowledge or permission, to a highly advanced civilization where their medical condition can be healed. Rutile is not pleased.
- Sousuke does this on occasion Kaname in Full Metal Panic!, starting off with an apology gift of his adoptive home country's most treasured export—the raw ingredients for opium. After Kaname tries to slap some sense into him, he realizes that he made a cultural error and apologizes for not remembering that cocaine is significantly more valued than opium in Tokyo.
- Happens in Dork Tower when Ken Mills gives his girlfriend Sujata a 1,000-point Korn Demon of Kaos High Priest of Pain Blood Champion miniature figure as a token of his affection. Needless to say, she didn't take it well.
- In Johnny the Homicidal Maniac, Johnny tells a story about someone who died horribly in one of his torture machines. When the listener (strapped into that very torture machine) is, understandably, horrified, Johnny looks confused and asks "Don't you think that's funny?"
- In The Nightmare Before Christmas, Jack Skellington plays
Santa ClausSandy Claws and distributes Christmas gifts to the children of the world - stuff like Shrunken Heads, carnivorous toys, etc. He is horrified to find that not only don't they like their gifts, but they shoot down his sleigh. - Buddy, having been raised as an Elf, doesn't really know what lingerie is, but sees it advertised as "the perfect gift". He buys it as a present for his dad, who, needless to say, isn't thrilled about it.
- Father of the Bride (1991)- Brian gives Annie a blender as a wedding present and she almost calls the wedding off because she thinks he's telling her to Stay in the Kitchen. Turns out he gave it to her because she loves banana milkshakes and the blender was supposed to be great for those.
- Crops up in the first ElfQuest novelisation: The Sun Folk want to welcome the Wolfriders with a feast. The Wolfriders are horrified at the cooking. They prefer eating meat raw.
- This is at least part of the story behind the Lone Power's exile in Young Wizards. At the beginning of the universe, It wanted to make something completely new and original and different from the other Powers' creations.
Others had invented planets, light, gravity, space. The Lone Power invented death, and bound it irrevocably into the worlds. Shortly thereafter the other Powers joined forces and cast the Lone One out.
- However, while the Lone Power may have originally been misguided rather than malevolent, It stubbornly refuses to believe that there's anything wrong with Its "gift" and therefore is not exactly in a hurry to fix the problems It caused.
- In Heart of Steel, Alistair has been virtually alone for the last ten years, but leaps at the chance to make gifts for Julia, with whom he is smitten. Romance and mad science turn out not to mix terribly well, and his initial gifts (her bisected diving companion turned into a cyborg and a pet chimera) horrify and confuse her.
- Pretty much anything The Addams Family has ever done as a favor for their Muggle neighbors.
- Inverted in Alien Nation: If you give flowers to the Tenctonese make sure the roots are intact. Dying flowers are unpleasant.
- In one of the movies, a Purist poisons Emily and Susan with infected flowers, and he's shown buying them at a stand and asking specifically for live flowers as a gift for Newcomers.
- Everwood: While cleaning out Nina's attic, 8-year-old Delia finds an issue of Penthouse. Caught off-guard, Nina says it's an artistic photography magazine. Delia keeps it and gives it to her classmate as a birthday present. Awkwardness ensues.
- From the Jonathan Coulton song "Skullcrusher Mountain":
I made this half-pony, half-monkey monster to please you
But I kind of get the feeling that you don't like it - what's with all the screaming?

- The music video for "Weird Al" Yankovic's "Close But No Cigar", where a cat tries to woo a human woman with gifts of dead mice.
- One Mother's Day FoxTrot strip had Andy receiving the traditional gifts of flowers, chocolates, and cards from her kids. Then Jason's pet iguana Quincy crawls up to her carrying a dead cricket in his mouth...
- In The Matrix: Path of Neo there's this conversation in which Tank references this trope, about Neo's first Virtual Training Simulation outfit which is black and rather Mortal Kombatesque with a red band, Sarashi type bindings around his waist and fists during the kung-fu/ninja training level
Neo: So, uh, what's with the outfit ?Tank: You don't like it ?Neo: ...
- In one of the 8-Bit Theater guest comics, this is Black Mage's response when White Mage objects to her present: a still-beating heart.
- Exaggerated in one episode of Llamas with Hats in which Comedic Sociopath Carl presents his friend Paul with a gift: a nuclear explosion that wipes out a city, followed of severed human faces tied to balloons. Paul is understandably horrified.
Carl: This was clearly the wrong way to go.
Paul: You think, Carl?
Carl: What can I say, I expected them to be cooked more. Raw face is just gross!
Paul: That isn't the problem Carl! Why would you think any of this was a good idea!?
Carl: Probably because I'm a dangerous sociopath with a long history of violence.
- Family Guy: Brian is considering becoming a teacher at Chris's school.
Brian: I probably have a lot to offer young people.
Stewie: What are you going to teach them? How to lick the Dorito crumbs from between the sofa cushions or how to leave a dead bird on the carpet?
Brian: That was a gift, you bastard, that was a gift for the family!- Brian did this earlier with a present for Lois - also a dead bird. Chris liked it.

Girlfriend: Oh, it's...what is this?Van Gogh: It's my ear! Do you like it?  But it's just — why you ear?Van Gogh: Because I love you!Girlfriend: Well, at least this'll be a funny story to tell our kids someday.Van Gogh: Oh, you want kids? Oh, yikes. Uh, I wish you'd told me that before I got you this.(It's a box shaped like a penis.) - On My Gym Partner's a Monkey, Mr. Hornbill gives Mrs. Tusk a rhino pie, which is exactly what you're thinking it is.
- In one episode of Sushi Pack, the Pack is chosen to greet a group of delegates From The Planet Citrus, and present them with gifts. However, because they were too busy to read up on Citrusian culture, their gifts of cut flowers, chocolates, and a painting titled "Making Applesauce" don't go over well with the delegates, who are essentially living fruits.
- Once on SpongeBob SquarePants, Patrick gives SpongeBob a giant ball of chewed gum as a present. SpongeBob was too polite to say anything, even after he, his house, and half the population of Bikini Bottom get tangled up in it.
- Not to mention Spongebob's sweater that he gave to Squidward ("Do you love it??"), which was a little itchy because it'd been made out of eyelashes.
- In the Bugs Bunny cartoon "Hare Trigger," Yosemite Sam gives Bugs one second to draw a gun. He does so on a sketch pad. Sam says he's fair-to-middlin' with a pencil himself. He goes through white heat trying to draw a gun on the pad. When he's finished:
Bugs: (observing the picture) Hmmm...mmm-hmmm....hmmmm.....It stinks!
- In the beginning of Xiaolin Showdown episode "Omi Town", the heroes are opening their Chinese New Year gifts;
Dojo: I wonder what my Great-Great-Great-Great Uncle Tiamat sent me! (Tears wrapping paper off an ice block containing a dragon's skeleton) His bones. How thoughtful.
- Truth in Television for cats and some dogs, bringing their masters dead animals as gifts.
- ...but only if they think you suck at hunting. Studies show they're trying to teach you how.
- This can happen thanks to Values Dissonance. Consider the hypothetical case of a friendly American family inviting their new Muslim neighbors over for a BBQ, then offering pork ribs and beernote . It's not so hypothetical.


Class GcMonitor
monitor gabage collector activities see details in http://buildnewgames.com/garbage-collector-friendly-code/
- Defined in: gcmonitor.js
| Constructor Attributes | Constructor Name and Description |
|---|---|
|
detect gabarge collector occurance.
|
Method Summary
Class Detail
GcMonitor()
detect gabarge collector occurance. Require v8 for now, so chrome or node.js.
typical usage:
new GcMonitor().start();
Method Detail
-
burnRate()getter for the burnRate
-
check(onChange)Check if currently used memory is less than previous check. If so it is assume a GC occured
- Parameters:
- {Function|undefined} onChange
- callback notified synchronously if gc occured
-
<static> {Boolean} GcMonitor.isAvailable()check if it is available on the plateform it runs on
- Returns:
- {Boolean} true if it is available, false otherwise
-
start(onChange, period)Start monitoring periodically
- Parameters:
- {Function|undefined} onChange
- optional function to notify when gc occurs
- {Number|undefined} period
- period of the check. default to 50ms
-
stop()Stop monitoring periodically
-
{Number} usedHeapSize()getter for the usedHeapSize
- Returns:
- {Number} used heap size in byte


Select Files
Multiple
Single
Element
Tap to Select
Images Only
Tap to Select
Drop Files
Base drop zone
Combo drop/select image only zone
Upload Queue
Queue length: {{ files.length }}
Name
Type
Size
Actions
=0">
{{ item.name }}
{{ item.type }}
{{ item.size/1024/1024 | number:'.2' }} MB
Queue progress:
Upload all
Cancel all
Remove all


Nothing is happening as I expect,” Moiraine muttered, not expecting an answer from Lan.
The long, polished table before her was littered with books and papers, scrolls and manuscripts, many of them dusty from long storage and tattered with age, some only fragments. The room seemed almost made of books and manuscripts, filling shelves except where there were doors or windows or the fireplace. The chairs were high-backed and well padded, but half of them, and most of the small tables, held books, and some had books and scrolls tucked under them. Only the clutter in front of Moiraine was hers, though.
She rose and moved to the window, peered into the night toward the lights of the village, not far off. No danger of pursuit here. No one would expect her to come here. Clear my head, and begin again, she thought. That is all there is to do.
None of the villagers had any suspicion that the two elderly sisters living in this snug house were Aes Sedai. One did not suspect such things in a small place like Tifan’s Well, a farming community deep in the grassy plains of Arafel. The villagers came to the sisters for advice on their problems and cures for their ills, and valued them as women blessed by the Light, but no more. Adeleas and Vandene had gone into voluntary retreat together so long ago that few even in the White Tower remembered they still lived.
With the one equally aged Warder who remained to them, they lived quietly, still intending to write the history of the world since the Breaking, and as much as they could include of before. One day. In the meantime, there was so much information to gather, so many puzzles to solve. Their house was the perfect place for Moiraine to find the information she needed. Except that it was not there.
Movement caught her eye, and she turned. Lan was lounging against the yellow brick fireplace, as imperturbable as a boulder. “Do you remember the first time we met, Lan?”
She was watching for some sign, or she would not have seen the quick twitch of his eyebrow. It was not often she caught him by surprise. This was a subject neither of them ever mentioned; nearly twenty years ago she had told him—with all the stiff pride of one still young enough to be called young, she recalled—that she would never speak of it again and expected the same silence of him.
“I remember,” was all he said.
“And still no apology, I suppose? You threw me into a pond.” She did not smile, though she could feel amusement at it, now. “Every stitch I had was soaked, and in what you Bordermen call new spring. I nearly froze.”
“I recall I built a fire, too, and hung blankets so you could warm yourself in privacy.” He poked at the burning logs and returned the firetool to its hook. Even summer nights were cool in the Borderlands. “I also recall that while I slept that night, you dumped half the pond on me. It would have saved a great deal of shivering on both our parts if you had simply told me you were Aes Sedai rather than demonstrating it. Rather than trying to separate me from my sword. Not a good way to introduce yourself to a Borderman, even for a young woman.”
“I was young, and alone, and you were as large then as you are now, and your fierceness more open. I did not want you to know I was Aes Sedai. It seemed to me at the time you might answer my questions more freely if you did not know.” She fell silent for a moment, thinking of the years since that meeting. It had been good to find a companion to join her in her quest. “In the weeks that followed, did you suspect that I would ask you to bond to me? I decided you were the one in the first day.”
“I never guessed,” he said dryly. “I was too busy wondering if I could escort you to Chachin and keep a whole skin. A different surprise you had for me every night. The ants I recall in particular. I don’t think I had one good night’s sleep that whole ride.”
She permitted herself a small smile, remembering. “I was young,” she repeated. “And does your bond chafe after all these years? You are not a man to wear a leash easily, even so light a one as mine.” It was a stinging comment; she meant it to be so.
“No.” His voice was cool, but he took up the firetool again and gave the blaze a fierce poking it did not need. Sparks cascaded up the chimney. “I chose freely, knowing what it entailed.” The iron rod clattered back onto its hook, and he made a formal bow. “Honor to serve, Moiraine Aes Sedai. It has been and will be so, always.”
Moiraine sniffed. “Your humility, Lan Gaidin, has always been more arrogance than most kings could manage with their armies at their backs. From the first day I met you, it has been so.”
“Why all this talk of days past, Moiraine?”
For the hundredth time—or so it seemed to her—she considered the words to use. “Before we left Tar Valon I made arrangements, should anything happen to me, for your bond to pass to another.” He stared at her, silent. “When you feel my death, you will find yourself compelled to seek her out immediately. I do not want you to be surprised by it.”
“Compelled,” he breathed softly, angrily. “Never once have you used my bond to compel me. I thought you more than disapproved of that.”
“Had I left this thing undone, you would be free of the bond at my death, and not even my strongest command to you would hold.  And I will not allow you to return to your equally useless private war in the Blight. The war we fight is the same war, if you could only see it so, and I will see that you fight it to some purpose.  His voice was quiet, his face expressionless, both like stone in a dead winter blizzard. It was a manner she had seen in him many times, usually when he was on the point of violence. “Have you planned something, without me, that will see you dead?”
“I am suddenly glad there is no pond in this room,” she murmured, then raised her hands when he stiffened, offended at her light tone. “I see my death in every day, as you do. How could I not, with the task we have followed these years? Now, with everything coming to a head, I must see it as even more possible.”
For a moment he studied his hands, large and square. “I had never thought,” he said slowly, “that I might not be the first of us to die. Somehow, even at the worst, it always seemed . . . ” Abruptly he scrubbed his hands against each other. “If there is a chance I might be given like a pet lapdog, I would at least like to know to whom I am being given.”
“I have never seen you as a pet,” Moiraine said sharply, “and neither does Myrelle.”
“Myrelle.” He grimaced. “Yes, she would have to be Green, or else some slip of a girl just raised to full sisterhood.”
“If Myrelle can keep her three Gaidin in line, perhaps she has a chance to manage you. Though she would like to keep you, I know, she has promised to pass your bond to another when she finds one who suits you better.”
“So. Not a pet but a parcel. Myrelle is to be a—a caretaker! Moiraine, not even the Greens treat their Warders so. No Aes Sedai has passed her Warder’s bond to another in four hundred years, but you intend to do it to me not once, but twice!”
“It is done, and I will not undo it.”
“The Light blind me, if I am to be passed from hand to hand, do you at least have some idea in whose hand I will end?”
“What I do is for your own good, and perhaps it may be for another’s, as well. It may be that Myrelle will find a slip of a girl just raised to sisterhood—was that not what you said?—who needs a Warder hardened in battle and wise in the ways of the world, a slip of a girl who may need someone who will throw her into a pond. You have much to offer, Lan, and to see it wasted in an unmarked grave, or left to the ravens, when it could go to a woman who needs it would be worse than the sin of which the Whitecloaks prate. Yes, I think she will have need of you.”
Lan’s eyes widened slightly; for him it was the same as another man gasping in shocked surmise. She had seldom seen him so off balance. He opened his mouth twice before he spoke.  “Are you sure the bond does not chafe, Lan Gaidin? Do you realize for the first time, only now, the strength of that bond, the depth of it? You could end with some budding White, all logic and no heart, or with a young Brown who sees you as nothing more than a pair of hands to carry her books and sketches. I can hand you where I will, like a parcel—or a lapdog—and you can do no more than go. Are you sure it does not chafe?”
“Is that what this has been for?” he grated.  Anger; for the first time ever that she had seen, open anger etched his face. “Has all this talk been a test—a test!—to see if you could make my bond rub? After all this time? From the day I pledged to you, I have ridden where you said ride, even when I thought it foolish, even when I had reason to ride another way. Never did you need my bond to force me. On your word I have watched you walk into danger and kept my hands at my sides when I wanted nothing more than to out sword and carve a path to safety for you. After this, you test me?”
“Not a test, Lan. I spoke plainly, not twisting, and I have done as I said. But at Fal Dara, I began to wonder if you were still wholly with me.” A wariness entered his eyes. Lan, forgive me. I would not have cracked the walls you hold so hard, but I must know. “Why did you do as you did with Rand?” He blinked; it was obviously not what he expected. She knew what he had thought was coming, and she would not let up now that he was off balance. “You brought him to the Amyrlin speaking and acting as a Border lord and a soldier born. It fit, in a way, with what I planned for him, but you and I never spoke of teaching him any of that. Why, Lan?”
“It seemed . . . right. A young wolfhound must meet his first wolf someday, but if the wolf sees him as a puppy, if he acts the puppy, the wolf will surely kill him. The wolfhound must be a wolfhound in the wolf’s eyes even more than in his own, if he is to survive.”
“Is that how you see Aes Sedai? The Amyrlin? Me? Wolves out to pull down your young wolfhound?” Lan shook his head. “You know what he is, Lan. You know what he must become. Must. What I have worked for since the day you and I met, and before. Do you now doubt what I do?”
“No. No, but . . . ” He was recovering himself, building his walls again. But they were not rebuilt yet. “How many times have you said that ta’veren pull those around them like twigs in a whirlpool? Perhaps I was pulled, too. I only know that it felt right. Those farm folk needed someone on their side. Rand did, at least. Moiraine, I believe in what you do, even as now, when I know not half of it; believe as I believe in you. I have not asked to be released from my bond, nor will I. Whatever your plans for dying and seeing me safely—disposed of—I will take great pleasure in keeping you alive and seeing those plans, at least, go for nothing.”
“Ta’veren,” Moiraine sighed. “Perhaps it was that. Rather than guiding a chip floating down a stream, I am trying to guide a log through rapids. Every time I push at it, it pushes at me, and the log grows larger the farther we go. Yet I must see it through to the end.” She gave a little laugh. “I will not be unhappy, my old friend, if you manage to put those plans awry. Now, please leave me. I need to be alone to think.” He hesitated only a moment before turning for the door. At the last moment, though, she could not let him go without one more question. “Do you ever dream of something different, Lan?”
“All men dream. But I know dreams for dreams. This”—he touched his sword hilt—“is reality.” The walls were back, as high and hard as ever.
For a time after he left, Moiraine leaned back in her chair, looking into the fire. She thought of Nynaeve and cracks in a wall. Without trying, without thinking what she was doing, that young woman had put cracks in Lan’s walls and seeded the cracks with creepers. Lan thought he was secure, imprisoned in his fortress by fate and his own wishes, but slowly, patiently, the creepers were tearing down the walls to bare the man within. Already he was sharing some of Nynaeve’s loyalties; in the beginning he had been indifferent to the Emond’s Field folk, except as people in whom Moiraine had some interest. Nynaeve had changed that as she had changed Lan.
To her surprise, Moiraine felt a flash of jealousy. She had never felt that before, certainly not for any of the women who had thrown their hearts at his feet, or those who had shared his bed. Indeed, she had never thought of him as an object of jealousy, had never thought so of any man. She was married to her battle, as he was married to his. But they had been companions in those battles for so long. He had ridden a horse to death, then run himself nearly to death, carrying her in his arms at the last, to Anaiya for Healing.  He had always said he was wedded with death. Now a new bride had captured his eyes, though he was blind to it. He thought he still stood strong behind his walls, but Nynaeve had laced bridal flowers in his hair. Would he still find himself able to court death so blithely? Moiraine wondered when he would ask her to release him from his bond. And what she would do when he did.
With a grimace, she got to her feet. There were more important matters. Far more important. Her eyes ran over the open books and papers crowding the room. So many hints, but no answers.
Vandene came in with a teapot and cups on a tray. She was slender and graceful, with a straight back, and the hair gathered neatly at the nape of her neck was almost white. The agelessness of her smooth face was that of long, long years. “I would have had Jaem bring this, and not disturb you myself, but he’s out in the barn practicing with his sword.” She made a clucking sound as she pushed a battered manuscript aside to set the tray on the table. “Lan being here has him remembering he’s more than a gardener and handyman. Gaidin are so stiff-necked. I thought Lan would still be here; that’s why I brought an extra cup. Have you found what you were seeking?”
“I am not even sure what it is I am seeking.” Moiraine frowned, studying the other woman. Vandene was of the Green Ajah, not Brown like her sister, yet the two of them had studied so long together that she knew as much of history as Adeleas.
“Whatever it is, you don’t even seem to know where to look.” Vandene shifted some of the books and manuscripts on the table, shaking her head. “So many subjects. The Trolloc Wars. The Watchers Over the Waves. The legend of the Return. Two treatises on the Horn of Valere. Three on dark prophecy, and—Light, here’s Santhra’s book on the Forsaken. Nasty, that. As nasty as this on Shadar Logoth. And the Prophecies of the Dragon, in three translations and the original. Moiraine, whatever are you after? The Prophecies, I can understand—we hear some news here, remote as we are. We hear some of what’s happening in Illian. There’s even a rumor in the village that someone has already found the Horn.” She gestured with a manuscript on the Horn, and coughed in the dust that rose from it. “I discount that, of course. There would be rumors. But what—? No. You said you wanted privacy, and I’ll give it to you.”
“Stop a moment,” Moiraine said, halting the other Aes Sedai short of the door. “Perhaps you can answer some questions for me.”
“I will try.” Vandene smiled suddenly. “Adeleas claims I should have chosen Brown. Ask.” She poured two cups of tea and handed one to Moiraine, then took a chair by the fire.
Steam curled over the cups while Moiraine chose her questions carefully. To find the answers, and not reveal too much. “The Horn of Valere is not mentioned in the Prophecies, but is it linked to the Dragon anywhere?”
“No. Except for the fact that the Horn must be found before Tarmon Gai’don and that the Dragon Reborn is supposed to fight the Last Battle, there is no link between them at all.” The white-haired woman sipped her tea and waited.
“Does anything link the Dragon with Toman Head?”
Vandene hesitated. “Yes, and no. This is a bone between Adeleas and me.” Her voice took on a lecturing tone, and for a time she did sound like a Brown. “There is a verse in the original that translates literally as ‘Five ride forth, and four return. Above the watchers shall he proclaim himself, bannered cross the sky in fire . . . ’ Well, it goes on. The point is, the word ma’vron. I say it should be translated not simply as ‘watchers,’ which is a’vron. Ma’vron has more importance to it. I say it means the Watchers Over the Waves, though they call themselves Do Miere A’vron, of course, not Ma’vron. Adeleas tells me I am quibbling. But I believe it means the Dragon Reborn will appear somewhere above Toman Head, in Arad Doman, or Saldaea. Adeleas may think I’m foolish, but I listen to every scrap I hear coming from Saldaea these days. Mazrim Taim can channel, so I hear, and our sisters haven’t managed to corner him yet. If the Dragon is Reborn, and the Horn of Valere found, then the Last Battle is coming soon. We may never finish our history.” She gave a shiver, then abruptly laughed. “Odd thing to worry about. I suppose I am becoming more a Brown. Horrible thing to contemplate. Ask your next question.”
“I do not think you need worry about Taim,” Moiraine said absently. It was a link with Toman Head, however small and tenuous. “He will be dealt with as Logain was. What of Shadar Logoth?”
“Shadar Logoth!” Vandene snorted. “In brief, the city was destroyed by its own hate, every living thing except Mordeth, the councilor who began it all, using the tactics of the Darkfriends against the Darkfriends, and he now lies trapped there waiting for a soul to steal. It is not safe to enter, and nothing in the city is safe to touch. But every novice close to being Accepted knows as much as that. In full, you will have to stay here a month and listen to Adeleas lecture—she has the true knowledge of it—but even I can tell you there’s nothing of the Dragon in it. That place was dead a hundred years before Yurian Stonebow rose from the ashes of the Trolloc Wars, and he lies closest to it in history of all the false Dragons.”
Moiraine raised a hand. “I did not speak clearly, and I do not speak of the Dragon, now, Reborn or false. Can you think of any reason why a Fade would take something that had come from Shadar Logoth?”
“Not if it knew the thing for what it was.  They rightly fear Shadar Logoth as much as we.”
“And what can you tell me of the Forsaken?”
“You do leap from subject to subject. I can tell you little more than you learned as a novice. No one knows much more of the Nameless than that. Do you expect me to ramble on with what we both learned as girls?”
For an instant, Moiraine was silent. She did not want to say too much, but Vandene and Adeleas had more knowledge their fingertips than existed anywhere else but the White Tower, and more complications awaited her there than she cared to deal with now. She let the name slip between her lips as if it were escaping. “Lanfear.”
“For once,” the other woman sighed, “I know not a whit more than I did as a novice. The Daughter of the Night remains as much a mystery as if she truly had cloaked herself in darkness.” She paused, peering into her cup, and when she looked up, her eyes were sharp on Moiraine’s face. “Lanfear was linked to the Dragon, to Lews Therin Telamon. Moiraine, do you have some clue as to where the Dragon will be Reborn? Or was Reborn? Has he come already?”
“If I did,” Moiraine replied levelly, “would I be here, instead of in the White Tower? The Amyrlin knows as much as I, that I swear. Have you received a summons from her?”
“No, and I suppose we would. When the time comes that we must face the Dragon Reborn, the Amyrlin will need every sister, every Accepted, every novice who can light a candle unguided.” Vandene’s voice lowered, musing. “With such power as he will wield, we must overwhelm him before he has a chance to use it against us, before he can go mad and destroy the world. Yet first we must let him face the Dark One.” She laughed mirthlessly at the look on Moiraine’s face. “I am not a Red. I’ve studied the Prophecies enough to know we dare not gentle him first. If we can gentle him. I know as well as you, as well as any sister who cares to find out, that the seals holding the Dark One in Shayol Ghul are weakening. The Illianers call the Great Hunt of the Horn. False Dragons abound. And two of them, Logain and now this fellow in Saldaea, able to channel. When was the last time the Reds found two men channeling in less than a year? When did they last find one in five years? Not in my lifetime, and I am a good deal older than you. The signs are everywhere. Tarmon Gai’don is coming. The Dark One will break free. And the Dragon will be Reborn.” Her cup rattled as she set it down. “I suppose that is why I feared you might have seen some sign of him.”
“He will come,” Moiraine said smoothly, “and we will do what must be done.”
“If I thought it would do any good, I’d pull Adeleas’s nose out of her book and set off for the White Tower. But I find I am glad to be here where I am instead. Perhaps we will have time to finish our history.”
“I hope that you will, Sister.”
Vandene rose to her feet. “Well, I have tasks to be about before bed. If you have no more questions, I will leave you to your studies.” But she paused and revealed that however long she had spent with books, she was still of the Green Ajah. “You should do something about Lan, Moiraine. The man is rumbling inside worse than Dragonmount. Sooner or later, he will erupt. I’ve known enough men to see when one is troubled with a woman. You two have been together a long time.  Aes Sedai. And still as a friend, I hope.”
“You Blues.
After the white-haired Aes Sedai left, Moiraine gathered her cloak and, muttering to herself, went into the garden. There was something in what Vandene had said that tugged at her mind, but she could not remember what it was. An answer, or a hint to an answer, for a question she had not asked—but she could not bring the question to mind, either.
The garden was small, like the house, but neat even in moonlight aided by the yellow glow from the cottage windows, with sandy walks between careful beds of flowers. She settled her cloak loosely on her shoulders against the soft coolness of the night. What was the answer, and what was the question?
Sand crunched behind her, and she turned, thinking it was Lan.
A shadow loomed dimly only a few paces from her, a shadow that appeared to be a too-tall man wrapped in his cloak.  The cloak opened, unfolding into great wings like a bat’s.
Knowing it was too late, she opened herself to saidar, but the Draghkar began to croon, and its soft hum filled her, fragmenting her will. Saidar slipped away. She felt only a vague sadness as she stepped toward the creature; the deep crooning that drew her closer suppressed feeling. White, white hands—like a man’s hands, but tipped with claws—reached for her, and lips the color of blood curved in a travesty of a smile, baring sharp teeth, but dimly, so dimly, she knew it would not bite or tear. Fear the Draghkar’s kiss. Once those lips touched her, she would be as good as dead, to be drained of soul, then of life. Whoever found her, even if they came as the Draghkar let her fall, would find a corpse without a mark and cold as if dead two days. And if they came before she was dead, what they found would be worse, and not really her at all any longer. The croon pulled her within reach of those pale hands, and the Draghkar’s head bent slowly toward her.
She felt only the smallest surprise when a sword blade flashed over her shoulder to pierce the Draghkar’s breast, and little more when a second crossed her other shoulder to strike beside the first.
Dazed, swaying, she watched as if from a great distance as the creature was pushed back, away from her. Lan came into her view, then Jaem, the gray-haired Warder’s bony arms holding his blade as straight and true as the younger man’s. The Draghkar’s pale hands bloodied as they tore at the sharp steel, wings buffeting the two men with thunderclaps. Suddenly, wounded and bleeding, it began to croon again. To the Warders.
With an effort, Moiraine gathered herself; she felt almost as drained as if the thing had managed its kiss. No time to be weak. In an instant she opened herself to saidar and, as the Power filled her, steeled herself to touch the Shadowspawn directly. The two men were too close; anything else would harm them, as well. Even using the One Power, she knew she would feel soiled by the Draghkar.
But even as she began, Lan cried out, “Embrace death!” Jaem echoed him firmly. “Embrace death!” And the two men stepped within reach of the Draghkar’s touch, drove home their blades to the hilt.
Throwing back its head, the Draghkar bellowed, a shriek that seemed to pierce Moiraine’s head with needles. Even wrapped in saidar she could feel it. Like a tree falling, the Draghkar toppled, one wing knocking Jaem to his knees. Lan sagged as if exhausted.
Lanterns hurried from the house, borne by Vandene and Adeleas.
“What was that noise?” Adeleas demanded. She was almost a mirror image of her sister. “Has Jaem gone and . . . ” The lantern light fell on the Draghkar; her voice trailed off.
Vandene took Moiraine’s hands. “It did not . . . ?” She left the question unfinished as, to Moiraine’s eyes, a nimbus surrounded her. Feeling strength flowing into her from the other woman, Moiraine wished, not for the first time, that Aes Sedai could do as much for themselves as they could for others.
“It did not,” she said gratefully. “See to the Gaidin.”
Lan looked at her, mouth tight. “If you had not made me so angry I had to go work forms with Jaem, so angry I gave it up to come back to the house . . . ”
“But I did,” she said. “The Pattern takes everything into the weaving.” Jaem was muttering, but still allowing Vandene to see to his shoulder. He was all bone and tendon, yet looked as hard as old roots.
“How,” Adeleas demanded, “could any creature of the Shadow come so close without us sensing it?”
“It was warded,” Moiraine said.
“Impossible,” Adeleas snapped. “Only a sister could—” She stopped, and Vandene turned from Jaem to look at Moiraine.
Moiraine said the words none of them wanted to hear. “The Black Ajah.” Shouts drifted from the village. “Best you hide this—”she gestured to the Draghkar, sprawled across a flower bed—“quickly. They will be coming to ask if you need help, but seeing this will start talk you will not like.”
“Yes, of course,” Adeleas said. “Jaem, go and meet them. Tell them you don’t know what made the noise, but all is well here. Slow them down.” The gray-haired Warder hurried into the night toward the sound of approaching villagers. Adeleas turned to study the Draghkar as if it were a puzzling passage in one of her books. “Whether Aes Sedai are involved or not, whatever could have brought it here?” Vandene regarded Moiraine silently.
“I fear I must leave you,” Moiraine said. “Lan, will you ready the horses?” As he left, she said, “I will leave letters with you to be sent on to the White Tower, if you will arrange it.” Adeleas nodded absently, her attention still on the thing on the ground.
“And will you find your answers where you are going?” Vandene asked.
“I may already have found one I did not know I sought. I only hope I am not too late. I will need pen and parchment.” She drew Vandene toward the house, leaving Adeleas to deal with the Draghkar.


How to Use
1. Open this file in your nearest browser (Chrome, Firefox, IE, etc.).
2. See the logs in console (e.g., in Chrome Developer Tools > console, Dock side > Dock to right).
3. All test of examples are executed one by one, including async tasks.
Enjoy!
What's Tas
Tas makes the code elegant. In Tas, we can write a set of micro tasks (including async tasks) instead of a complex function, make the code logic clear and easy to test and maintain. Tas can be used in Node.js and in browsers. "Tas" is the abbreviation of "tasks".
In Tas, we can insert or remove an async tasks anywhere in any micro task without having to adjust the code elsewhere, all tasks are executed in the order we write, just like the sync tasks, and more better than Promise and generator / yield and async / await, and the tasks execution order is more reasonable.
Tas can performs more than **3 million** sync tasks or **1 million** async tasks per second, faster than native Promise (Benchmark). With Tas, we can write server code with clear code structure and excellent performance in Node.js.
Learn more about Tas:
https://github.com/tasjs/tas


PERLOPENBSD
Section: Perl Programmers Reference Guide (1)Updated: 2009-02-12
Index Return to Main Contents
NAME
README.openbsd - Perl version 5 on OpenBSD systemsDESCRIPTION
This document describes various features of OpenBSD that will affect how Perl version 5 (hereafter just Perl) is compiled and/or runs.OpenBSD core dumps from getprotobyname_r and getservbyname_r with ithreads
When Perl is configured to use ithreads, it will use re-entrant library calls in preference to non-re-entrant versions. There is an incompatability in OpenBSD's "getprotobyname_r" and "getservbyname_r" function in versions 3.7 and later that will cause a SEGV when called without doing a "bzero" on their return structs prior to calling these functions. Current Perl's should handle this problem correctly. Older threaded Perls (5.8.6 or earlier) will run into this problem. If you want to run a threaded Perl on OpenBSD 3.7 or higher, you will need to upgrade to at least Perl 5.8.7.AUTHOR
Steve Peters<EMAIL_ADDRESS>report any errors, updates, or suggestions to<EMAIL_ADDRESS>Index
This document was created by man2html, using the manual pages.
Time: 05:29:08 GMT, December 24, 2015


LEO CDP is the Customer Data Platform for on-premises deployments, is developed by USPA Technology Company.
There are 5 main functions of LEO CDP
- Provide a customer analytics platform for data-driven organizations
- Data Unification: Consistent & Unified 360 degree Customer View
- Provide a visual data segmentation tool for marketing team
- Leveraging AI, Machine Learning and Big Data for Smart Personalization
- Provide predictive marketing automation technology to activate your data-driven business


Interface IWebhookControllerApi
Represents a collection of functions to interact with the API endpoints
Inherited Members
Namespace: mailslurp.Api
Assembly: mailslurp.dll
Syntax
public interface IWebhookControllerApi : IWebhookControllerApiSync, IWebhookControllerApiAsync, IApiAccessor


😋 Pickle Editor
Sorry :(
Pickle is not currently available for the screen size you are using.
We are trying to bring Pickle to all screen sizes and devices, but currently, you need to use a screen with a width of at least 994px to use Pickle.
If you are joining from a tablet, please try in landscape orientation.


Across: 1. Hammer partner on standards? (6) 4. Ascot hat cherished, only partly as one that might help keep the weather out (8) 10. They serve by weaving tales in tune (11) 11. First "lady of the night", early on (3) 12. Stern, far different for move (8) 13. Charm of quiet arrangement applying to 16 19 for 99 years (6) 15,20. Working with briefly ecological U.N. effort, toy with including wide and small parts of plants in proposal for 16 19 (3 7, 3 7) 16,19. City with traffic noise and Chinese musical instrument side by side, slightly overlapping (4 4) 19. see 16 20. see 15 22. Nasty dox? Sue for mass 30! (6) 24.  (8) 27. Daft idea of cold war? (3) 28. Autonomy mostly gone, smashed with severity (11) 29. Some snort her narcotics, which lights Tromsø's winter shows (8) 30. Going out in turned twill and silk top (6) Down: 1. Damaged lips taking time to go away (5) 2. Unfortunate case with region beginning to need surgery to remove significant growth (9) 3. How tales woven into popular entertainment? (4 4) 5,26. 12 with Chinese getting famous British port (4 4) 6. Moving lets us fight (6) 7. He mixed with any African hunter (5) 8. Comes back to dominant position, making Greer seem radical (9) 9. Screwed on new bunk, hidden (9) 14. Overrunning borders of Syria, rough raiders (extremely) (9) 15. Most 29 Britons deviously deny moniker, discarding I.D. (9) 17. Satisying another's desires (in bed, that is) once held (9) 18. Getting out in cape, sing wildly (8) 21. Sudden disruption of program as PC shut down (6) 23. Something favoured by fascist or revolutionary socialist (5) 25. Might like Americans? (5) 26. see 5


ABOUT Hello Is An Zsd
Hi! go to , Google
We Now Have Some Images And Videos to explain value and our program


And the viral sensation is so hot, that apparently it’s even making an impact on the NFL world.
Texans quarterback Deshaun Watson put together a great performance in Sunday’s 26-3 win over the Jaguars, having completed 22 of 28 passes, with two touchdowns, and no turnovers.
What fueled him in the big performance? It was the Popeyes chicken sandwich, apparently, according to Watson himself.
Vikings receiver Stefon Diggs gave it some love as well, with his cleats.
It’s a magical sandwich, apparently, and Popeyes had to be happy that Watson gave it some shine on live TV.


| File | Statements | Branches | Functions | Lines | |||||
|---|---|---|---|---|---|---|---|---|---|
| Botkit.js | 100% | 11/11 | 100% | 0/0 | 100% | 0/0 | 100% | 11/11 | |
| CoreBot.js | 11.24% | 84/747 | 4.47% | 17/380 | 8.8% | 11/125 | 11.26% | 84/746 | |
| JabberBot.js | 2.86% | 4/140 | 0% | 0/55 | 0% | 0/22 | 2.86% | 4/140 | |
| JabberGroupManager.js | 5.15% | 10/194 | 0% | 0/85 | 0% | 0/33 | 5.15% | 10/194 | |
| Slack_web_api.js | 96.55% | 56/58 | 100% | 28/28 | 92.86% | 13/14 | 96.55% | 56/58 | |
| Studio.js | 7.62% | 31/407 | 0.35% | 1/283 | 1.45% | 1/69 | 7.62% | 31/407 | |
| Teams.js | 12.02% | 28/233 | 3.23% | 4/124 | 4.35% | 2/46 | 12.12% | 28/231 | |
| console_logger.js | 91.3% | 21/23 | 82.35% | 14/17 | 100% | 4/4 | 91.3% | 21/23 |


My name is Sailor, and my pronouns are they/them/their. I benefit when my collaborators use the correct pronouns without help from me. Here is a resource guide about gender pronouns.
I've worked plenty of service industry jobs, spent a two
year period as a graduate student and English Composition instructor,
and have been doing technology-related work for the last three years.
When I arrived in Portland in 2014, I was in immediate need of housing
and employment. I started working at a call center supporting iOS
devices, and later moved on to Apple CPU support.
That job was disempowering and paid $9.25/hr, but I discovered that I
enjoyed troubleshooting issues and learning more about how Apple
products work. I also found there a variety of other queer and trans
people in similar situations to mine, a few of whom i still commiserate
and collaborate with. From this point on, technology work is my survival
strategy as well as my personal fascination.
Now, I work as the Technology Coordinator for a collectively-managed food co-op in SE Portland. Most of my Technology Coordinator role is project management, but I also install and implement systems and provide support to users. In addition, I work in and co-manage the retail store and serve as a Team Coordinator in the Personnel Coordinating Body.
Learning to code is part of my personal long term survival strategy.
I want to find work that sustains me, nourishes my desire to learn,
and provides me opportunities to be treated as an equal contributing to a
team.
I've always been fascinated by how the style and function
of online space informs the human interactions within it. Before I left
graduate school, I was writing about queer and trans people using tumblr
and creating digital art installations.
I dream of improving or creating software tools that enable queer,
anti-racist, feminist, and anti-capitalist action and survival. But
also, I would love to be able to pay my rent and maybe even be able
put up some of my friends who are houseless.