Loading the needed packages and getting the data

We’ll be using the tidyverse package and working with the strava data set from github

library(tidyverse)

strava <- read.csv('https://raw.githubusercontent.com/Shammalamala/STA2410/refs/heads/main/data/practice/strava%20full.csv') |> 
  dplyr::select(
    time = Moving.Time,
    distance = Distance,
    elevation_gain = Elevation.Gain,
    elevation_loss = Elevation.Gain,
    max_grade = Max.Grade
  ) |> 
  filter(distance > 5) |> 
  # Converting distance to miles and time to minutes 
  mutate(
    time = time/60,
    distance = distance * 0.6,
    elevation_gain = elevation_gain * 3.3,
    elevation_loss = elevation_loss * 3.3
  )

# Random sample of 10 rows
slice_sample(strava, n = 10)
##         time distance elevation_gain elevation_loss max_grade
## 1   26.93333    5.118       78.30059       78.30059  4.159235
## 2   89.21667   12.108      188.01345      188.01345  7.877260
## 3  139.58333   24.594      496.55589      496.55589  9.825160
## 4   29.88333    4.956      326.62117      326.62117 10.428879
## 5  101.78333   13.074      151.71131      151.71131  7.504580
## 6   53.93333   11.418      168.48578      168.48578  3.839808
## 7   82.30000   12.318      208.44120      208.44120  5.056998
## 8   76.83333   12.366      171.17973      171.17973  8.516098
## 9   30.73333    4.920      326.99460      326.99460 10.501966
## 10  65.33333    9.228      440.23488      440.23488 11.261410

The strava data sets has a beginner cyclist’s 138 bike rides of at least 3 miles. We want to see what the relationship is between the rider’s distance (\(X\)) and time (\(Y\)).

Q1) EDA: Is a linear model appropriate?

Step 1 is to visualize your data! Start by making a scatter plot with time on the y-axis and distance on the x-axis:

gg_trip <- 
  ggplot(
    data = strava,
    mapping = aes(
      x = distance,
      y = time
    )
  ) + 
  geom_point() + 
  theme_bw() + 
  labs(x = 'Distance (mi)',
       y = 'Time (min)')

gg_trip

Does a linear model seem appropriate?

Are there any potential issues with the data currently?

Question 2: Full Data

Part 2a) Estimating \(\beta_0\) and \(\beta_1\) by ‘hand’

Start by calculating \(b_0\) and \(b_1\) using one of the formulas, not by using lm(). Add the regression line to your plot from question 1

\[b_1 = \frac{\sum_i^n(X_i - \bar{X})(Y_i - \bar{Y})}{\sum_i^n(X_i - \bar{X})^2}\]

\[b0 = \bar{Y} - b_1 \bar{X}\]

# Getting the needed values:
## Xbar and Ybar
dist_avg <- mean(strava$distance); time_avg <- mean(strava$time)

## S_XX and S_XY
S_XY <- sum((strava$distance - dist_avg) * (strava$time - time_avg))
S_XX <- sum((strava$distance - dist_avg)^2)

# Model Estimates
## b1: slope
b1 <- S_XY/S_XX

## b0: intercept
b0 <- time_avg - b1 * dist_avg

round(c('b0' = b0, 'b1' = b1), 2)
##    b0    b1 
## 10.66  5.09

Adding the line with geom_smooth()

gg_trip +
  geom_smooth(
    method = 'lm',
    se = F,
    formula = y ~ x
  )

Part 1b) Checking your answer

Check your answer in 1a) by using the lm() function to fit the linear model:

trip_lm <- lm(time ~ distance, data = strava)
broom::tidy(trip_lm)
## # A tibble: 2 × 5
##   term        estimate std.error statistic  p.value
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)    10.7      2.83       3.77 2.42e- 4
## 2 distance        5.09     0.209     24.3  2.02e-51

Part 2b) Interpreting the slope

What is the interpretation of the slope, in context?

The average time spent cycling increases by 5.1 minutes for each additional mile traveled.

Part 2c) Interpreting the intercept

Interpret the intercept. Does the interpretation make sense in context?

For a trip that is 0 miles long, the average time spent cycling is about 10.7 minutes.

No, a trip that is 0 miles long should average 0 minutes spent cycling.

2d) State the linear model

Write out the linear model fully

\[Y_i = \beta_0 + \beta_1 X_i + \varepsilon_i\]

\[Y_i | X_i \sim N(\beta_0 + \beta_1 X_i, \sigma^2)\]

Part 2e) Calculate the predicted time and residuals

Calculate the predicted time and the residuals for the 138 trips in the data.

strava <- 
  strava |> 
  mutate(
    time_hat = b0 + b1 * distance,
    residual = time - time_hat
  )

