Processing

The processing stage involves cleaning the data after confirming that it is from a good source and it satisfies the necessary conditions.It also involves confirming that the data is complete, correct and relevant. I chose R studios as the tool to use for this phase of the analysis process. I started by installing and then loading the relevant packages.

library(tidyverse)
Warning: package ‘tidyverse’ was built under R version 4.2.1
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
── Attaching packages ────────────────────────────────────────────────── tidyverse 1.3.1 ──
✔ ggplot2 3.3.6     ✔ purrr   0.3.4
✔ tibble  3.1.7     ✔ dplyr   1.0.9
✔ tidyr   1.2.0     ✔ stringr 1.4.0
✔ readr   2.1.2     ✔ forcats 0.5.1
Warning: package ‘ggplot2’ was built under R version 4.2.1
Warning: package ‘tibble’ was built under R version 4.2.1
Warning: package ‘tidyr’ was built under R version 4.2.1
Warning: package ‘readr’ was built under R version 4.2.1
Warning: package ‘purrr’ was built under R version 4.2.1
Warning: package ‘dplyr’ was built under R version 4.2.1
Warning: package ‘stringr’ was built under R version 4.2.1
Warning: package ‘forcats’ was built under R version 4.2.1
── Conflicts ───────────────────────────────────────────────────── tidyverse_conflicts() ──
✖ dplyr::filter() masks stats::filter()
✖ dplyr::lag()    masks stats::lag()
library(lubridate)
Warning: package ‘lubridate’ was built under R version 4.2.1

Attaching package: ‘lubridate’

The following objects are masked from ‘package:base’:

    date, intersect, setdiff, union
library(janitor)
Warning: package ‘janitor’ was built under R version 4.2.1

Attaching package: ‘janitor’

The following objects are masked from ‘package:stats’:

    chisq.test, fisher.test
library(skimr)
Warning: package ‘skimr’ was built under R version 4.2.1

Loading datasets into the environment with the correct naming conventions.

June_2021 <- read_csv("202106-divvy-tripdata.csv")
Rows: 729595 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
July_2021 <- read_csv("202107-divvy-tripdata.csv")
Rows: 822410 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
August_2021 <- read_csv("202108-divvy-tripdata.csv")
Rows: 804352 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
September_2021 <- read_csv("202109-divvy-tripdata.csv")
Rows: 756147 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
October_2021 <- read_csv("202110-divvy-tripdata.csv")
Rows: 631226 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
November_2021 <- read_csv("202111-divvy-tripdata.csv")
Rows: 359978 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
December_2021 <- read_csv("202112-divvy-tripdata.csv")
Rows: 247540 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
January_2022 <- read_csv("202201-divvy-tripdata.csv")
Rows: 103770 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
February_2022 <- read_csv("202202-divvy-tripdata.csv")
Rows: 115609 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
March_2022 <- read_csv("202203-divvy-tripdata.csv")
Rows: 284042 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
April_2022 <- read_csv("202204-divvy-tripdata.csv")
Rows: 371249 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.
May_2022 <- read_csv("202205-divvy-tripdata.csv")
Rows: 634858 Columns: 13
── Column specification ───────────────────────────────────────────────────────────────────
Delimiter: ","
chr  (7): ride_id, rideable_type, start_station_name, start_station_id, end_station_nam...
dbl  (4): start_lat, start_lng, end_lat, end_lng
dttm (2): started_at, ended_at

ℹ Use `spec()` to retrieve the full column specification for this data.
ℹ Specify the column types or set `show_col_types = FALSE` to quiet this message.

The next step would ideally be to combine all of the data sets into one single data frame. But first, I confirmed that the data sets include the same column names.

colnames(June_2021)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(July_2021)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(August_2021)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(September_2021)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(October_2021)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(November_2021)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(December_2021)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(January_2022)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(February_2022)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(March_2022)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(April_2022)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     
colnames(May_2022)
 [1] "ride_id"            "rideable_type"      "started_at"        
 [4] "ended_at"           "start_station_name" "start_station_id"  
 [7] "end_station_name"   "end_station_id"     "start_lat"         
[10] "start_lng"          "end_lat"            "end_lng"           
[13] "member_casual"     

Checking the overall structure of each data set and if they have the same data types.

str(June_2021)
spec_tbl_df [729,595 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:729595] "99FEC93BA843FB20" "06048DCFC8520CAF" "9598066F68045DF2" "B03C0FE48C412214" ...
 $ rideable_type     : chr [1:729595] "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
 $ started_at        : POSIXct[1:729595], format: "2021-06-13 14:31:28" "2021-06-04 11:18:02" ...
 $ ended_at          : POSIXct[1:729595], format: "2021-06-13 14:34:11" "2021-06-04 11:24:19" ...
 $ start_station_name: chr [1:729595] NA NA NA NA ...
 $ start_station_id  : chr [1:729595] NA NA NA NA ...
 $ end_station_name  : chr [1:729595] NA NA NA NA ...
 $ end_station_id    : chr [1:729595] NA NA NA NA ...
 $ start_lat         : num [1:729595] 41.8 41.8 41.8 41.8 41.8 ...
 $ start_lng         : num [1:729595] -87.6 -87.6 -87.6 -87.6 -87.6 ...
 $ end_lat           : num [1:729595] 41.8 41.8 41.8 41.8 41.8 ...
 $ end_lng           : num [1:729595] -87.6 -87.6 -87.6 -87.6 -87.6 ...
 $ member_casual     : chr [1:729595] "member" "member" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(July_2021)
spec_tbl_df [822,410 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:822410] "0A1B623926EF4E16" "B2D5583A5A5E76EE" "6F264597DDBF427A" "379B58EAB20E8AA5" ...
 $ rideable_type     : chr [1:822410] "docked_bike" "classic_bike" "classic_bike" "classic_bike" ...
 $ started_at        : POSIXct[1:822410], format: "2021-07-02 14:44:36" "2021-07-07 16:57:42" ...
 $ ended_at          : POSIXct[1:822410], format: "2021-07-02 15:19:58" "2021-07-07 17:16:09" ...
 $ start_station_name: chr [1:822410] "Michigan Ave & Washington St" "California Ave & Cortez St" "Wabash Ave & 16th St" "California Ave & Cortez St" ...
 $ start_station_id  : chr [1:822410] "13001" "17660" "SL-012" "17660" ...
 $ end_station_name  : chr [1:822410] "Halsted St & North Branch St" "Wood St & Hubbard St" "Rush St & Hubbard St" "Carpenter St & Huron St" ...
 $ end_station_id    : chr [1:822410] "KA1504000117" "13432" "KA1503000044" "13196" ...
 $ start_lat         : num [1:822410] 41.9 41.9 41.9 41.9 41.9 ...
 $ start_lng         : num [1:822410] -87.6 -87.7 -87.6 -87.7 -87.7 ...
 $ end_lat           : num [1:822410] 41.9 41.9 41.9 41.9 41.9 ...
 $ end_lng           : num [1:822410] -87.6 -87.7 -87.6 -87.7 -87.7 ...
 $ member_casual     : chr [1:822410] "casual" "casual" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(August_2021)
spec_tbl_df [804,352 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:804352] "99103BB87CC6C1BB" "EAFCCCFB0A3FC5A1" "9EF4F46C57AD234D" "5834D3208BFAF1DA" ...
 $ rideable_type     : chr [1:804352] "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
 $ started_at        : POSIXct[1:804352], format: "2021-08-10 17:15:49" "2021-08-10 17:23:14" ...
 $ ended_at          : POSIXct[1:804352], format: "2021-08-10 17:22:44" "2021-08-10 17:39:24" ...
 $ start_station_name: chr [1:804352] NA NA NA NA ...
 $ start_station_id  : chr [1:804352] NA NA NA NA ...
 $ end_station_name  : chr [1:804352] NA NA NA NA ...
 $ end_station_id    : chr [1:804352] NA NA NA NA ...
 $ start_lat         : num [1:804352] 41.8 41.8 42 42 41.8 ...
 $ start_lng         : num [1:804352] -87.7 -87.7 -87.7 -87.7 -87.6 ...
 $ end_lat           : num [1:804352] 41.8 41.8 42 42 41.8 ...
 $ end_lng           : num [1:804352] -87.7 -87.6 -87.7 -87.7 -87.6 ...
 $ member_casual     : chr [1:804352] "member" "member" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(September_2021)
spec_tbl_df [756,147 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:756147] "9DC7B962304CBFD8" "F930E2C6872D6B32" "6EF72137900BB910" "78D1DE133B3DBF55" ...
 $ rideable_type     : chr [1:756147] "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
 $ started_at        : POSIXct[1:756147], format: "2021-09-28 16:07:10" "2021-09-28 14:24:51" ...
 $ ended_at          : POSIXct[1:756147], format: "2021-09-28 16:09:54" "2021-09-28 14:40:05" ...
 $ start_station_name: chr [1:756147] NA NA NA NA ...
 $ start_station_id  : chr [1:756147] NA NA NA NA ...
 $ end_station_name  : chr [1:756147] NA NA NA NA ...
 $ end_station_id    : chr [1:756147] NA NA NA NA ...
 $ start_lat         : num [1:756147] 41.9 41.9 41.8 41.8 41.9 ...
 $ start_lng         : num [1:756147] -87.7 -87.6 -87.7 -87.7 -87.7 ...
 $ end_lat           : num [1:756147] 41.9 42 41.8 41.8 41.9 ...
 $ end_lng           : num [1:756147] -87.7 -87.7 -87.7 -87.7 -87.7 ...
 $ member_casual     : chr [1:756147] "casual" "casual" "casual" "casual" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(October_2021)
spec_tbl_df [631,226 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:631226] "620BC6107255BF4C" "4471C70731AB2E45" "26CA69D43D15EE14" "362947F0437E1514" ...
 $ rideable_type     : chr [1:631226] "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
 $ started_at        : POSIXct[1:631226], format: "2021-10-22 12:46:42" "2021-10-21 09:12:37" ...
 $ ended_at          : POSIXct[1:631226], format: "2021-10-22 12:49:50" "2021-10-21 09:14:14" ...
 $ start_station_name: chr [1:631226] "Kingsbury St & Kinzie St" NA NA NA ...
 $ start_station_id  : chr [1:631226] "KA1503000043" NA NA NA ...
 $ end_station_name  : chr [1:631226] NA NA NA NA ...
 $ end_station_id    : chr [1:631226] NA NA NA NA ...
 $ start_lat         : num [1:631226] 41.9 41.9 41.9 41.9 41.9 ...
 $ start_lng         : num [1:631226] -87.6 -87.7 -87.7 -87.7 -87.7 ...
 $ end_lat           : num [1:631226] 41.9 41.9 41.9 41.9 41.9 ...
 $ end_lng           : num [1:631226] -87.6 -87.7 -87.7 -87.7 -87.7 ...
 $ member_casual     : chr [1:631226] "member" "member" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(November_2021)
spec_tbl_df [359,978 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:359978] "7C00A93E10556E47" "90854840DFD508BA" "0A7D10CDD144061C" "2F3BE33085BCFF02" ...
 $ rideable_type     : chr [1:359978] "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
 $ started_at        : POSIXct[1:359978], format: "2021-11-27 13:27:38" "2021-11-27 13:38:25" ...
 $ ended_at          : POSIXct[1:359978], format: "2021-11-27 13:46:38" "2021-11-27 13:56:10" ...
 $ start_station_name: chr [1:359978] NA NA NA NA ...
 $ start_station_id  : chr [1:359978] NA NA NA NA ...
 $ end_station_name  : chr [1:359978] NA NA NA NA ...
 $ end_station_id    : chr [1:359978] NA NA NA NA ...
 $ start_lat         : num [1:359978] 41.9 42 42 41.9 41.9 ...
 $ start_lng         : num [1:359978] -87.7 -87.7 -87.7 -87.8 -87.6 ...
 $ end_lat           : num [1:359978] 42 41.9 42 41.9 41.9 ...
 $ end_lng           : num [1:359978] -87.7 -87.7 -87.7 -87.8 -87.6 ...
 $ member_casual     : chr [1:359978] "casual" "casual" "casual" "casual" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(December_2021)
spec_tbl_df [247,540 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:247540] "46F8167220E4431F" "73A77762838B32FD" "4CF42452054F59C5" "3278BA87BF698339" ...
 $ rideable_type     : chr [1:247540] "electric_bike" "electric_bike" "electric_bike" "classic_bike" ...
 $ started_at        : POSIXct[1:247540], format: "2021-12-07 15:06:07" "2021-12-11 03:43:29" ...
 $ ended_at          : POSIXct[1:247540], format: "2021-12-07 15:13:42" "2021-12-11 04:10:23" ...
 $ start_station_name: chr [1:247540] "Laflin St & Cullerton St" "LaSalle Dr & Huron St" "Halsted St & North Branch St" "Halsted St & North Branch St" ...
 $ start_station_id  : chr [1:247540] "13307" "KP1705001026" "KA1504000117" "KA1504000117" ...
 $ end_station_name  : chr [1:247540] "Morgan St & Polk St" "Clarendon Ave & Leland Ave" "Broadway & Barry Ave" "LaSalle Dr & Huron St" ...
 $ end_station_id    : chr [1:247540] "TA1307000130" "TA1307000119" "13137" "KP1705001026" ...
 $ start_lat         : num [1:247540] 41.9 41.9 41.9 41.9 41.9 ...
 $ start_lng         : num [1:247540] -87.7 -87.6 -87.6 -87.6 -87.7 ...
 $ end_lat           : num [1:247540] 41.9 42 41.9 41.9 41.9 ...
 $ end_lng           : num [1:247540] -87.7 -87.7 -87.6 -87.6 -87.6 ...
 $ member_casual     : chr [1:247540] "member" "casual" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(January_2022)
spec_tbl_df [103,770 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:103770] "C2F7DD78E82EC875" "A6CF8980A652D272" "BD0F91DFF741C66D" "CBB80ED419105406" ...
 $ rideable_type     : chr [1:103770] "electric_bike" "electric_bike" "classic_bike" "classic_bike" ...
 $ started_at        : POSIXct[1:103770], format: "2022-01-13 11:59:47" "2022-01-10 08:41:56" ...
 $ ended_at          : POSIXct[1:103770], format: "2022-01-13 12:02:44" "2022-01-10 08:46:17" ...
 $ start_station_name: chr [1:103770] "Glenwood Ave & Touhy Ave" "Glenwood Ave & Touhy Ave" "Sheffield Ave & Fullerton Ave" "Clark St & Bryn Mawr Ave" ...
 $ start_station_id  : chr [1:103770] "525" "525" "TA1306000016" "KA1504000151" ...
 $ end_station_name  : chr [1:103770] "Clark St & Touhy Ave" "Clark St & Touhy Ave" "Greenview Ave & Fullerton Ave" "Paulina St & Montrose Ave" ...
 $ end_station_id    : chr [1:103770] "RP-007" "RP-007" "TA1307000001" "TA1309000021" ...
 $ start_lat         : num [1:103770] 42 42 41.9 42 41.9 ...
 $ start_lng         : num [1:103770] -87.7 -87.7 -87.7 -87.7 -87.6 ...
 $ end_lat           : num [1:103770] 42 42 41.9 42 41.9 ...
 $ end_lng           : num [1:103770] -87.7 -87.7 -87.7 -87.7 -87.6 ...
 $ member_casual     : chr [1:103770] "casual" "casual" "member" "casual" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(February_2022)
spec_tbl_df [115,609 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:115609] "E1E065E7ED285C02" "1602DCDC5B30FFE3" "BE7DD2AF4B55C4AF" "A1789BDF844412BE" ...
 $ rideable_type     : chr [1:115609] "classic_bike" "classic_bike" "classic_bike" "classic_bike" ...
 $ started_at        : POSIXct[1:115609], format: "2022-02-19 18:08:41" "2022-02-20 17:41:30" ...
 $ ended_at          : POSIXct[1:115609], format: "2022-02-19 18:23:56" "2022-02-20 17:45:56" ...
 $ start_station_name: chr [1:115609] "State St & Randolph St" "Halsted St & Wrightwood Ave" "State St & Randolph St" "Southport Ave & Waveland Ave" ...
 $ start_station_id  : chr [1:115609] "TA1305000029" "TA1309000061" "TA1305000029" "13235" ...
 $ end_station_name  : chr [1:115609] "Clark St & Lincoln Ave" "Southport Ave & Wrightwood Ave" "Canal St & Adams St" "Broadway & Sheridan Rd" ...
 $ end_station_id    : chr [1:115609] "13179" "TA1307000113" "13011" "13323" ...
 $ start_lat         : num [1:115609] 41.9 41.9 41.9 41.9 41.9 ...
 $ start_lng         : num [1:115609] -87.6 -87.6 -87.6 -87.7 -87.6 ...
 $ end_lat           : num [1:115609] 41.9 41.9 41.9 42 41.9 ...
 $ end_lng           : num [1:115609] -87.6 -87.7 -87.6 -87.6 -87.6 ...
 $ member_casual     : chr [1:115609] "member" "member" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(March_2022)
spec_tbl_df [284,042 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:284042] "47EC0A7F82E65D52" "8494861979B0F477" "EFE527AF80B66109" "9F446FD9DEE3F389" ...
 $ rideable_type     : chr [1:284042] "classic_bike" "electric_bike" "classic_bike" "classic_bike" ...
 $ started_at        : POSIXct[1:284042], format: "2022-03-21 13:45:01" "2022-03-16 09:37:16" ...
 $ ended_at          : POSIXct[1:284042], format: "2022-03-21 13:51:18" "2022-03-16 09:43:34" ...
 $ start_station_name: chr [1:284042] "Wabash Ave & Wacker Pl" "Michigan Ave & Oak St" "Broadway & Berwyn Ave" "Wabash Ave & Wacker Pl" ...
 $ start_station_id  : chr [1:284042] "TA1307000131" "13042" "13109" "TA1307000131" ...
 $ end_station_name  : chr [1:284042] "Kingsbury St & Kinzie St" "Orleans St & Chestnut St (NEXT Apts)" "Broadway & Ridge Ave" "Franklin St & Jackson Blvd" ...
 $ end_station_id    : chr [1:284042] "KA1503000043" "620" "15578" "TA1305000025" ...
 $ start_lat         : num [1:284042] 41.9 41.9 42 41.9 41.9 ...
 $ start_lng         : num [1:284042] -87.6 -87.6 -87.7 -87.6 -87.6 ...
 $ end_lat           : num [1:284042] 41.9 41.9 42 41.9 41.9 ...
 $ end_lng           : num [1:284042] -87.6 -87.6 -87.7 -87.6 -87.7 ...
 $ member_casual     : chr [1:284042] "member" "member" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(April_2022)
spec_tbl_df [371,249 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:371249] "3564070EEFD12711" "0B820C7FCF22F489" "89EEEE32293F07FF" "84D4751AEB31888D" ...
 $ rideable_type     : chr [1:371249] "electric_bike" "classic_bike" "classic_bike" "classic_bike" ...
 $ started_at        : POSIXct[1:371249], format: "2022-04-06 17:42:48" "2022-04-24 19:23:07" ...
 $ ended_at          : POSIXct[1:371249], format: "2022-04-06 17:54:36" "2022-04-24 19:43:17" ...
 $ start_station_name: chr [1:371249] "Paulina St & Howard St" "Wentworth Ave & Cermak Rd" "Halsted St & Polk St" "Wentworth Ave & Cermak Rd" ...
 $ start_station_id  : chr [1:371249] "515" "13075" "TA1307000121" "13075" ...
 $ end_station_name  : chr [1:371249] "University Library (NU)" "Green St & Madison St" "Green St & Madison St" "Delano Ct & Roosevelt Rd" ...
 $ end_station_id    : chr [1:371249] "605" "TA1307000120" "TA1307000120" "KA1706005007" ...
 $ start_lat         : num [1:371249] 42 41.9 41.9 41.9 41.9 ...
 $ start_lng         : num [1:371249] -87.7 -87.6 -87.6 -87.6 -87.6 ...
 $ end_lat           : num [1:371249] 42.1 41.9 41.9 41.9 41.9 ...
 $ end_lng           : num [1:371249] -87.7 -87.6 -87.6 -87.6 -87.6 ...
 $ member_casual     : chr [1:371249] "member" "member" "member" "casual" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