strava
##          time distance elevation_gain elevation_loss max_grade  time_hat
## 1    22.38333    3.006      119.19558      119.19558  8.353217  25.96655
## 2    27.21667    4.266      134.74616      134.74616  7.346939  32.38417
## 3    59.98333    8.964       94.10215       94.10215  6.674271  56.31272
## 4    31.86667    4.446       65.86800       65.86800  3.338904  33.30097
## 5    54.68333    8.046      150.58128      150.58128  8.429718  51.63703
## 6    27.66667    4.560      143.59975      143.59975 10.576084  33.88161
## 7    66.98333   10.776      137.69970      137.69970  7.416707  65.54187
## 8    77.93333   14.976      519.62693      519.62693 10.973878  86.93394
## 9    45.43333    8.604       92.60842       92.60842 10.824524  54.47912
## 10   59.45000   11.094      164.86572      164.86572  8.181818  67.16156
## 11   24.88333    4.518       68.19154       68.19154  3.915776  33.66769
## 12   31.81667    3.960       32.84100       32.84100  5.131743  30.82560
## 13   32.25000    4.044       92.26039       92.26039  5.408403  31.25345
## 14  139.58333   24.594      496.55589      496.55589  9.825160 135.92177
## 15   65.83333   12.360      167.59715      167.59715  5.312108  73.60974
## 16   82.08333   10.290      146.02278      146.02278  9.776990  63.06650
## 17  104.56667   18.126      209.33530      209.33530  9.400964 102.97799
## 18   52.45000    8.904      113.63396      113.63396 11.282051  56.00712
## 19   94.36667   11.586      162.01196      162.01196  6.642880  69.66748
## 20  140.86667   20.256      656.64426      656.64426 11.722954 113.82682
## 21   77.80000    5.400       93.75904       93.75904  6.791202  38.16003
## 22   30.31667    5.700      177.43890      177.43890  6.653761  39.68803
## 23   72.06667    9.480      108.41576      108.41576  4.027645  58.94089
## 24   66.81667   13.014      186.39491      186.39491 10.513347  76.94079
## 25   67.66667    8.346      104.37044      104.37044  6.657781  53.16503
## 26   78.53333   11.520      148.88501      148.88501  4.012854  69.33132
## 27   62.41667   11.748      166.35313      166.35313  7.052099  70.49261
## 28   84.18333   11.274      158.40251      158.40251  5.876151  68.07836
## 29   30.33333    5.286      323.83886      323.83886 13.698164  37.57938
## 30   93.46667   17.388      187.39149      187.39149  6.459456  99.21909
## 31   68.93333   12.258      202.78883      202.78883 39.946281  73.09021
## 32   34.03333    4.686      147.59708      147.59708  6.926378  34.52338
## 33   86.88333   12.882      195.01491      195.01491  4.329078  76.26846
## 34  103.23333   12.678      170.79622      170.79622  5.873664  75.22942
## 35   78.28333   14.886      359.47776      359.47776 13.514721  86.47554
## 36   89.21667   12.108      188.01345      188.01345  7.877260  72.32621
## 37  120.10000   26.214      346.05396      346.05396 32.860008 144.17299
## 38   64.40000    8.760      128.90701      128.90701  8.738692  55.27368
## 39   97.71667   13.356      257.63208      257.63208  5.811342  78.68271
## 40   61.13333   12.222      205.43841      205.43841  3.989438  72.90685
## 41   49.91667    5.514      324.47330      324.47330 12.779366  38.74067
## 42   28.15000    5.358      136.01809      136.01809  6.816253  37.94611
## 43   31.35000    5.100      322.41661      322.41661 10.857809  36.63202
## 44   26.41667    5.094      144.13083      144.13083  6.444643  36.60146
## 45  134.16667   25.158      382.35412      382.35412  6.963736 138.79442
## 46   22.00000    3.138      281.56108      281.56108 11.669771  26.63887
## 47   26.73333    5.880      165.14911      165.14911 20.851810  40.60483
## 48   82.30000   12.318      208.44120      208.44120  5.056998  73.39582
## 49  115.40000   16.776      181.51798      181.51798  6.756846  96.10197
## 50   29.73333    4.920      322.42354      322.42354 12.534513  35.71522
## 51  108.83333   16.692      181.43006      181.43006  8.356910  95.67412
## 52   69.63333    9.618      139.43867      139.43867  8.032422  59.64377
## 53   30.01667    5.664       72.84672       72.84672  4.864443  39.50467
## 54   55.08333   11.688      199.09789      199.09789  8.584123  70.18701
## 55   63.01667    8.388      398.20269      398.20269 11.029201  53.37895
## 56   29.43333    4.818      323.44741      323.44741 12.675882  35.19570
## 57   26.00000    4.902      136.14199      136.14199  6.750165  35.62354
## 58   32.03333    4.926      322.62775      322.62775 12.618608  35.74578
## 59   28.93333    6.006      163.55877      163.55877  6.578863  41.24660
## 60   41.70000    7.692      115.82199      115.82199  4.276560  49.83398
## 61  108.43333   12.798      199.96092      199.96092 10.884933  75.84062
## 62   65.33333    9.228      440.23488      440.23488 11.261410  57.65737
## 63   29.73333    4.938      325.06493      325.06493 10.458420  35.80690
## 64   28.58333    5.574      135.94407      135.94407  6.358094  39.04627
## 65   92.90000   15.522      175.40533      175.40533  5.047650  89.71491
## 66   25.96667    4.926      139.43226      139.43226  6.989910  35.74578
## 67   97.25000   12.552      214.22361      214.22361  5.618348  74.58766
## 68   31.70000    4.956       95.93739       95.93739  4.278991  35.89858
## 69   40.05000    8.232      106.85262      106.85262  3.892714  52.58439
## 70  187.38333   10.914      492.05384      492.05384 18.858194  66.24475
## 71   38.10000    7.842      117.06085      117.06085  6.039771  50.59798
## 72   26.81667    4.002      296.17759      296.17759 10.243201  31.03952
## 73   82.35000    8.304      129.28168      129.28168 10.489474  52.95111
## 74   30.73333    4.920      326.99460      326.99460 10.501966  35.71522
## 75   23.25000    4.944      139.48490      139.48490 10.747322  35.83746
## 76   60.53333   11.958      163.76064      163.76064  8.203156  71.56221
## 77   29.55000    4.926      327.02350      327.02350 11.111456  35.74578
## 78   32.26667    5.724       83.27733       83.27733  4.324324  39.81027
## 79   69.61667   11.058      158.68351      158.68351  3.775612  66.97820
## 80   29.71667    5.994      116.81826      116.81826  5.857210  41.18548
## 81   28.26667    4.914      327.08395      327.08395 10.810811  35.68466
## 82   76.83333   12.366      171.17973      171.17973  8.516098  73.64030
## 83   62.35000   10.338      157.70425      157.70425  5.653294  63.31098
## 84   20.65000    3.864      221.85035      221.85035 10.000000  30.33664
## 85   54.40000    7.050      163.54676      163.54676  6.689531  46.56405
## 86   31.88333    6.516      129.63731      129.63731  9.175628  43.84420
## 87   47.15000    9.222      142.28506      142.28506  5.990932  57.62681
## 88   85.88333   17.676      202.97712      202.97712  7.885194 100.68598
## 89   54.50000    7.614      194.32058      194.32058  7.674724  49.43670
## 90  139.66667   24.552      378.18954      378.18954  8.781691 135.70785
## 91   58.40000   11.250      161.95887      161.95887  3.853608  67.95612
## 92   33.40000    6.450       69.81676       69.81676  3.957743  43.50804
## 93   79.80000   16.902      179.13350      179.13350  7.565825  96.74373
## 94   45.38333    7.962       98.52174       98.52174  4.239507  51.20919
## 95  120.18333   25.428      284.62946      284.62946  7.617502 140.16962
## 96   98.15000   17.016      166.22452      166.22452  7.445919  97.32437
## 97   42.26667    8.982      115.17242      115.17242  4.524967  56.40440
## 98   55.85000   11.214      161.57905      161.57905  4.231314  67.77276
## 99   59.60000    8.616      215.39653      215.39653  7.974535  54.54024
## 100  81.55000   16.734      172.73320      172.73320  7.584342  95.88804
## 101  73.28333   16.782      166.05721      166.05721  6.924182  96.13253
## 102 123.01667   15.882      207.33061      207.33061  7.279837  91.54851
## 103 106.90000   16.860      179.99763      179.99763  8.035874  96.52981
## 104 144.61667   25.758      493.36370      493.36370  9.474902 141.85043
## 105  71.43333    9.810      146.73794      146.73794  5.706855  60.62170
## 106 163.70000   25.062      365.87267      365.87267  8.494904 138.30546
## 107 145.73333   11.610      145.40985      145.40985 12.422662  69.78972
## 108  52.98333   11.208      161.50262      161.50262  3.385544  67.74220
## 109 114.60000   19.734      646.77064      646.77064 10.143636 111.16809
## 110 119.50000   26.322      339.35799      339.35799  9.358591 144.72307
## 111 147.40000   27.816      413.85941      413.85941  8.438401 152.33254
## 112  26.56667    5.106       44.89300       44.89300  4.245244  36.66258
## 113  26.93333    5.118       78.30059       78.30059  4.159235  36.72370
## 114  30.75000    5.988       97.57452       97.57452  3.805171  41.15492
## 115  58.05000   11.094      155.60513      155.60513  4.739487  67.16156
## 116  80.88333   16.770      165.68270      165.68270  6.896087  96.07140
## 117  57.75000    5.682       71.29702       71.29702  5.050555  39.59635
## 118 191.35000   39.174     1050.23054     1050.23054 13.552144 210.18280
## 119  48.65000    7.026      304.59638      304.59638  6.309165  46.44181
## 120  35.43333    8.352       54.30831       54.30831  6.363289  53.19559
## 121  52.26667    8.352      369.89782      369.89782  9.695658  53.19559
## 122  53.93333   11.418      168.48578      168.48578  3.839808  68.81180
## 123 279.38333   53.304      951.53286      951.53286 48.395321 282.15182
## 124  65.25000    9.540      162.55572      162.55572  9.657064  59.24649
## 125  82.03333   16.782      171.93591      171.93591  7.506414  96.13253
## 126  58.56667   12.276      209.75587      209.75587  8.121613  73.18189
## 127 101.78333   13.074      151.71131      151.71131  7.504580  77.24639
## 128  77.28333   16.794      165.02780      165.02780  6.883777  96.19365
## 129  55.15000    8.850      110.47016      110.47016  5.844007  55.73208
## 130 110.20000   17.826      423.11216      423.11216  9.102761 101.44998
## 131  82.33333   12.300      177.33205      177.33205  5.794040  73.30413
## 132 145.81667   24.492      490.69101      490.69101 10.559812 135.40225
## 133  77.33333   16.806      165.80613      165.80613  7.142857  96.25477
## 134  32.81667    5.280      349.90660      349.90660 13.034019  37.54882
## 135  78.38333   16.800      165.09365      165.09365  7.112907  96.22421
## 136  58.35000   11.520      153.76747      153.76747  4.016070  69.33132
## 137  64.86667    9.288      163.60939      163.60939 14.005334  57.96297
## 138  29.88333    4.956      326.62117      326.62117 10.428879  35.89858
##        residual
## 1    -3.5832156
## 2    -5.1675020
## 3     3.6706109
## 4    -1.4343048
## 5     3.0463053
## 6    -6.2149466
## 7     1.4414625
## 8    -9.0006034
## 9    -9.0457834
## 10   -7.7115558
## 11   -8.7843593
## 12    0.9910628
## 13    0.9965548
## 14    3.6615656
## 15   -7.7764024
## 16   19.0168301
## 17    1.5886805
## 18   -3.5571215
## 19   24.6991831
## 20   27.0398471
## 21   39.6399735
## 22   -9.3713645
## 23   13.1257762
## 24  -10.1241193
## 25   14.5016340
## 26    9.2020108
## 27   -8.0759394
## 28   16.1049747
## 29   -7.2460514
## 30   -5.7524279
## 31   -4.1568808
## 32   -0.4900419
## 33   10.6148694
## 34   28.0039126
## 35   -8.1922020
## 36   16.8904549
## 37  -24.0729931
## 38    9.1263208
## 39   19.0339553
## 40  -11.7735202
## 41   11.1759984
## 42   -9.7961058
## 43   -5.2820218
## 44  -10.1847950
## 45   -4.6277499
## 46   -4.6388710
## 47  -13.8715007
## 48    8.9041850
## 49   19.2980350
## 50   -5.9818856
## 51   13.1592096
## 52    9.9895607
## 53   -9.4880040
## 54  -15.1036718
## 55    9.6377133
## 56   -5.7623640
## 57   -9.6235387
## 58   -3.7124457
## 59  -12.3132627
## 60   -8.1339824
## 61   32.5927108
## 62    7.6759668
## 63   -6.0735659
## 64  -10.4629359
## 65    3.1850947
## 66   -9.7791124
## 67   22.6623413
## 68   -4.1985795
## 69  -12.5343909
## 70  121.1385803
## 71  -12.4979848
## 72   -4.2228579
## 73   29.3988880
## 74   -4.9818856
## 75  -12.5874593
## 76  -11.0288761
## 77   -6.1957790
## 78   -7.5436049
## 79    2.6384714
## 80  -11.4688091
## 81   -7.4179922
## 82    3.1930375
## 83   -0.9609840
## 84   -9.6866424
## 85    7.8359476
## 86  -11.9608707
## 87  -10.4768065
## 88  -14.8026458
## 89    5.0632988
## 90    3.9588196
## 91   -9.5561183
## 92  -10.1080430
## 93  -16.9437270
## 94   -5.8258533
## 95  -19.9862874
## 96    0.8256312
## 97  -14.1377360
## 98  -11.9227577
## 99    5.0597631
## 100 -14.3380443
## 101 -22.8491918
## 102  31.4681557
## 103  10.3701937
## 104   2.7662407
## 105  10.8116377
## 106  25.3945450
## 107  75.9436094
## 108 -14.7588643
## 109   3.4319086
## 110 -25.2230748
## 111  -4.9325383
## 112 -10.0959152
## 113  -9.7903687
## 114 -10.4049157
## 115  -9.1115558
## 116 -15.1880716
## 117  18.1536491
## 118 -18.8327965
## 119   2.2081880
## 120 -17.7622595
## 121  -0.9289261
## 122 -14.8784676
## 123  -2.7684849
## 124   6.0035086
## 125 -14.0991918
## 126 -14.6152277
## 127  24.5369464
## 128 -18.9103120
## 129  -0.5820806
## 130   8.7500185
## 131   9.0291986
## 132  10.4144206
## 133 -18.9214321
## 134  -4.7321579
## 135 -17.8408720
## 136 -10.9813225
## 137   6.9036992
## 138  -6.0152462