str(May_2022)
spec_tbl_df [634,858 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:634858] "EC2DE40644C6B0F4" "1C31AD03897EE385" "1542FBEC830415CF" "6FF59852924528F8" ...
 $ rideable_type     : chr [1:634858] "classic_bike" "classic_bike" "classic_bike" "classic_bike" ...
 $ started_at        : POSIXct[1:634858], format: "2022-05-23 23:06:58" "2022-05-11 08:53:28" ...
 $ ended_at          : POSIXct[1:634858], format: "2022-05-23 23:40:19" "2022-05-11 09:31:22" ...
 $ start_station_name: chr [1:634858] "Wabash Ave & Grand Ave" "DuSable Lake Shore Dr & Monroe St" "Clinton St & Madison St" "Clinton St & Madison St" ...
 $ start_station_id  : chr [1:634858] "TA1307000117" "13300" "TA1305000032" "TA1305000032" ...
 $ end_station_name  : chr [1:634858] "Halsted St & Roscoe St" "Field Blvd & South Water St" "Wood St & Milwaukee Ave" "Clark St & Randolph St" ...
 $ end_station_id    : chr [1:634858] "TA1309000025" "15534" "13221" "TA1305000030" ...
 $ start_lat         : num [1:634858] 41.9 41.9 41.9 41.9 41.9 ...
 $ start_lng         : num [1:634858] -87.6 -87.6 -87.6 -87.6 -87.6 ...
 $ end_lat           : num [1:634858] 41.9 41.9 41.9 41.9 41.9 ...
 $ end_lng           : num [1:634858] -87.6 -87.6 -87.7 -87.6 -87.7 ...
 $ member_casual     : chr [1:634858] "member" "member" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 

Confirming that datatypes are consistent across all datasets.

compare_df_cols(June_2021,July_2021,August_2021,September_2021,October_2021,November_2021,December_2021,January_2022,February_2022,March_2022,April_2022,May_2022,return = "mismatch")

The function above confirms that there are no mismatched datatypes across all 12 of the data sets. I proceeded by combining all of them into a single data frame by stacking them untop of each other vertically.

combined_trips <- bind_rows(June_2021,July_2021,August_2021,September_2021,October_2021,November_2021,December_2021,January_2022,February_2022,March_2022,April_2022,May_2022)

Running some functions to get a better idea of the data frame.

str (combined_trips)
spec_tbl_df [5,860,776 × 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:5860776] "99FEC93BA843FB20" "06048DCFC8520CAF" "9598066F68045DF2" "B03C0FE48C412214" ...
 $ rideable_type     : chr [1:5860776] "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
 $ started_at        : POSIXct[1:5860776], format: "2021-06-13 14:31:28" "2021-06-04 11:18:02" ...
 $ ended_at          : POSIXct[1:5860776], format: "2021-06-13 14:34:11" "2021-06-04 11:24:19" ...
 $ start_station_name: chr [1:5860776] NA NA NA NA ...
 $ start_station_id  : chr [1:5860776] NA NA NA NA ...
 $ end_station_name  : chr [1:5860776] NA NA NA NA ...
 $ end_station_id    : chr [1:5860776] NA NA NA NA ...
 $ start_lat         : num [1:5860776] 41.8 41.8 41.8 41.8 41.8 ...
 $ start_lng         : num [1:5860776] -87.6 -87.6 -87.6 -87.6 -87.6 ...
 $ end_lat           : num [1:5860776] 41.8 41.8 41.8 41.8 41.8 ...
 $ end_lng           : num [1:5860776] -87.6 -87.6 -87.6 -87.6 -87.6 ...
 $ member_casual     : chr [1:5860776] "member" "member" "member" "member" ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 
skim_without_charts(combined_trips)
── Data Summary ────────────────────────
                           Values        
Name                       combined_trips
Number of rows             5860776       
Number of columns          13            
_______________________                  
Column type frequency:                   
  character                7             
  numeric                  4             
  POSIXct                  2             
________________________                 
Group variables            None          
dim(combined_trips)
[1] 5860776      13
head(combined_trips)

Creating columns that extract the day, month, year and day of the week of each trip using its recorded “started_at” time.

combined_trips$date <- as.Date(combined_trips$started_at)
combined_trips$month <- format(as.Date(combined_trips$date), "%B")
combined_trips$day <- format(as.Date(combined_trips$date), "%d")
combined_trips$year <- format(as.Date(combined_trips$date), "%Y")
combined_trips$day_of_the_week <- weekdays(combined_trips$date)
head(combined_trips)

Adding a fifth variable; the ride length. This can be gotten from the difference between the “started_at” and “ended_at” time of each trip.

combined_trips$ride_length <- difftime(combined_trips$ended_at,combined_trips$started_at, units = "min") 

Reducing the decimal points to two places and changing the datatype to numeric so that arithmetic analysis can be done on the ride_length column.

combined_trips$ride_length <- round(combined_trips$ride_length, 2)
combined_trips$ride_length <- as.numeric(as.character(combined_trips$ride_length))

Checking the structure of the dataset again to confirm that each variable is in the right form for analysis.

str(combined_trips)
spec_tbl_df [5,860,776 × 19] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
 $ ride_id           : chr [1:5860776] "99FEC93BA843FB20" "06048DCFC8520CAF" "9598066F68045DF2" "B03C0FE48C412214" ...
 $ rideable_type     : chr [1:5860776] "electric_bike" "electric_bike" "electric_bike" "electric_bike" ...
 $ started_at        : POSIXct[1:5860776], format: "2021-06-13 14:31:28" "2021-06-04 11:18:02" ...
 $ ended_at          : POSIXct[1:5860776], format: "2021-06-13 14:34:11" "2021-06-04 11:24:19" ...
 $ start_station_name: chr [1:5860776] NA NA NA NA ...
 $ start_station_id  : chr [1:5860776] NA NA NA NA ...
 $ end_station_name  : chr [1:5860776] NA NA NA NA ...
 $ end_station_id    : chr [1:5860776] NA NA NA NA ...
 $ start_lat         : num [1:5860776] 41.8 41.8 41.8 41.8 41.8 ...
 $ start_lng         : num [1:5860776] -87.6 -87.6 -87.6 -87.6 -87.6 ...
 $ end_lat           : num [1:5860776] 41.8 41.8 41.8 41.8 41.8 ...
 $ end_lng           : num [1:5860776] -87.6 -87.6 -87.6 -87.6 -87.6 ...
 $ member_casual     : chr [1:5860776] "member" "member" "member" "member" ...
 $ date              : Date[1:5860776], format: "2021-06-13" "2021-06-04" ...
 $ month             : chr [1:5860776] "June" "June" "June" "June" ...
 $ day               : chr [1:5860776] "13" "04" "04" "03" ...
 $ year              : chr [1:5860776] "2021" "2021" "2021" "2021" ...
 $ day_of_the_week   : chr [1:5860776] "Sunday" "Friday" "Friday" "Thursday" ...
 $ ride_length       : num [1:5860776] 2.72 6.28 5.98 25.83 4.13 ...
 - attr(*, "spec")=
  .. cols(
  ..   ride_id = col_character(),
  ..   rideable_type = col_character(),
  ..   started_at = col_datetime(format = ""),
  ..   ended_at = col_datetime(format = ""),
  ..   start_station_name = col_character(),
  ..   start_station_id = col_character(),
  ..   end_station_name = col_character(),
  ..   end_station_id = col_character(),
  ..   start_lat = col_double(),
  ..   start_lng = col_double(),
  ..   end_lat = col_double(),
  ..   end_lng = col_double(),
  ..   member_casual = col_character()
  .. )
 - attr(*, "problems")=<externalptr> 

Cleaning the data

In a real life scenario, I would normally ask a superior colleague or one of the primary shareholders of the project on what specific data cleaning procedures I’m allowed to carry out on the data. An example would be what to do about null values in the data and whether I’m allowed to delete anything completely from the data frame. To stay on the safe side, I created a new data frame called “combined_trips_v2” where I performed all data cleaning (deleting) exercises whilst retaining the integrity of the original “combined_trips” data frame.

#deleting null values 
combined_trips_v2 <- drop_na(combined_trips)

Deleting the entries with negative ride_length since the end time should ideally not be earlier than the start time.

combined_trips_v2 <- filter (combined_trips_v2, ride_length > 0)

Extracting the longitude and latitude data from the data set as it will not be needed in this phase of the analysis.

lat_lng1 <- select(combined_trips_v2,start_station_name,end_station_name,start_lat,start_lng,end_lat,end_lng,member_casual)
combined_trips_v2 <- combined_trips_v2 %>%
select (-c(start_lat, start_lng, end_lat, end_lng))
head (combined_trips_v2)

After I concluded that my data was in the correct format and has been properly cleaned, I moved on to the next phase of the analysis process; Analsis.

Analysis

Analysis is the process of making sense of the data collected (and cleaned). The goal is to identify trends and relationships within the data that will help in solving the business task. The main purpose of the analysis was to deduce all the ways that cyclist members and cyclist casuals used the bicycles differently, in line with the business task.

I started by performing descriptive analysis on the data. ### Descriptive analysis

combined_trips_v2 %>%
  group_by (member_casual) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))
combined_trips_v2 %>%
  count(rideable_type)
combined_trips_v2 %>%
  group_by(member_casual)%>%
  count (rideable_type)
summary (combined_trips_v2$ride_length) #This shows a summary of the ride length. 
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
    0.02     6.60    11.60    20.22    20.97 55944.15 
combined_trips_v2%>%
  group_by(member_casual)%>%
  summarise(number_of_rides=n(), min_ride_length=min(ride_length),max_ride_length=max(ride_length),avg_ride_length=mean(ride_length),median_ride_length=median(ride_length))

Ordering the months from June 2021 to May 2022 and the days of the week from Sunday to Saturday.

combined_trips_v2$month <- ordered(combined_trips_v2$month, levels=c( "June", "July", "August", "September", "October", "November", "December","January", "February", "March", "April", "May"))

combined_trips_v2$day_of_the_week <- ordered(combined_trips_v2$day_of_the_week, levels=c("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"))
combined_trips_v2 %>%
  group_by(member_casual, month) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  arrange (month)
`summarise()` has grouped output by 'member_casual'. You can override
using the `.groups` argument.
combined_trips_v2 %>%
  group_by(member_casual, day_of_the_week) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  arrange (day_of_the_week)
`summarise()` has grouped output by 'member_casual'. You can override
using the `.groups` argument.