Part 2f) Estimate \(\sigma\)

Calculate the estimate of \(\sigma\), \(\hat{\sigma} = s\)

\[s^2 = MSE = \frac{SSE}{n - p} = \frac{\sum_i^n (Y_i - \hat{Y}_i)^2}{n - 2}\]

# We'll start by calculating the SSE
SSE <- sum(strava$residual^2)

# Then MSE
MSE <- SSE / (nrow(strava) - 2)

# The estimated standard deviation of the residuals
res_sd <- sqrt(MSE)

res_sd
## [1] 17.8638

Question 3: Outliers and High Leverage Points

We’ll discuss outliers and high leverage points in more detail in chapter 3, but for now, we want to remove four points from the strava data:

  1. The two outliers with residuals above 75 minutes

  2. The two high leverage points with distance > 30 miles

Part 3a) No outliers

Fit a model with out the two outliers. You can use the lm() function estimated the intercept, slope, and \(s^2\). Does it appear those two trips were influential (aka, did \(b_1\) and \(s\) change by noticeable amounts)?

trip_no_outliers_lm <- 
  lm(time ~ distance, data = strava |> filter(residual < 75))

# Model terms
broom::tidy(trip_no_outliers_lm)
## # A tibble: 2 × 5
##   term        estimate std.error statistic  p.value
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)     9.14     2.06       4.43 1.91e- 5
## 2 distance        5.10     0.152     33.5  6.08e-67
# s
broom::glance(trip_no_outliers_lm) |> dplyr::select(sigma)
## # A tibble: 1 × 1
##   sigma
##   <dbl>
## 1  13.0

No, the slope is almost exactly the same! 5.0933 with the two outliers vs 5.0989 without the outliers.

On the other hand, \(s\) decreased from 17.86 to about 13, which is a noticeable decrease!

The two outliers do not appear to be influential!

Part 3b) Without the high leverage points

Fit the linear model, now without the leverage points (but keep the outliers). Again, do the high leverage points appear to be influential?

trip_no_leverage_lm <- 
  lm(time ~ distance, data = strava |> filter(distance < 30))

# Model terms
broom::tidy(trip_no_leverage_lm)
## # A tibble: 2 × 5
##   term        estimate std.error statistic  p.value
##   <chr>          <dbl>     <dbl>     <dbl>    <dbl>
## 1 (Intercept)     9.32     3.22       2.89 4.45e- 3
## 2 distance        5.23     0.260     20.1  3.01e-42
# s
broom::glance(trip_no_leverage_lm) |> dplyr::select(sigma)
## # A tibble: 1 × 1
##   sigma
##   <dbl>
## 1  17.9

The two high leverage trips had a larger effect on the slope than the two outliers did, but it still isn’t a dramatic change.

Part 3c) Comparing 3a) and 3b)

Which two sets of trips had a larger impact on the slope: the two outliers or the two high leverage? Justify your answer.

Plot the three lines (all trips, no outliers, no high leverage). You can have geom_smooth() plot across the entire range of the graph by including fullrange = T

The two high leverage trips had a larger impact on the slope than the outliers since the slope changed more, but still not a dramatic change.

gg_trip + 
  geom_smooth(
    mapping = aes(color = 'All Trips'),
    method = 'lm',
    se = F,
    formula = y ~ x,
    alpha = 0.5
  ) + 
  geom_smooth(
    data = strava |> filter(residual < 75),
    mapping = aes(color = 'No Outliers'),
    method = 'lm',
    se = F,
    formula = y ~ x,
    alpha = 0.5
  ) + 
  geom_smooth(
    data = strava |> filter(distance < 30),
    mapping = aes(color = 'No High Leverage'),
    method = 'lm',
    formula = y ~ x,
    se = F,
    alpha = 0.5,
    fullrange = T
  )

Question 4: Intercept = 0

Since a trip that traveled 0 miles should have a moving speed of 0 minutes, we’ll force the intercept to be 0.

Fit a linear model using lm() with forcing \(b_0 = 0\). You can have lm() not include the intercept by including -1 in the formula. For example: y ~ -1 + x

trip_lm_no_int <- lm(time ~ -1 + distance, data = strava)