Most popular start stations for casual riders

combined_trips_v2 %>%
  group_by(start_station_name, member_casual) %>%
  summarise(number_of_trips=n()) %>%
  arrange(desc (number_of_trips)) %>%
  filter(member_casual== "casual") %>%
  select(start_station_name, number_of_trips)
`summarise()` has grouped output by 'start_station_name'. You can override using the `.groups` argument.

Most popular end stations for casual riders

combined_trips_v2 %>%
  group_by(end_station_name, member_casual) %>%
  summarise(number_of_trips=n()) %>%
  arrange(desc (number_of_trips)) %>%
  filter(member_casual== "casual") %>%
  select(end_station_name, number_of_trips)
`summarise()` has grouped output by 'end_station_name'. You can override using the `.groups` argument.

Creating a new version of the data set that combines the start_station_name and the end_station_name to serve as an aggregate representation of each ride route.

combined_trips_v3 <- (unite(combined_trips_v2, "ride_routes", start_station_name, end_station_name, sep= " to "))
head (combined_trips_v3)

Extracting data about the ride routes to be used for visualizations in Tableau.

top_routes <- combined_trips_v3 %>%
  group_by(ride_routes) %>%
  summarise(number_of_rides=n()) %>%
  arrange (desc (number_of_rides))
head (top_routes,10)
top_routes_1 <- combined_trips_v3 %>%
  group_by(ride_routes, member_casual) %>%
  summarise(number_of_rides=n()) %>%
  arrange (desc(number_of_rides)) 
head (top_routes_1, 10)

Visualizations

Creating charts to visualize different parts of the data and acquire useful insights. Tableau was also used for this section of the analysis.

Number of rides and Average ride length segmented by rider type

combined_trips_v3 %>%
  group_by(member_casual) %>%
  summarise(Average_ride_length=mean(ride_length)) %>%
  ggplot(aes(x= member_casual, y=Average_ride_length, fill=member_casual)) + geom_col() + labs(title = "Average ride length by rider type", x="Rider type", y="Average ride length")

combined_trips_v3 %>%
  group_by(member_casual, month) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  ggplot (aes(x=month, y=number_of_rides, fill=member_casual)) + geom_col(position= "dodge2") + labs(title = "Number of rides per month segmented by rider type", x= "Month", y="Number of rides")+ theme(axis.text.x = element_text(angle = 60, hjust=1))
`summarise()` has grouped output by 'member_casual'. You can override using the `.groups` argument.

combined_trips_v3 %>%
  group_by(member_casual, month) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  ggplot (aes(x=month, y=average_ride_length, fill=member_casual)) + geom_col(position= "dodge2") + labs(title = "Average ride length per month segmented by rider type", x= "Month", y="Average ride length")+ theme(axis.text.x = element_text(angle = 60, hjust=1))
`summarise()` has grouped output by 'member_casual'. You can override using the `.groups` argument.

combined_trips_v3 %>%
  group_by(member_casual, day_of_the_week) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  ggplot (aes(x=day_of_the_week, y=number_of_rides, fill=member_casual)) + geom_col(position= "dodge2") + labs(title = "Number of rides per day of the week", x= "Day of the week", y="Number of rides")
`summarise()` has grouped output by 'member_casual'. You can override using the `.groups` argument.

combined_trips_v3 %>%
  group_by(member_casual, day_of_the_week) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  ggplot (aes(x=day_of_the_week, y=average_ride_length, fill=member_casual)) + geom_col(position= "dodge2") + labs(title = "Average ride length per week day segmented by rider type", x= "Day of the week", y="Average ride length")+ theme(axis.text.x = element_text(angle = 60, hjust=1))
`summarise()` has grouped output by 'member_casual'. You can override using the `.groups` argument.

Number of rides and Average ride length segmented by rideable type

combined_trips_v3 %>%
  group_by(rideable_type, member_casual) %>%
  summarise(number_of_rides=n()) %>%
  ggplot(aes(x=rideable_type, y=number_of_rides, fill=member_casual)) + geom_col(position = "dodge") + labs(title="Number of rides per rideable type" , x="Rideable Type", y="Number of rides")
`summarise()` has grouped output by 'rideable_type'. You can override using the `.groups` argument.

combined_trips_v3 %>%
  group_by(rideable_type, member_casual) %>%
  summarise(Average_ride_length = mean(ride_length)) %>%
  ggplot(aes(x=rideable_type, y=Average_ride_length, fill=member_casual)) + geom_col(position = "dodge") + labs(title="Average ride length per rideable type" , x="Rideable Type", y="Average ride length")
`summarise()` has grouped output by 'rideable_type'. You can override using the `.groups` argument.

combined_trips_v3 %>%
  group_by(member_casual, month, rideable_type) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  ggplot (aes(x=month, y=number_of_rides, fill=rideable_type)) + geom_col(position="dodge2") + facet_wrap(~member_casual) + labs(title = "Number of rides segmented by rideable types for each month", x="Month", y="Number of rides") + theme(axis.text.x = element_text(angle = 60, hjust=1))
`summarise()` has grouped output by 'member_casual', 'month'. You can override using the `.groups` argument.

combined_trips_v3 %>%
  group_by(member_casual, day_of_the_week, rideable_type) %>%
  summarise(number_of_rides=n(), average_ride_length=mean(ride_length))%>%
  ggplot (aes(x=day_of_the_week, y=number_of_rides, fill=rideable_type)) + geom_col(position = "dodge") + facet_wrap(~member_casual) + labs(title = "Number of rides segmented by rideable types for each day of the week", x="Day of the week", y="Number of rides") + theme(axis.text.x = element_text(angle = 60, hjust=1))
`summarise()` has grouped output by 'member_casual', 'day_of_the_week'. You can override using the `.groups` argument.

head (combined_trips_v2)
combined_trips_v2 %>%
  group_by(start_station_name, member_casual) %>%
  summarise(number_of_trips=n()) %>%
  arrange(desc (number_of_trips)) %>%
  filter(member_casual== "casual", number_of_trips >= 15460) %>%
  select(start_station_name, number_of_trips) %>%
  ggplot(aes(x=start_station_name, y=number_of_trips)) + geom_col(fill="blue") + coord_flip() + labs(title="Top 10 most popular start stations for casual riders", x="Start station name", y="Number of trips")
`summarise()` has grouped output by 'start_station_name'. You can override using the `.groups` argument.

NA
combined_trips_v2 %>%
  group_by(end_station_name, member_casual) %>%
  summarise(number_of_trips=n()) %>%
  arrange(desc (number_of_trips)) %>%
  filter(member_casual== "casual", number_of_trips >= 15596) %>%
  select(end_station_name, number_of_trips) %>%
  ggplot(aes(x=end_station_name, y=number_of_trips)) + geom_col(fill="red") + coord_flip() + labs(title="Top 10 most popular end stations for casual riders", x="End station name", y="Number of trips")
`summarise()` has grouped output by 'end_station_name'. You can override using the `.groups` argument.

NA

The document, plots and tables are then exported for further analysis. Further visualisations also performed on Tableau. Saving the dataframes as CSV files on my local desktop.