broom::tidy(trip_lm_no_int)
## # A tibble: 1 × 5
##   term     estimate std.error statistic  p.value
##   <chr>       <dbl>     <dbl>     <dbl>    <dbl>
## 1 distance     5.76     0.118      48.8 1.52e-88
LS0tDQp0aXRsZTogJ1NMUiBQcmFjdGljZTogQmlraW5nIFRyaXBzJw0KYXV0aG9yOiAiQ2hhcHRlciAxIg0KZGF0ZTogIlNUQSA0MjEwIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGZpZ193aWR0aDogMTANCiAgICBmaWdfaGVpZ2h0OiA2DQogICAgZmlnX2NhcHRpb246IHRydWUNCiAgICB0b2M6IHRydWUNCiAgICB0b2NfZmxvYXQ6IHRydWUNCiAgICBudW1iZXJfc2VjdGlvbnM6IGZhbHNlDQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQogICAgY29kZV9kb3dubG9hZDogdHJ1ZQ0KICAgIHNtb290aF9zY3JvbGw6IHRydWUNCiAgICB0aGVtZTogbHVtZW4NCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldChlY2hvID0gVFJVRSkNCmBgYA0KDQoNCiMjIExvYWRpbmcgdGhlIG5lZWRlZCBwYWNrYWdlcyBhbmQgZ2V0dGluZyB0aGUgZGF0YQ0KDQpXZSdsbCBiZSB1c2luZyB0aGUgYHRpZHl2ZXJzZWAgcGFja2FnZSBhbmQgd29ya2luZyB3aXRoIHRoZSAqKnN0cmF2YSoqIGRhdGEgc2V0IGZyb20gZ2l0aHViDQoNCmBgYHtyIHBhY2thZ2VzX2FuZF9kYXRhLCBtZXNzYWdlID0gRn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQpzdHJhdmEgPC0gcmVhZC5jc3YoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS9TaGFtbWFsYW1hbGEvU1RBMjQxMC9yZWZzL2hlYWRzL21haW4vZGF0YS9wcmFjdGljZS9zdHJhdmElMjBmdWxsLmNzdicpIHw+IA0KICBkcGx5cjo6c2VsZWN0KA0KICAgIHRpbWUgPSBNb3ZpbmcuVGltZSwNCiAgICBkaXN0YW5jZSA9IERpc3RhbmNlLA0KICAgIGVsZXZhdGlvbl9nYWluID0gRWxldmF0aW9uLkdhaW4sDQogICAgZWxldmF0aW9uX2xvc3MgPSBFbGV2YXRpb24uR2FpbiwNCiAgICBtYXhfZ3JhZGUgPSBNYXguR3JhZGUNCiAgKSB8PiANCiAgZmlsdGVyKGRpc3RhbmNlID4gNSkgfD4gDQogICMgQ29udmVydGluZyBkaXN0YW5jZSB0byBtaWxlcyBhbmQgdGltZSB0byBtaW51dGVzIA0KICBtdXRhdGUoDQogICAgdGltZSA9IHRpbWUvNjAsDQogICAgZGlzdGFuY2UgPSBkaXN0YW5jZSAqIDAuNiwNCiAgICBlbGV2YXRpb25fZ2FpbiA9IGVsZXZhdGlvbl9nYWluICogMy4zLA0KICAgIGVsZXZhdGlvbl9sb3NzID0gZWxldmF0aW9uX2xvc3MgKiAzLjMNCiAgKQ0KDQojIFJhbmRvbSBzYW1wbGUgb2YgMTAgcm93cw0Kc2xpY2Vfc2FtcGxlKHN0cmF2YSwgbiA9IDEwKQ0KYGBgDQoNClRoZSAqKnN0cmF2YSoqIGRhdGEgc2V0cyBoYXMgYSBiZWdpbm5lciBjeWNsaXN0J3MgMTM4IGJpa2UgcmlkZXMgb2YgYXQgbGVhc3QgMyBtaWxlcy4gV2Ugd2FudCB0byBzZWUgd2hhdCB0aGUgcmVsYXRpb25zaGlwIGlzIGJldHdlZW4gdGhlIHJpZGVyJ3MgKipkaXN0YW5jZSoqICgkWCQpIGFuZCAqKnRpbWUqKiAoJFkkKS4NCg0KDQojIyBRMSkgRURBOiBJcyBhIGxpbmVhciBtb2RlbCBhcHByb3ByaWF0ZT8NCg0KU3RlcCAxIGlzIHRvIHZpc3VhbGl6ZSB5b3VyIGRhdGEhIFN0YXJ0IGJ5IG1ha2luZyBhIHNjYXR0ZXIgcGxvdCB3aXRoICp0aW1lKiBvbiB0aGUgeS1heGlzIGFuZCAqZGlzdGFuY2UqIG9uIHRoZSB4LWF4aXM6DQoNCmBgYHtyIFExfQ0KZ2dfdHJpcCA8LSANCiAgZ2dwbG90KA0KICAgIGRhdGEgPSBzdHJhdmEsDQogICAgbWFwcGluZyA9IGFlcygNCiAgICAgIHggPSBkaXN0YW5jZSwNCiAgICAgIHkgPSB0aW1lDQogICAgKQ0KICApICsgDQogIGdlb21fcG9pbnQoKSArIA0KICB0aGVtZV9idygpICsgDQogIGxhYnMoeCA9ICdEaXN0YW5jZSAobWkpJywNCiAgICAgICB5ID0gJ1RpbWUgKG1pbiknKQ0KDQpnZ190cmlwDQpgYGANCg0KRG9lcyBhIGxpbmVhciBtb2RlbCBzZWVtIGFwcHJvcHJpYXRlPw0KDQoNCg0KDQpBcmUgdGhlcmUgYW55IHBvdGVudGlhbCBpc3N1ZXMgd2l0aCB0aGUgZGF0YSBjdXJyZW50bHk/DQoNCg0KDQoNCiMjIFF1ZXN0aW9uIDI6IEZ1bGwgRGF0YQ0KDQoNCiMjIyBQYXJ0IDJhKSBFc3RpbWF0aW5nICRcYmV0YV8wJCBhbmQgJFxiZXRhXzEkIGJ5ICdoYW5kJw0KDQpTdGFydCBieSBjYWxjdWxhdGluZyAkYl8wJCBhbmQgJGJfMSQgdXNpbmcgb25lIG9mIHRoZSBmb3JtdWxhcywgbm90IGJ5IHVzaW5nIGBsbSgpYC4gQWRkIHRoZSByZWdyZXNzaW9uIGxpbmUgdG8geW91ciBwbG90IGZyb20gcXVlc3Rpb24gMQ0KDQoNCiQkYl8xID0gXGZyYWN7XHN1bV9pXm4oWF9pIC0gXGJhcntYfSkoWV9pIC0gXGJhcntZfSl9e1xzdW1faV5uKFhfaSAtIFxiYXJ7WH0pXjJ9JCQNCg0KJCRiMCA9IFxiYXJ7WX0gLSBiXzEgXGJhcntYfSQkDQoNCg0KDQpgYGB7ciAxYV9leGFjdF9mb3JtdWxhfQ0KIyBHZXR0aW5nIHRoZSBuZWVkZWQgdmFsdWVzOg0KIyMgWGJhciBhbmQgWWJhcg0KZGlzdF9hdmcgPC0gbWVhbihzdHJhdmEkZGlzdGFuY2UpOyB0aW1lX2F2ZyA8LSBtZWFuKHN0cmF2YSR0aW1lKQ0KDQojIyBTX1hYIGFuZCBTX1hZDQpTX1hZIDwtIHN1bSgoc3RyYXZhJGRpc3RhbmNlIC0gZGlzdF9hdmcpICogKHN0cmF2YSR0aW1lIC0gdGltZV9hdmcpKQ0KU19YWCA8LSBzdW0oKHN0cmF2YSRkaXN0YW5jZSAtIGRpc3RfYXZnKV4yKQ0KDQojIE1vZGVsIEVzdGltYXRlcw0KIyMgYjE6IHNsb3BlDQpiMSA8LSBTX1hZL1NfWFgNCg0KIyMgYjA6IGludGVyY2VwdA0KYjAgPC0gdGltZV9hdmcgLSBiMSAqIGRpc3RfYXZnDQoNCnJvdW5kKGMoJ2IwJyA9IGIwLCAnYjEnID0gYjEpLCAyKQ0KYGBgDQoNCg0KQWRkaW5nIHRoZSBsaW5lIHdpdGggYGdlb21fc21vb3RoKClgDQoNCmBgYHtyIHEyYV9hZGRfbGluZX0NCmdnX3RyaXAgKw0KICBnZW9tX3Ntb290aCgNCiAgICBtZXRob2QgPSAnbG0nLA0KICAgIHNlID0gRiwNCiAgICBmb3JtdWxhID0geSB+IHgNCiAgKQ0KYGBgDQoNCg0KDQojIyMgUGFydCAxYikgQ2hlY2tpbmcgeW91ciBhbnN3ZXINCg0KQ2hlY2sgeW91ciBhbnN3ZXIgaW4gMWEpIGJ5IHVzaW5nIHRoZSBgbG0oKWAgZnVuY3Rpb24gdG8gZml0IHRoZSBsaW5lYXIgbW9kZWw6DQoNCmBgYHtyIDFiX2xtfQ0KdHJpcF9sbSA8LSBsbSh0aW1lIH4gZGlzdGFuY2UsIGRhdGEgPSBzdHJhdmEpDQpicm9vbTo6dGlkeSh0cmlwX2xtKQ0KYGBgDQoNCg0KDQojIyMgUGFydCAyYikgSW50ZXJwcmV0aW5nIHRoZSBzbG9wZQ0KDQpXaGF0IGlzIHRoZSBpbnRlcnByZXRhdGlvbiBvZiB0aGUgc2xvcGUsIGluIGNvbnRleHQ/DQoNCioqVGhlIGF2ZXJhZ2UgdGltZSBzcGVudCBjeWNsaW5nIGluY3JlYXNlcyBieSA1LjEgbWludXRlcyBmb3IgZWFjaCBhZGRpdGlvbmFsIG1pbGUgdHJhdmVsZWQuKioNCg0KDQojIyMgUGFydCAyYykgSW50ZXJwcmV0aW5nIHRoZSBpbnRlcmNlcHQNCg0KSW50ZXJwcmV0IHRoZSBpbnRlcmNlcHQuIERvZXMgdGhlIGludGVycHJldGF0aW9uIG1ha2Ugc2Vuc2UgaW4gY29udGV4dD8NCg0KKipGb3IgYSB0cmlwIHRoYXQgaXMgMCBtaWxlcyBsb25nLCB0aGUgYXZlcmFnZSB0aW1lIHNwZW50IGN5Y2xpbmcgaXMgYWJvdXQgMTAuNyBtaW51dGVzLioqDQoNCioqTm8sIGEgdHJpcCB0aGF0IGlzIDAgbWlsZXMgbG9uZyBzaG91bGQgYXZlcmFnZSAwIG1pbnV0ZXMgc3BlbnQgY3ljbGluZy4qKg0KDQoNCg0KDQojIyMgMmQpIFN0YXRlIHRoZSBsaW5lYXIgbW9kZWwNCg0KV3JpdGUgb3V0IHRoZSBsaW5lYXIgbW9kZWwgZnVsbHkNCg0KJCRZX2kgPSBcYmV0YV8wICsgXGJldGFfMSBYX2kgKyBcdmFyZXBzaWxvbl9pJCQNCg0KJCRZX2kgfCBYX2kgXHNpbSBOKFxiZXRhXzAgKyBcYmV0YV8xIFhfaSwgXHNpZ21hXjIpJCQNCg0KIyMjIFBhcnQgMmUpIENhbGN1bGF0ZSB0aGUgcHJlZGljdGVkIHRpbWUgYW5kIHJlc2lkdWFscw0KDQpDYWxjdWxhdGUgdGhlIHByZWRpY3RlZCB0aW1lIGFuZCB0aGUgcmVzaWR1YWxzIGZvciB0aGUgMTM4IHRyaXBzIGluIHRoZSBkYXRhLiANCg0KYGBge3J9DQpzdHJhdmEgPC0gDQogIHN0cmF2YSB8PiANCiAgbXV0YXRlKA0KICAgIHRpbWVfaGF0ID0gYjAgKyBiMSAqIGRpc3RhbmNlLA0KICAgIHJlc2lkdWFsID0gdGltZSAtIHRpbWVfaGF0DQogICkNCg0Kc3RyYXZhDQpgYGANCg0KDQoNCg0KDQojIyMgUGFydCAyZikgRXN0aW1hdGUgJFxzaWdtYSQNCg0KQ2FsY3VsYXRlIHRoZSBlc3RpbWF0ZSBvZiAkXHNpZ21hJCwgJFxoYXR7XHNpZ21hfSA9IHMkDQoNCg0KJCRzXjIgPSBNU0UgPSBcZnJhY3tTU0V9e24gLSBwfSA9IFxmcmFje1xzdW1faV5uIChZX2kgLSBcaGF0e1l9X2kpXjJ9e24gLSAyfSQkDQoNCmBgYHtyIDFmX3NpZ21hMl9oYXR9DQojIFdlJ2xsIHN0YXJ0IGJ5IGNhbGN1bGF0aW5nIHRoZSBTU0UNClNTRSA8LSBzdW0oc3RyYXZhJHJlc2lkdWFsXjIpDQoNCiMgVGhlbiBNU0UNCk1TRSA8LSBTU0UgLyAobnJvdyhzdHJhdmEpIC0gMikNCg0KIyBUaGUgZXN0aW1hdGVkIHN0YW5kYXJkIGRldmlhdGlvbiBvZiB0aGUgcmVzaWR1YWxzDQpyZXNfc2QgPC0gc3FydChNU0UpDQoNCnJlc19zZA0KYGBgDQoNCg0KIyMgUXVlc3Rpb24gMzogT3V0bGllcnMgYW5kIEhpZ2ggTGV2ZXJhZ2UgUG9pbnRzDQoNCldlJ2xsIGRpc2N1c3Mgb3V0bGllcnMgYW5kIGhpZ2ggbGV2ZXJhZ2UgcG9pbnRzIGluIG1vcmUgZGV0YWlsIGluIGNoYXB0ZXIgMywgYnV0IGZvciBub3csIHdlIHdhbnQgdG8gcmVtb3ZlIGZvdXIgcG9pbnRzIGZyb20gdGhlICoqc3RyYXZhKiogZGF0YToNCg0KMSkgVGhlIHR3byBvdXRsaWVycyB3aXRoIHJlc2lkdWFscyBhYm92ZSA3NSBtaW51dGVzDQoNCjIpIFRoZSB0d28gaGlnaCBsZXZlcmFnZSBwb2ludHMgd2l0aCBkaXN0YW5jZSA+IDMwIG1pbGVzDQoNCiMjIyBQYXJ0IDNhKSBObyBvdXRsaWVycw0KDQpGaXQgYSBtb2RlbCB3aXRoIG91dCB0aGUgdHdvIG91dGxpZXJzLiBZb3UgY2FuIHVzZSB0aGUgYGxtKClgIGZ1bmN0aW9uIGVzdGltYXRlZCB0aGUgaW50ZXJjZXB0LCBzbG9wZSwgYW5kICRzXjIkLiBEb2VzIGl0IGFwcGVhciB0aG9zZSB0d28gdHJpcHMgd2VyZSBpbmZsdWVudGlhbCAoYWthLCBkaWQgJGJfMSQgYW5kICRzJCBjaGFuZ2UgYnkgbm90aWNlYWJsZSBhbW91bnRzKT8NCg0KDQpgYGB7ciAzYV9vdXRsaWVyc30NCnRyaXBfbm9fb3V0bGllcnNfbG0gPC0gDQogIGxtKHRpbWUgfiBkaXN0YW5jZSwgZGF0YSA9IHN0cmF2YSB8PiBmaWx0ZXIocmVzaWR1YWwgPCA3NSkpDQoNCiMgTW9kZWwgdGVybXMNCmJyb29tOjp0aWR5KHRyaXBfbm9fb3V0bGllcnNfbG0pDQoNCiMgcw0KYnJvb206OmdsYW5jZSh0cmlwX25vX291dGxpZXJzX2xtKSB8PiBkcGx5cjo6c2VsZWN0KHNpZ21hKQ0KYGBgDQoNCg0KTm8sIHRoZSBzbG9wZSBpcyBhbG1vc3QgZXhhY3RseSB0aGUgc2FtZSEgNS4wOTMzIHdpdGggdGhlIHR3byBvdXRsaWVycyB2cyA1LjA5ODkgd2l0aG91dCB0aGUgb3V0bGllcnMuIA0KDQpPbiB0aGUgb3RoZXIgaGFuZCwgJHMkIGRlY3JlYXNlZCBmcm9tIDE3Ljg2IHRvIGFib3V0IDEzLCB3aGljaCBpcyBhIG5vdGljZWFibGUgZGVjcmVhc2UhDQoNClRoZSB0d28gb3V0bGllcnMgZG8gbm90IGFwcGVhciB0byBiZSBpbmZsdWVudGlhbCENCg0KDQoNCiMjIyBQYXJ0IDNiKSBXaXRob3V0IHRoZSBoaWdoIGxldmVyYWdlIHBvaW50cw0KDQpGaXQgdGhlIGxpbmVhciBtb2RlbCwgbm93IHdpdGhvdXQgdGhlIGxldmVyYWdlIHBvaW50cyAoYnV0IGtlZXAgdGhlIG91dGxpZXJzKS4gQWdhaW4sIGRvIHRoZSBoaWdoIGxldmVyYWdlIHBvaW50cyBhcHBlYXIgdG8gYmUgaW5mbHVlbnRpYWw/DQoNCg0KYGBge3IgM2JfaGlnaF9sZXZlcmFnZX0NCnRyaXBfbm9fbGV2ZXJhZ2VfbG0gPC0gDQogIGxtKHRpbWUgfiBkaXN0YW5jZSwgZGF0YSA9IHN0cmF2YSB8PiBmaWx0ZXIoZGlzdGFuY2UgPCAzMCkpDQoNCiMgTW9kZWwgdGVybXMNCmJyb29tOjp0aWR5KHRyaXBfbm9fbGV2ZXJhZ2VfbG0pDQoNCiMgcw0KYnJvb206OmdsYW5jZSh0cmlwX25vX2xldmVyYWdlX2xtKSB8PiBkcGx5cjo6c2VsZWN0KHNpZ21hKQ0KYGBgDQoNClRoZSB0d28gaGlnaCBsZXZlcmFnZSB0cmlwcyBoYWQgYSBsYXJnZXIgZWZmZWN0IG9uIHRoZSBzbG9wZSB0aGFuIHRoZSB0d28gb3V0bGllcnMgZGlkLCBidXQgaXQgc3RpbGwgaXNuJ3QgYSBkcmFtYXRpYyBjaGFuZ2UuIA0KDQoNCg0KIyMjIFBhcnQgM2MpIENvbXBhcmluZyAzYSkgYW5kIDNiKQ0KDQpXaGljaCB0d28gc2V0cyBvZiB0cmlwcyBoYWQgYSBsYXJnZXIgaW1wYWN0IG9uIHRoZSBzbG9wZTogdGhlIHR3byBvdXRsaWVycyBvciB0aGUgdHdvIGhpZ2ggbGV2ZXJhZ2U/IEp1c3RpZnkgeW91ciBhbnN3ZXIuDQoNClBsb3QgdGhlIHRocmVlIGxpbmVzIChhbGwgdHJpcHMsIG5vIG91dGxpZXJzLCBubyBoaWdoIGxldmVyYWdlKS4gWW91IGNhbiBoYXZlIGBnZW9tX3Ntb290aCgpYCBwbG90IGFjcm9zcyB0aGUgZW50aXJlIHJhbmdlIG9mIHRoZSBncmFwaCBieSBpbmNsdWRpbmcgYGZ1bGxyYW5nZSA9IFRgDQoNClRoZSB0d28gaGlnaCBsZXZlcmFnZSB0cmlwcyBoYWQgYSBsYXJnZXIgaW1wYWN0IG9uIHRoZSBzbG9wZSB0aGFuIHRoZSBvdXRsaWVycyBzaW5jZSB0aGUgc2xvcGUgY2hhbmdlZCBtb3JlLCBidXQgc3RpbGwgbm90IGEgZHJhbWF0aWMgY2hhbmdlLg0KDQpgYGB7ciBRM2N9DQpnZ190cmlwICsgDQogIGdlb21fc21vb3RoKA0KICAgIG1hcHBpbmcgPSBhZXMoY29sb3IgPSAnQWxsIFRyaXBzJyksDQogICAgbWV0aG9kID0gJ2xtJywNCiAgICBzZSA9IEYsDQogICAgZm9ybXVsYSA9IHkgfiB4LA0KICAgIGFscGhhID0gMC41DQogICkgKyANCiAgZ2VvbV9zbW9vdGgoDQogICAgZGF0YSA9IHN0cmF2YSB8PiBmaWx0ZXIocmVzaWR1YWwgPCA3NSksDQogICAgbWFwcGluZyA9IGFlcyhjb2xvciA9ICdObyBPdXRsaWVycycpLA0KICAgIG1ldGhvZCA9ICdsbScsDQogICAgc2UgPSBGLA0KICAgIGZvcm11bGEgPSB5IH4geCwNCiAgICBhbHBoYSA9IDAuNQ0KICApICsgDQogIGdlb21fc21vb3RoKA0KICAgIGRhdGEgPSBzdHJhdmEgfD4gZmlsdGVyKGRpc3RhbmNlIDwgMzApLA0KICAgIG1hcHBpbmcgPSBhZXMoY29sb3IgPSAnTm8gSGlnaCBMZXZlcmFnZScpLA0KICAgIG1ldGhvZCA9ICdsbScsDQogICAgZm9ybXVsYSA9IHkgfiB4LA0KICAgIHNlID0gRiwNCiAgICBhbHBoYSA9IDAuNSwNCiAgICBmdWxscmFuZ2UgPSBUDQogICkNCg0KYGBgDQoNCg0KDQojIyBRdWVzdGlvbiA0OiBJbnRlcmNlcHQgPSAwDQoNClNpbmNlIGEgdHJpcCB0aGF0IHRyYXZlbGVkIDAgbWlsZXMgc2hvdWxkIGhhdmUgYSBtb3Zpbmcgc3BlZWQgb2YgMCBtaW51dGVzLCB3ZSdsbCBmb3JjZSB0aGUgaW50ZXJjZXB0IHRvIGJlIDAuIA0KDQpGaXQgYSBsaW5lYXIgbW9kZWwgdXNpbmcgYGxtKClgIHdpdGggZm9yY2luZyAkYl8wID0gMCQuIFlvdSBjYW4gaGF2ZSBgbG0oKWAgbm90IGluY2x1ZGUgdGhlIGludGVyY2VwdCBieSBpbmNsdWRpbmcgYC0xYCBpbiB0aGUgZm9ybXVsYS4gRm9yIGV4YW1wbGU6IGB5IH4gLTEgKyB4YA0KDQpgYGB7ciBRNH0NCnRyaXBfbG1fbm9faW50IDwtIGxtKHRpbWUgfiAtMSArIGRpc3RhbmNlLCBkYXRhID0gc3RyYXZhKQ0KDQpicm9vbTo6dGlkeSh0cmlwX2xtX25vX2ludCkNCmBgYA0KDQoNCg0KDQoNCg0KDQoNCg0K