write.csv(top_routes,"C:\\Users\\Temi\\Desktop\\Cyclist project\\top_routes.csv", row.names=FALSE)
write.csv(combined_trips_v3,"C:\\Users\\Temi\\Desktop\\Cyclist project\\combined_trips_v3.csv", row.names=FALSE)
write.csv(top_routes_1,"C:\\Users\\Temi\\Desktop\\Cyclist project\\top_routes_1.csv", row.names=FALSE)
write.csv(lat_lng1,"C:\\Users\\Temi\\Desktop\\Cyclist project\\lat_lng1.csv", row.names=FALSE)
LS0tDQp0aXRsZTogIkN5Y2xpc3RpYyBDYXNlIFN0dWR5Ig0KYXV0aG9yOiAnQXV0aG9yOiBBYmR1bGxhYWggT2R1bm1iYWt1Jw0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCiMjIFByb2Nlc3NpbmcNClRoZSBwcm9jZXNzaW5nIHN0YWdlIGludm9sdmVzIGNsZWFuaW5nIHRoZSBkYXRhIGFmdGVyIGNvbmZpcm1pbmcgdGhhdCBpdCBpcyBmcm9tIGEgZ29vZCBzb3VyY2UgYW5kIGl0IHNhdGlzZmllcyB0aGUgbmVjZXNzYXJ5IGNvbmRpdGlvbnMuSXQgYWxzbyBpbnZvbHZlcyBjb25maXJtaW5nIHRoYXQgdGhlIGRhdGEgaXMgY29tcGxldGUsIGNvcnJlY3QgYW5kIHJlbGV2YW50LiBJIGNob3NlIFIgc3R1ZGlvcyBhcyB0aGUgdG9vbCB0byB1c2UgZm9yIHRoaXMgcGhhc2Ugb2YgdGhlIGFuYWx5c2lzIHByb2Nlc3MuIEkgc3RhcnRlZCBieSBpbnN0YWxsaW5nIGFuZCB0aGVuIGxvYWRpbmcgdGhlIHJlbGV2YW50IHBhY2thZ2VzLiANCmBgYHtyIGluY2x1ZGU9RkFMU0V9DQppbnN0YWxsLnBhY2thZ2VzKCJ0aWR5dmVyc2UiKQ0KaW5zdGFsbC5wYWNrYWdlcyAoImx1YnJpZGF0ZSIpDQppbnN0YWxsLnBhY2thZ2VzKCJqYW5pdG9yIikNCmluc3RhbGwucGFja2FnZXMoInNraW1yIikNCmBgYA0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkobHVicmlkYXRlKQ0KbGlicmFyeShqYW5pdG9yKQ0KbGlicmFyeShza2ltcikNCmBgYA0KTG9hZGluZyBkYXRhc2V0cyBpbnRvIHRoZSBlbnZpcm9ubWVudCB3aXRoIHRoZSBjb3JyZWN0IG5hbWluZyBjb252ZW50aW9ucy4gDQpgYGB7cn0NCkp1bmVfMjAyMSA8LSByZWFkX2NzdigiMjAyMTA2LWRpdnZ5LXRyaXBkYXRhLmNzdiIpDQpKdWx5XzIwMjEgPC0gcmVhZF9jc3YoIjIwMjEwNy1kaXZ2eS10cmlwZGF0YS5jc3YiKQ0KQXVndXN0XzIwMjEgPC0gcmVhZF9jc3YoIjIwMjEwOC1kaXZ2eS10cmlwZGF0YS5jc3YiKQ0KU2VwdGVtYmVyXzIwMjEgPC0gcmVhZF9jc3YoIjIwMjEwOS1kaXZ2eS10cmlwZGF0YS5jc3YiKQ0KT2N0b2Jlcl8yMDIxIDwtIHJlYWRfY3N2KCIyMDIxMTAtZGl2dnktdHJpcGRhdGEuY3N2IikNCk5vdmVtYmVyXzIwMjEgPC0gcmVhZF9jc3YoIjIwMjExMS1kaXZ2eS10cmlwZGF0YS5jc3YiKQ0KRGVjZW1iZXJfMjAyMSA8LSByZWFkX2NzdigiMjAyMTEyLWRpdnZ5LXRyaXBkYXRhLmNzdiIpDQpKYW51YXJ5XzIwMjIgPC0gcmVhZF9jc3YoIjIwMjIwMS1kaXZ2eS10cmlwZGF0YS5jc3YiKQ0KRmVicnVhcnlfMjAyMiA8LSByZWFkX2NzdigiMjAyMjAyLWRpdnZ5LXRyaXBkYXRhLmNzdiIpDQpNYXJjaF8yMDIyIDwtIHJlYWRfY3N2KCIyMDIyMDMtZGl2dnktdHJpcGRhdGEuY3N2IikNCkFwcmlsXzIwMjIgPC0gcmVhZF9jc3YoIjIwMjIwNC1kaXZ2eS10cmlwZGF0YS5jc3YiKQ0KTWF5XzIwMjIgPC0gcmVhZF9jc3YoIjIwMjIwNS1kaXZ2eS10cmlwZGF0YS5jc3YiKQ0KDQpgYGANClRoZSBuZXh0IHN0ZXAgd291bGQgaWRlYWxseSBiZSB0byBjb21iaW5lIGFsbCBvZiB0aGUgZGF0YSBzZXRzIGludG8gb25lIHNpbmdsZSBkYXRhIGZyYW1lLiBCdXQgZmlyc3QsIEkgY29uZmlybWVkIHRoYXQgdGhlIGRhdGEgc2V0cyBpbmNsdWRlIHRoZSBzYW1lIGNvbHVtbiBuYW1lcy4gDQpgYGB7cn0NCmNvbG5hbWVzKEp1bmVfMjAyMSkNCmNvbG5hbWVzKEp1bHlfMjAyMSkNCmNvbG5hbWVzKEF1Z3VzdF8yMDIxKQ0KY29sbmFtZXMoU2VwdGVtYmVyXzIwMjEpDQpjb2xuYW1lcyhPY3RvYmVyXzIwMjEpDQpjb2xuYW1lcyhOb3ZlbWJlcl8yMDIxKQ0KY29sbmFtZXMoRGVjZW1iZXJfMjAyMSkNCmNvbG5hbWVzKEphbnVhcnlfMjAyMikNCmNvbG5hbWVzKEZlYnJ1YXJ5XzIwMjIpDQpjb2xuYW1lcyhNYXJjaF8yMDIyKQ0KY29sbmFtZXMoQXByaWxfMjAyMikNCmNvbG5hbWVzKE1heV8yMDIyKQ0KYGBgDQpDaGVja2luZyB0aGUgb3ZlcmFsbCBzdHJ1Y3R1cmUgb2YgZWFjaCBkYXRhIHNldCBhbmQgaWYgdGhleSBoYXZlIHRoZSBzYW1lIGRhdGEgdHlwZXMuDQpgYGB7cn0NCnN0cihKdW5lXzIwMjEpDQpzdHIoSnVseV8yMDIxKQ0Kc3RyKEF1Z3VzdF8yMDIxKQ0Kc3RyKFNlcHRlbWJlcl8yMDIxKQ0Kc3RyKE9jdG9iZXJfMjAyMSkNCnN0cihOb3ZlbWJlcl8yMDIxKQ0Kc3RyKERlY2VtYmVyXzIwMjEpDQpzdHIoSmFudWFyeV8yMDIyKQ0Kc3RyKEZlYnJ1YXJ5XzIwMjIpDQpzdHIoTWFyY2hfMjAyMikNCnN0cihBcHJpbF8yMDIyKQ0Kc3RyKE1heV8yMDIyKQ0KYGBgDQpDb25maXJtaW5nIHRoYXQgZGF0YXR5cGVzIGFyZSBjb25zaXN0ZW50IGFjcm9zcyBhbGwgZGF0YXNldHMuDQpgYGB7cn0NCmNvbXBhcmVfZGZfY29scyhKdW5lXzIwMjEsSnVseV8yMDIxLEF1Z3VzdF8yMDIxLFNlcHRlbWJlcl8yMDIxLE9jdG9iZXJfMjAyMSxOb3ZlbWJlcl8yMDIxLERlY2VtYmVyXzIwMjEsSmFudWFyeV8yMDIyLEZlYnJ1YXJ5XzIwMjIsTWFyY2hfMjAyMixBcHJpbF8yMDIyLE1heV8yMDIyLHJldHVybiA9ICJtaXNtYXRjaCIpDQpgYGANClRoZSBmdW5jdGlvbiBhYm92ZSBjb25maXJtcyB0aGF0IHRoZXJlIGFyZSBubyBtaXNtYXRjaGVkIGRhdGF0eXBlcyBhY3Jvc3MgYWxsIDEyIG9mIHRoZSBkYXRhIHNldHMuIEkgcHJvY2VlZGVkIGJ5IGNvbWJpbmluZyBhbGwgb2YgdGhlbSBpbnRvIGEgc2luZ2xlIGRhdGEgZnJhbWUgYnkgc3RhY2tpbmcgdGhlbSB1bnRvcCBvZiBlYWNoIG90aGVyIHZlcnRpY2FsbHkuIA0KYGBge3J9DQpjb21iaW5lZF90cmlwcyA8LSBiaW5kX3Jvd3MoSnVuZV8yMDIxLEp1bHlfMjAyMSxBdWd1c3RfMjAyMSxTZXB0ZW1iZXJfMjAyMSxPY3RvYmVyXzIwMjEsTm92ZW1iZXJfMjAyMSxEZWNlbWJlcl8yMDIxLEphbnVhcnlfMjAyMixGZWJydWFyeV8yMDIyLE1hcmNoXzIwMjIsQXByaWxfMjAyMixNYXlfMjAyMikNCmBgYA0KDQpSdW5uaW5nIHNvbWUgZnVuY3Rpb25zIHRvIGdldCBhIGJldHRlciBpZGVhIG9mIHRoZSBkYXRhIGZyYW1lLg0KYGBge3J9DQpzdHIgKGNvbWJpbmVkX3RyaXBzKQ0KYGBgDQoNCmBgYHtyfQ0Kc2tpbV93aXRob3V0X2NoYXJ0cyhjb21iaW5lZF90cmlwcykNCmBgYA0KYGBge3J9DQpkaW0oY29tYmluZWRfdHJpcHMpDQpgYGANCmBgYHtyfQ0KaGVhZChjb21iaW5lZF90cmlwcykNCmBgYA0KQ3JlYXRpbmcgY29sdW1ucyB0aGF0IGV4dHJhY3QgdGhlIGRheSwgbW9udGgsIHllYXIgYW5kIGRheSBvZiB0aGUgd2VlayBvZiBlYWNoIHRyaXAgdXNpbmcgaXRzIHJlY29yZGVkICJzdGFydGVkX2F0IiB0aW1lLg0KYGBge3J9DQpjb21iaW5lZF90cmlwcyRkYXRlIDwtIGFzLkRhdGUoY29tYmluZWRfdHJpcHMkc3RhcnRlZF9hdCkNCmNvbWJpbmVkX3RyaXBzJG1vbnRoIDwtIGZvcm1hdChhcy5EYXRlKGNvbWJpbmVkX3RyaXBzJGRhdGUpLCAiJUIiKQ0KY29tYmluZWRfdHJpcHMkZGF5IDwtIGZvcm1hdChhcy5EYXRlKGNvbWJpbmVkX3RyaXBzJGRhdGUpLCAiJWQiKQ0KY29tYmluZWRfdHJpcHMkeWVhciA8LSBmb3JtYXQoYXMuRGF0ZShjb21iaW5lZF90cmlwcyRkYXRlKSwgIiVZIikNCmNvbWJpbmVkX3RyaXBzJGRheV9vZl90aGVfd2VlayA8LSB3ZWVrZGF5cyhjb21iaW5lZF90cmlwcyRkYXRlKQ0KYGBgDQoNCmBgYHtyfQ0KaGVhZChjb21iaW5lZF90cmlwcykNCmBgYA0KDQpBZGRpbmcgYSBmaWZ0aCB2YXJpYWJsZTsgdGhlIHJpZGUgbGVuZ3RoLiBUaGlzIGNhbiBiZSBnb3R0ZW4gZnJvbSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSAic3RhcnRlZF9hdCIgYW5kICJlbmRlZF9hdCIgdGltZSBvZiBlYWNoIHRyaXAuIA0KYGBge3J9DQpjb21iaW5lZF90cmlwcyRyaWRlX2xlbmd0aCA8LSBkaWZmdGltZShjb21iaW5lZF90cmlwcyRlbmRlZF9hdCxjb21iaW5lZF90cmlwcyRzdGFydGVkX2F0LCB1bml0cyA9ICJtaW4iKSANCmBgYA0KUmVkdWNpbmcgdGhlIGRlY2ltYWwgcG9pbnRzIHRvIHR3byBwbGFjZXMgYW5kIGNoYW5naW5nIHRoZSBkYXRhdHlwZSB0byBudW1lcmljIHNvIHRoYXQgYXJpdGhtZXRpYyBhbmFseXNpcyBjYW4gYmUgZG9uZSBvbiB0aGUgcmlkZV9sZW5ndGggY29sdW1uLiANCmBgYHtyfQ0KY29tYmluZWRfdHJpcHMkcmlkZV9sZW5ndGggPC0gcm91bmQoY29tYmluZWRfdHJpcHMkcmlkZV9sZW5ndGgsIDIpDQpgYGANCmBgYHtyfQ0KY29tYmluZWRfdHJpcHMkcmlkZV9sZW5ndGggPC0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIoY29tYmluZWRfdHJpcHMkcmlkZV9sZW5ndGgpKQ0KYGBgDQpDaGVja2luZyB0aGUgc3RydWN0dXJlIG9mIHRoZSBkYXRhc2V0IGFnYWluIHRvIGNvbmZpcm0gdGhhdCBlYWNoIHZhcmlhYmxlIGlzIGluIHRoZSByaWdodCBmb3JtIGZvciBhbmFseXNpcy4gDQpgYGB7cn0NCnN0cihjb21iaW5lZF90cmlwcykNCmBgYA0KIyMjIENsZWFuaW5nIHRoZSBkYXRhDQpJbiBhIHJlYWwgbGlmZSBzY2VuYXJpbywgSSB3b3VsZCBub3JtYWxseSBhc2sgYSBzdXBlcmlvciBjb2xsZWFndWUgb3Igb25lIG9mIHRoZSBwcmltYXJ5IHNoYXJlaG9sZGVycyBvZiB0aGUgcHJvamVjdCBvbiB3aGF0IHNwZWNpZmljIGRhdGEgY2xlYW5pbmcgcHJvY2VkdXJlcyBJJ20gYWxsb3dlZCB0byBjYXJyeSBvdXQgb24gdGhlIGRhdGEuIEFuIGV4YW1wbGUgd291bGQgYmUgd2hhdCB0byBkbyBhYm91dCBudWxsIHZhbHVlcyBpbiB0aGUgZGF0YSBhbmQgd2hldGhlciBJJ20gYWxsb3dlZCB0byBkZWxldGUgYW55dGhpbmcgY29tcGxldGVseSBmcm9tIHRoZSBkYXRhIGZyYW1lLiBUbyBzdGF5IG9uIHRoZSBzYWZlIHNpZGUsIEkgY3JlYXRlZCBhIG5ldyBkYXRhIGZyYW1lIGNhbGxlZCAiY29tYmluZWRfdHJpcHNfdjIiIHdoZXJlIEkgcGVyZm9ybWVkIGFsbCBkYXRhIGNsZWFuaW5nIChkZWxldGluZykgZXhlcmNpc2VzIHdoaWxzdCByZXRhaW5pbmcgdGhlIGludGVncml0eSBvZiB0aGUgb3JpZ2luYWwgImNvbWJpbmVkX3RyaXBzIiBkYXRhIGZyYW1lLiANCg0KYGBge3J9DQojZGVsZXRpbmcgbnVsbCB2YWx1ZXMgDQpjb21iaW5lZF90cmlwc192MiA8LSBkcm9wX25hKGNvbWJpbmVkX3RyaXBzKQ0KYGBgDQoNCkRlbGV0aW5nIHRoZSBlbnRyaWVzIHdpdGggbmVnYXRpdmUgcmlkZV9sZW5ndGggc2luY2UgdGhlIGVuZCB0aW1lIHNob3VsZCBpZGVhbGx5IG5vdCBiZSBlYXJsaWVyIHRoYW4gdGhlIHN0YXJ0IHRpbWUuIA0KYGBge3J9DQpjb21iaW5lZF90cmlwc192MiA8LSBmaWx0ZXIgKGNvbWJpbmVkX3RyaXBzX3YyLCByaWRlX2xlbmd0aCA+IDApDQpgYGANCg0KRXh0cmFjdGluZyB0aGUgbG9uZ2l0dWRlIGFuZCBsYXRpdHVkZSBkYXRhIGZyb20gdGhlIGRhdGEgc2V0IGFzIGl0IHdpbGwgbm90IGJlIG5lZWRlZCBpbiB0aGlzIHBoYXNlIG9mIHRoZSBhbmFseXNpcy4gDQpgYGB7cn0NCmxhdF9sbmcxIDwtIHNlbGVjdChjb21iaW5lZF90cmlwc192MixzdGFydF9zdGF0aW9uX25hbWUsZW5kX3N0YXRpb25fbmFtZSxzdGFydF9sYXQsc3RhcnRfbG5nLGVuZF9sYXQsZW5kX2xuZyxtZW1iZXJfY2FzdWFsKQ0KYGBgDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YyIDwtIGNvbWJpbmVkX3RyaXBzX3YyICU+JQ0Kc2VsZWN0ICgtYyhzdGFydF9sYXQsIHN0YXJ0X2xuZywgZW5kX2xhdCwgZW5kX2xuZykpDQpgYGANCmBgYHtyfQ0KaGVhZCAoY29tYmluZWRfdHJpcHNfdjIpDQpgYGANCkFmdGVyIEkgY29uY2x1ZGVkIHRoYXQgbXkgZGF0YSB3YXMgaW4gdGhlIGNvcnJlY3QgZm9ybWF0IGFuZCBoYXMgYmVlbiBwcm9wZXJseSBjbGVhbmVkLCBJIG1vdmVkIG9uIHRvIHRoZSBuZXh0IHBoYXNlIG9mIHRoZSBhbmFseXNpcyBwcm9jZXNzOyBBbmFsc2lzLg0KDQojIyBBbmFseXNpcw0KQW5hbHlzaXMgaXMgdGhlIHByb2Nlc3Mgb2YgbWFraW5nIHNlbnNlIG9mIHRoZSBkYXRhIGNvbGxlY3RlZCAoYW5kIGNsZWFuZWQpLiBUaGUgZ29hbCBpcyB0byBpZGVudGlmeSB0cmVuZHMgYW5kIHJlbGF0aW9uc2hpcHMgd2l0aGluIHRoZSBkYXRhIHRoYXQgd2lsbCBoZWxwIGluIHNvbHZpbmcgdGhlIGJ1c2luZXNzIHRhc2suIA0KVGhlIG1haW4gcHVycG9zZSBvZiB0aGUgYW5hbHlzaXMgd2FzIHRvIGRlZHVjZSBhbGwgdGhlIHdheXMgdGhhdCBjeWNsaXN0IG1lbWJlcnMgYW5kIGN5Y2xpc3QgY2FzdWFscyB1c2VkIHRoZSBiaWN5Y2xlcyBkaWZmZXJlbnRseSwgaW4gbGluZSB3aXRoIHRoZSBidXNpbmVzcyB0YXNrLiANCg0KSSBzdGFydGVkIGJ5IHBlcmZvcm1pbmcgZGVzY3JpcHRpdmUgYW5hbHlzaXMgb24gdGhlIGRhdGEuIA0KIyMjIERlc2NyaXB0aXZlIGFuYWx5c2lzDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YyICU+JQ0KICBncm91cF9ieSAobWVtYmVyX2Nhc3VhbCkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfcmlkZXM9bigpLCBhdmVyYWdlX3JpZGVfbGVuZ3RoPW1lYW4ocmlkZV9sZW5ndGgpKQ0KYGBgDQoNCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjIgJT4lDQogIGNvdW50KHJpZGVhYmxlX3R5cGUpDQpgYGANCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjIgJT4lDQogIGdyb3VwX2J5KG1lbWJlcl9jYXN1YWwpJT4lDQogIGNvdW50IChyaWRlYWJsZV90eXBlKQ0KYGBgDQoNCmBgYHtyfQ0Kc3VtbWFyeSAoY29tYmluZWRfdHJpcHNfdjIkcmlkZV9sZW5ndGgpICNUaGlzIHNob3dzIGEgc3VtbWFyeSBvZiB0aGUgcmlkZSBsZW5ndGguIA0KYGBgDQoNCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjIlPiUNCiAgZ3JvdXBfYnkobWVtYmVyX2Nhc3VhbCklPiUNCiAgc3VtbWFyaXNlKG51bWJlcl9vZl9yaWRlcz1uKCksIG1pbl9yaWRlX2xlbmd0aD1taW4ocmlkZV9sZW5ndGgpLG1heF9yaWRlX2xlbmd0aD1tYXgocmlkZV9sZW5ndGgpLGF2Z19yaWRlX2xlbmd0aD1tZWFuKHJpZGVfbGVuZ3RoKSxtZWRpYW5fcmlkZV9sZW5ndGg9bWVkaWFuKHJpZGVfbGVuZ3RoKSkNCmBgYA0KT3JkZXJpbmcgdGhlIG1vbnRocyBmcm9tIEp1bmUgMjAyMSB0byBNYXkgMjAyMiBhbmQgdGhlIGRheXMgb2YgdGhlIHdlZWsgZnJvbSBTdW5kYXkgdG8gU2F0dXJkYXkuDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YyJG1vbnRoIDwtIG9yZGVyZWQoY29tYmluZWRfdHJpcHNfdjIkbW9udGgsIGxldmVscz1jKCAiSnVuZSIsICJKdWx5IiwgIkF1Z3VzdCIsICJTZXB0ZW1iZXIiLCAiT2N0b2JlciIsICJOb3ZlbWJlciIsICJEZWNlbWJlciIsIkphbnVhcnkiLCAiRmVicnVhcnkiLCAiTWFyY2giLCAiQXByaWwiLCAiTWF5IikpDQoNCmNvbWJpbmVkX3RyaXBzX3YyJGRheV9vZl90aGVfd2VlayA8LSBvcmRlcmVkKGNvbWJpbmVkX3RyaXBzX3YyJGRheV9vZl90aGVfd2VlaywgbGV2ZWxzPWMoIlN1bmRheSIsIk1vbmRheSIsIlR1ZXNkYXkiLCJXZWRuZXNkYXkiLCJUaHVyc2RheSIsIkZyaWRheSIsIlNhdHVyZGF5IikpDQpgYGANCg0KYGBge3J9DQpjb21iaW5lZF90cmlwc192MiAlPiUNCiAgZ3JvdXBfYnkobWVtYmVyX2Nhc3VhbCwgbW9udGgpICU+JQ0KICBzdW1tYXJpc2UobnVtYmVyX29mX3JpZGVzPW4oKSwgYXZlcmFnZV9yaWRlX2xlbmd0aD1tZWFuKHJpZGVfbGVuZ3RoKSklPiUNCiAgYXJyYW5nZSAobW9udGgpDQpgYGANCg0KYGBge3J9DQpjb21iaW5lZF90cmlwc192MiAlPiUNCiAgZ3JvdXBfYnkobWVtYmVyX2Nhc3VhbCwgZGF5X29mX3RoZV93ZWVrKSAlPiUNCiAgc3VtbWFyaXNlKG51bWJlcl9vZl9yaWRlcz1uKCksIGF2ZXJhZ2VfcmlkZV9sZW5ndGg9bWVhbihyaWRlX2xlbmd0aCkpJT4lDQogIGFycmFuZ2UgKGRheV9vZl90aGVfd2VlaykNCmBgYA0KTW9zdCBwb3B1bGFyIHN0YXJ0IHN0YXRpb25zIGZvciBjYXN1YWwgcmlkZXJzDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YyICU+JQ0KICBncm91cF9ieShzdGFydF9zdGF0aW9uX25hbWUsIG1lbWJlcl9jYXN1YWwpICU+JQ0KICBzdW1tYXJpc2UobnVtYmVyX29mX3RyaXBzPW4oKSkgJT4lDQogIGFycmFuZ2UoZGVzYyAobnVtYmVyX29mX3RyaXBzKSkgJT4lDQogIGZpbHRlcihtZW1iZXJfY2FzdWFsPT0gImNhc3VhbCIpICU+JQ0KICBzZWxlY3Qoc3RhcnRfc3RhdGlvbl9uYW1lLCBudW1iZXJfb2ZfdHJpcHMpDQpgYGANCk1vc3QgcG9wdWxhciBlbmQgc3RhdGlvbnMgZm9yIGNhc3VhbCByaWRlcnMNCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjIgJT4lDQogIGdyb3VwX2J5KGVuZF9zdGF0aW9uX25hbWUsIG1lbWJlcl9jYXN1YWwpICU+JQ0KICBzdW1tYXJpc2UobnVtYmVyX29mX3RyaXBzPW4oKSkgJT4lDQogIGFycmFuZ2UoZGVzYyAobnVtYmVyX29mX3RyaXBzKSkgJT4lDQogIGZpbHRlcihtZW1iZXJfY2FzdWFsPT0gImNhc3VhbCIpICU+JQ0KICBzZWxlY3QoZW5kX3N0YXRpb25fbmFtZSwgbnVtYmVyX29mX3RyaXBzKQ0KYGBgDQoNCkNyZWF0aW5nIGEgbmV3IHZlcnNpb24gb2YgdGhlIGRhdGEgc2V0IHRoYXQgY29tYmluZXMgdGhlIHN0YXJ0X3N0YXRpb25fbmFtZSBhbmQgdGhlIGVuZF9zdGF0aW9uX25hbWUgdG8gc2VydmUgYXMgYW4gYWdncmVnYXRlIHJlcHJlc2VudGF0aW9uIG9mIGVhY2ggcmlkZSByb3V0ZS4NCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjMgPC0gKHVuaXRlKGNvbWJpbmVkX3RyaXBzX3YyLCAicmlkZV9yb3V0ZXMiLCBzdGFydF9zdGF0aW9uX25hbWUsIGVuZF9zdGF0aW9uX25hbWUsIHNlcD0gIiB0byAiKSkNCmBgYA0KDQpgYGB7cn0NCmhlYWQgKGNvbWJpbmVkX3RyaXBzX3YzKQ0KYGBgDQoNCkV4dHJhY3RpbmcgZGF0YSBhYm91dCB0aGUgcmlkZSByb3V0ZXMgdG8gYmUgdXNlZCBmb3IgdmlzdWFsaXphdGlvbnMgaW4gVGFibGVhdS4NCmBgYHtyfQ0KdG9wX3JvdXRlcyA8LSBjb21iaW5lZF90cmlwc192MyAlPiUNCiAgZ3JvdXBfYnkocmlkZV9yb3V0ZXMpICU+JQ0KICBzdW1tYXJpc2UobnVtYmVyX29mX3JpZGVzPW4oKSkgJT4lDQogIGFycmFuZ2UgKGRlc2MgKG51bWJlcl9vZl9yaWRlcykpDQpgYGANCg0KYGBge3J9DQpoZWFkICh0b3Bfcm91dGVzLDEwKQ0KYGBgDQoNCmBgYHtyfQ0KdG9wX3JvdXRlc18xIDwtIGNvbWJpbmVkX3RyaXBzX3YzICU+JQ0KICBncm91cF9ieShyaWRlX3JvdXRlcywgbWVtYmVyX2Nhc3VhbCkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfcmlkZXM9bigpKSAlPiUNCiAgYXJyYW5nZSAoZGVzYyhudW1iZXJfb2ZfcmlkZXMpKSANCmBgYA0KDQpgYGB7cn0NCmhlYWQgKHRvcF9yb3V0ZXNfMSwgMTApDQpgYGANCg0KIyMgVmlzdWFsaXphdGlvbnMNCkNyZWF0aW5nIGNoYXJ0cyB0byB2aXN1YWxpemUgZGlmZmVyZW50IHBhcnRzIG9mIHRoZSBkYXRhIGFuZCBhY3F1aXJlIHVzZWZ1bCBpbnNpZ2h0cy4gVGFibGVhdSB3YXMgYWxzbyB1c2VkIGZvciB0aGlzIHNlY3Rpb24gb2YgdGhlIGFuYWx5c2lzLg0KDQojIyMgTnVtYmVyIG9mIHJpZGVzIGFuZCBBdmVyYWdlIHJpZGUgbGVuZ3RoIHNlZ21lbnRlZCBieSByaWRlciB0eXBlIA0KYGBge3J9DQpjb21iaW5lZF90cmlwc192MyAlPiUNCiAgZ3JvdXBfYnkobWVtYmVyX2Nhc3VhbCkgJT4lDQogIHN1bW1hcmlzZShBdmVyYWdlX3JpZGVfbGVuZ3RoPW1lYW4ocmlkZV9sZW5ndGgpKSAlPiUNCiAgZ2dwbG90KGFlcyh4PSBtZW1iZXJfY2FzdWFsLCB5PUF2ZXJhZ2VfcmlkZV9sZW5ndGgsIGZpbGw9bWVtYmVyX2Nhc3VhbCkpICsgZ2VvbV9jb2woKSArIGxhYnModGl0bGUgPSAiQXZlcmFnZSByaWRlIGxlbmd0aCBieSByaWRlciB0eXBlIiwgeD0iUmlkZXIgdHlwZSIsIHk9IkF2ZXJhZ2UgcmlkZSBsZW5ndGgiKQ0KYGBgDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YzICU+JQ0KICBncm91cF9ieShtZW1iZXJfY2FzdWFsLCBtb250aCkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfcmlkZXM9bigpLCBhdmVyYWdlX3JpZGVfbGVuZ3RoPW1lYW4ocmlkZV9sZW5ndGgpKSU+JQ0KICBnZ3Bsb3QgKGFlcyh4PW1vbnRoLCB5PW51bWJlcl9vZl9yaWRlcywgZmlsbD1tZW1iZXJfY2FzdWFsKSkgKyBnZW9tX2NvbChwb3NpdGlvbj0gImRvZGdlMiIpICsgbGFicyh0aXRsZSA9ICJOdW1iZXIgb2YgcmlkZXMgcGVyIG1vbnRoIHNlZ21lbnRlZCBieSByaWRlciB0eXBlIiwgeD0gIk1vbnRoIiwgeT0iTnVtYmVyIG9mIHJpZGVzIikrIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0PTEpKQ0KYGBgDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YzICU+JQ0KICBncm91cF9ieShtZW1iZXJfY2FzdWFsLCBtb250aCkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfcmlkZXM9bigpLCBhdmVyYWdlX3JpZGVfbGVuZ3RoPW1lYW4ocmlkZV9sZW5ndGgpKSU+JQ0KICBnZ3Bsb3QgKGFlcyh4PW1vbnRoLCB5PWF2ZXJhZ2VfcmlkZV9sZW5ndGgsIGZpbGw9bWVtYmVyX2Nhc3VhbCkpICsgZ2VvbV9jb2wocG9zaXRpb249ICJkb2RnZTIiKSArIGxhYnModGl0bGUgPSAiQXZlcmFnZSByaWRlIGxlbmd0aCBwZXIgbW9udGggc2VnbWVudGVkIGJ5IHJpZGVyIHR5cGUiLCB4PSAiTW9udGgiLCB5PSJBdmVyYWdlIHJpZGUgbGVuZ3RoIikrIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0PTEpKQ0KYGBgDQoNCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjMgJT4lDQogIGdyb3VwX2J5KG1lbWJlcl9jYXN1YWwsIGRheV9vZl90aGVfd2VlaykgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfcmlkZXM9bigpLCBhdmVyYWdlX3JpZGVfbGVuZ3RoPW1lYW4ocmlkZV9sZW5ndGgpKSU+JQ0KICBnZ3Bsb3QgKGFlcyh4PWRheV9vZl90aGVfd2VlaywgeT1udW1iZXJfb2ZfcmlkZXMsIGZpbGw9bWVtYmVyX2Nhc3VhbCkpICsgZ2VvbV9jb2wocG9zaXRpb249ICJkb2RnZTIiKSArIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIHJpZGVzIHBlciBkYXkgb2YgdGhlIHdlZWsiLCB4PSAiRGF5IG9mIHRoZSB3ZWVrIiwgeT0iTnVtYmVyIG9mIHJpZGVzIikNCmBgYA0KDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YzICU+JQ0KICBncm91cF9ieShtZW1iZXJfY2FzdWFsLCBkYXlfb2ZfdGhlX3dlZWspICU+JQ0KICBzdW1tYXJpc2UobnVtYmVyX29mX3JpZGVzPW4oKSwgYXZlcmFnZV9yaWRlX2xlbmd0aD1tZWFuKHJpZGVfbGVuZ3RoKSklPiUNCiAgZ2dwbG90IChhZXMoeD1kYXlfb2ZfdGhlX3dlZWssIHk9YXZlcmFnZV9yaWRlX2xlbmd0aCwgZmlsbD1tZW1iZXJfY2FzdWFsKSkgKyBnZW9tX2NvbChwb3NpdGlvbj0gImRvZGdlMiIpICsgbGFicyh0aXRsZSA9ICJBdmVyYWdlIHJpZGUgbGVuZ3RoIHBlciB3ZWVrIGRheSBzZWdtZW50ZWQgYnkgcmlkZXIgdHlwZSIsIHg9ICJEYXkgb2YgdGhlIHdlZWsiLCB5PSJBdmVyYWdlIHJpZGUgbGVuZ3RoIikrIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0PTEpKQ0KYGBgDQoNCiMjIyBOdW1iZXIgb2YgcmlkZXMgYW5kIEF2ZXJhZ2UgcmlkZSBsZW5ndGggc2VnbWVudGVkIGJ5IHJpZGVhYmxlIHR5cGUNCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjMgJT4lDQogIGdyb3VwX2J5KHJpZGVhYmxlX3R5cGUsIG1lbWJlcl9jYXN1YWwpICU+JQ0KICBzdW1tYXJpc2UobnVtYmVyX29mX3JpZGVzPW4oKSkgJT4lDQogIGdncGxvdChhZXMoeD1yaWRlYWJsZV90eXBlLCB5PW51bWJlcl9vZl9yaWRlcywgZmlsbD1tZW1iZXJfY2FzdWFsKSkgKyBnZW9tX2NvbChwb3NpdGlvbiA9ICJkb2RnZSIpICsgbGFicyh0aXRsZT0iTnVtYmVyIG9mIHJpZGVzIHBlciByaWRlYWJsZSB0eXBlIiAsIHg9IlJpZGVhYmxlIFR5cGUiLCB5PSJOdW1iZXIgb2YgcmlkZXMiKQ0KYGBgDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YzICU+JQ0KICBncm91cF9ieShyaWRlYWJsZV90eXBlLCBtZW1iZXJfY2FzdWFsKSAlPiUNCiAgc3VtbWFyaXNlKEF2ZXJhZ2VfcmlkZV9sZW5ndGggPSBtZWFuKHJpZGVfbGVuZ3RoKSkgJT4lDQogIGdncGxvdChhZXMoeD1yaWRlYWJsZV90eXBlLCB5PUF2ZXJhZ2VfcmlkZV9sZW5ndGgsIGZpbGw9bWVtYmVyX2Nhc3VhbCkpICsgZ2VvbV9jb2wocG9zaXRpb24gPSAiZG9kZ2UiKSArIGxhYnModGl0bGU9IkF2ZXJhZ2UgcmlkZSBsZW5ndGggcGVyIHJpZGVhYmxlIHR5cGUiICwgeD0iUmlkZWFibGUgVHlwZSIsIHk9IkF2ZXJhZ2UgcmlkZSBsZW5ndGgiKQ0KYGBgDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YzICU+JQ0KICBncm91cF9ieShtZW1iZXJfY2FzdWFsLCBtb250aCwgcmlkZWFibGVfdHlwZSkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfcmlkZXM9bigpLCBhdmVyYWdlX3JpZGVfbGVuZ3RoPW1lYW4ocmlkZV9sZW5ndGgpKSU+JQ0KICBnZ3Bsb3QgKGFlcyh4PW1vbnRoLCB5PW51bWJlcl9vZl9yaWRlcywgZmlsbD1yaWRlYWJsZV90eXBlKSkgKyBnZW9tX2NvbChwb3NpdGlvbj0iZG9kZ2UyIikgKyBmYWNldF93cmFwKH5tZW1iZXJfY2FzdWFsKSArIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIHJpZGVzIHNlZ21lbnRlZCBieSByaWRlYWJsZSB0eXBlcyBmb3IgZWFjaCBtb250aCIsIHg9Ik1vbnRoIiwgeT0iTnVtYmVyIG9mIHJpZGVzIikgKyB0aGVtZShheGlzLnRleHQueCA9IGVsZW1lbnRfdGV4dChhbmdsZSA9IDYwLCBoanVzdD0xKSkNCmBgYA0KDQpgYGB7cn0NCmNvbWJpbmVkX3RyaXBzX3YzICU+JQ0KICBncm91cF9ieShtZW1iZXJfY2FzdWFsLCBkYXlfb2ZfdGhlX3dlZWssIHJpZGVhYmxlX3R5cGUpICU+JQ0KICBzdW1tYXJpc2UobnVtYmVyX29mX3JpZGVzPW4oKSwgYXZlcmFnZV9yaWRlX2xlbmd0aD1tZWFuKHJpZGVfbGVuZ3RoKSklPiUNCiAgZ2dwbG90IChhZXMoeD1kYXlfb2ZfdGhlX3dlZWssIHk9bnVtYmVyX29mX3JpZGVzLCBmaWxsPXJpZGVhYmxlX3R5cGUpKSArIGdlb21fY29sKHBvc2l0aW9uID0gImRvZGdlIikgKyBmYWNldF93cmFwKH5tZW1iZXJfY2FzdWFsKSArIGxhYnModGl0bGUgPSAiTnVtYmVyIG9mIHJpZGVzIHNlZ21lbnRlZCBieSByaWRlYWJsZSB0eXBlcyBmb3IgZWFjaCBkYXkgb2YgdGhlIHdlZWsiLCB4PSJEYXkgb2YgdGhlIHdlZWsiLCB5PSJOdW1iZXIgb2YgcmlkZXMiKSArIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gNjAsIGhqdXN0PTEpKQ0KYGBgDQpgYGB7cn0NCmhlYWQgKGNvbWJpbmVkX3RyaXBzX3YyKQ0KYGBgDQoNCmBgYHtyfQ0KY29tYmluZWRfdHJpcHNfdjIgJT4lDQogIGdyb3VwX2J5KHN0YXJ0X3N0YXRpb25fbmFtZSwgbWVtYmVyX2Nhc3VhbCkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfdHJpcHM9bigpKSAlPiUNCiAgYXJyYW5nZShkZXNjIChudW1iZXJfb2ZfdHJpcHMpKSAlPiUNCiAgZmlsdGVyKG1lbWJlcl9jYXN1YWw9PSAiY2FzdWFsIiwgbnVtYmVyX29mX3RyaXBzID49IDE1NDYwKSAlPiUNCiAgc2VsZWN0KHN0YXJ0X3N0YXRpb25fbmFtZSwgbnVtYmVyX29mX3RyaXBzKSAlPiUNCiAgZ2dwbG90KGFlcyh4PXN0YXJ0X3N0YXRpb25fbmFtZSwgeT1udW1iZXJfb2ZfdHJpcHMpKSArIGdlb21fY29sKGZpbGw9ImJsdWUiKSArIGNvb3JkX2ZsaXAoKSArIGxhYnModGl0bGU9IlRvcCAxMCBtb3N0IHBvcHVsYXIgc3RhcnQgc3RhdGlvbnMgZm9yIGNhc3VhbCByaWRlcnMiLCB4PSJTdGFydCBzdGF0aW9uIG5hbWUiLCB5PSJOdW1iZXIgb2YgdHJpcHMiKQ0KICANCmBgYA0KYGBge3J9DQpjb21iaW5lZF90cmlwc192MiAlPiUNCiAgZ3JvdXBfYnkoZW5kX3N0YXRpb25fbmFtZSwgbWVtYmVyX2Nhc3VhbCkgJT4lDQogIHN1bW1hcmlzZShudW1iZXJfb2ZfdHJpcHM9bigpKSAlPiUNCiAgYXJyYW5nZShkZXNjIChudW1iZXJfb2ZfdHJpcHMpKSAlPiUNCiAgZmlsdGVyKG1lbWJlcl9jYXN1YWw9PSAiY2FzdWFsIiwgbnVtYmVyX29mX3RyaXBzID49IDE1NTk2KSAlPiUNCiAgc2VsZWN0KGVuZF9zdGF0aW9uX25hbWUsIG51bWJlcl9vZl90cmlwcykgJT4lDQogIGdncGxvdChhZXMoeD1lbmRfc3RhdGlvbl9uYW1lLCB5PW51bWJlcl9vZl90cmlwcykpICsgZ2VvbV9jb2woZmlsbD0icmVkIikgKyBjb29yZF9mbGlwKCkgKyBsYWJzKHRpdGxlPSJUb3AgMTAgbW9zdCBwb3B1bGFyIGVuZCBzdGF0aW9ucyBmb3IgY2FzdWFsIHJpZGVycyIsIHg9IkVuZCBzdGF0aW9uIG5hbWUiLCB5PSJOdW1iZXIgb2YgdHJpcHMiKQ0KICANCmBgYA0KVGhlIGRvY3VtZW50LCBwbG90cyBhbmQgdGFibGVzIGFyZSB0aGVuIGV4cG9ydGVkIGZvciBmdXJ0aGVyIGFuYWx5c2lzLiBGdXJ0aGVyIHZpc3VhbGlzYXRpb25zIGFsc28gcGVyZm9ybWVkIG9uIFRhYmxlYXUuIA0KU2F2aW5nIHRoZSBkYXRhZnJhbWVzIGFzIENTViBmaWxlcyBvbiBteSBsb2NhbCBkZXNrdG9wLiANCmBgYHtyfQ0Kd3JpdGUuY3N2KHRvcF9yb3V0ZXMsIkM6XFxVc2Vyc1xcVGVtaVxcRGVza3RvcFxcQ3ljbGlzdCBwcm9qZWN0XFx0b3Bfcm91dGVzLmNzdiIsIHJvdy5uYW1lcz1GQUxTRSkNCmBgYA0KYGBge3J9DQp3cml0ZS5jc3YoY29tYmluZWRfdHJpcHNfdjMsIkM6XFxVc2Vyc1xcVGVtaVxcRGVza3RvcFxcQ3ljbGlzdCBwcm9qZWN0XFxjb21iaW5lZF90cmlwc192My5jc3YiLCByb3cubmFtZXM9RkFMU0UpDQpgYGANCmBgYHtyfQ0Kd3JpdGUuY3N2KHRvcF9yb3V0ZXNfMSwiQzpcXFVzZXJzXFxUZW1pXFxEZXNrdG9wXFxDeWNsaXN0IHByb2plY3RcXHRvcF9yb3V0ZXNfMS5jc3YiLCByb3cubmFtZXM9RkFMU0UpDQpgYGANCmBgYHtyfQ0Kd3JpdGUuY3N2KGxhdF9sbmcxLCJDOlxcVXNlcnNcXFRlbWlcXERlc2t0b3BcXEN5Y2xpc3QgcHJvamVjdFxcbGF0X2xuZzEuY3N2Iiwgcm93Lm5hbWVzPUZBTFNFKQ0KYGBgDQoNCg0KDQoNCg0KDQo=