library(dplyr)
library(ggplot2)
library(rstatix)
library(tidyverse)
data = read_delim("Project_1_integration_data.csv", delim = ',')
Rows: 148 Columns: 7── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Analyte
dbl (6): Concentration, Peak, Retention Time, Area, Height, Width
ℹ 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.
cereal_data = read_delim("cereal_samples.csv", delim = ',')
Rows: 18 Columns: 6── Column specification ──────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Delimiter: ","
chr (1): Sample
dbl (5): Peak, Ret_time, Area, Height, Width
ℹ 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.
#Separate peaks by variables
fructose = data %>%
filter(Analyte == "Fructose")
glucose = data %>%
filter(Analyte == "Glucose")
sucrose = data %>%
filter(Analyte == "Sucrose")
xylose = data %>%
filter(Analyte == "Xylose")
dsmo = data %>%
filter(Peak == 1)
fructose_peaks = fructose %>%
filter(Peak == 2) %>%
select(-Analyte) %>%
select(-Peak)
glucose_peaks = glucose %>%
filter(Peak == 2) %>%
select(-Analyte) %>%
select(-Peak)
sucrose_peaks = sucrose %>%
filter(Peak == 2) %>%
select(-Analyte) %>%
select(-Peak)
sucrose_peaks = sucrose_peaks[-c(3),]
xylose_peaks = xylose %>%
filter(`Retention Time`>10)
ggplot(data=fructose_peaks, mapping=aes(x=Concentration, y=Area)) +
geom_point(color = "blue", size = 2) +
ggtitle("Fructose")+
theme(plot.title=element_text(face='bold', size = 20, hjust = 0.5), panel.background = element_rect('azure2'))

ggplot(data=glucose_peaks, mapping=aes(x=Concentration, y=Area)) +
geom_point(color = "blue", size = 2) +
ggtitle("Glucose")+
theme(plot.title=element_text(face='bold', size = 20, hjust = 0.5), panel.background = element_rect('azure2'))

ggplot(data=sucrose_peaks, mapping=aes(x=Concentration, y=Area)) +
geom_point(color = "blue", size = 2) +
ggtitle("Sucrose")+
theme(plot.title=element_text(face='bold', size = 20, hjust = 0.5), panel.background = element_rect('azure2')) +
geom_smooth(method = 'lm') +
xlab("Concentration (g/L)")

Grubbs_max = function(peaks = tibble()) {
grubbs_max = max(peaks$Area)
grubbs_avg = mean(peaks$Area)
grubbs_reg = lm(Area ~ Concentration +0, data=peaks)
G_calc = abs(grubbs_max-grubbs_avg)/grubbs_reg$coefficents[1]
return(G_calc)
}
Sucrose_reg = lm(Area ~ Concentration+0, data= sucrose_peaks)
summary(Sucrose_reg)
Call:
lm(formula = Area ~ Concentration + 0, data = sucrose_peaks)
Residuals:
Min 1Q Median 3Q Max
-15.561 -7.797 1.930 4.166 32.884
Coefficients:
Estimate Std. Error t value Pr(>|t|)
Concentration 18.908 1.002 18.87 7.89e-11 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 11.79 on 13 degrees of freedom
Multiple R-squared: 0.9648, Adjusted R-squared: 0.9621
F-statistic: 356.1 on 1 and 13 DF, p-value: 7.893e-11
sucrose_peaks = sucrose_peaks %>%
mutate(sig_pred = Concentration * Sucrose_reg$coefficients[1]) %>%
mutate(resid = Area - sig_pred)
ggplot(data=sucrose_peaks, mapping=aes(x=Concentration, y=resid)) +
geom_point(color = "blue", size = 2) +
ggtitle("Sucrose Residual")+
theme(plot.title=element_text(face='bold', size = 20, hjust = 0.5), panel.background = element_rect('azure2')) +
geom_hline(yintercept = 0)

suc_res_sd = sd(sucrose_peaks$resid)
LOD = 3 *suc_res_sd / as.numeric(Sucrose_reg$coefficients[1])
LOQ = 10 *suc_res_sd / as.numeric(Sucrose_reg$coefficients[1])
LOD
[1] 1.869589
LOQ
[1] 6.231964
Fructose_reg = lm(Area ~ Concentration, data= fructose_peaks)
summary(Fructose_reg)
Call:
lm(formula = Area ~ Concentration, data = fructose_peaks)
Residuals:
Min 1Q Median 3Q Max
-32.471 -15.573 -14.070 -3.192 174.167
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 46.747 23.400 1.998 0.0671 .
Concentration 5.142 15.388 0.334 0.7436
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 51.61 on 13 degrees of freedom
Multiple R-squared: 0.008517, Adjusted R-squared: -0.06775
F-statistic: 0.1117 on 1 and 13 DF, p-value: 0.7436
Glucose_reg = lm(Area ~ Concentration, data= glucose_peaks)
summary(Glucose_reg)
Call:
lm(formula = Area ~ Concentration, data = glucose_peaks)
Residuals:
Min 1Q Median 3Q Max
-12.4570 -5.6250 -0.5563 2.9662 22.9004
Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) 25.027 4.228 5.919 5.07e-05 ***
Concentration -5.413 2.780 -1.947 0.0735 .
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1
Residual standard error: 9.326 on 13 degrees of freedom
Multiple R-squared: 0.2257, Adjusted R-squared: 0.1662
F-statistic: 3.79 on 1 and 13 DF, p-value: 0.0735
R_times = data.frame(Analyte = character(),
avg_r_time = numeric(),
sd_r_time = numeric(),
r_ci_low = numeric(),
r_ci_high = numeric())
R_times = rbind(R_times, data.frame(Analyte = "Sucrose",
avg_r_time = mean(sucrose_peaks$`Retention Time`),
sd_r_time = sd(sucrose_peaks$`Retention Time`),
r_ci_low = mean(sucrose_peaks$`Retention Time`)-2*sd(sucrose_peaks$`Retention Time`),
r_ci_high = mean(sucrose_peaks$`Retention Time`)+2*sd(sucrose_peaks$`Retention Time`)))
R_times = rbind(R_times, data.frame(Analyte = "Fructose",
avg_r_time = mean(fructose_peaks$`Retention Time`),
sd_r_time = sd(fructose_peaks$`Retention Time`),
r_ci_low = mean(fructose_peaks$`Retention Time`)-2*sd(fructose_peaks$`Retention Time`),
r_ci_high = mean(fructose_peaks$`Retention Time`)+2*sd(fructose_peaks$`Retention Time`)))
R_times = rbind(R_times, data.frame(Analyte = "Glucose",
avg_r_time = mean(glucose_peaks$`Retention Time`),
sd_r_time = sd(glucose_peaks$`Retention Time`),
r_ci_low = mean(glucose_peaks$`Retention Time`)-2*sd(glucose_peaks$`Retention Time`),
r_ci_high = mean(glucose_peaks$`Retention Time`)+2*sd(glucose_peaks$`Retention Time`)))
R_times = rbind(R_times, data.frame(Analyte = "Xylose",
avg_r_time = mean(xylose_peaks$`Retention Time`),
sd_r_time = sd(xylose_peaks$`Retention Time`),
r_ci_low = mean(xylose_peaks$`Retention Time`)-2*sd(xylose_peaks$`Retention Time`),
r_ci_high = mean(xylose_peaks$`Retention Time`)+2*sd(xylose_peaks$`Retention Time`)))
R_times = rbind(R_times, data.frame(Analyte = "DSMO",
avg_r_time = mean(dsmo$`Retention Time`),
sd_r_time = sd(dsmo$`Retention Time`),
r_ci_low = mean(dsmo$`Retention Time`)-2*sd(dsmo$`Retention Time`),
r_ci_high = mean(dsmo$`Retention Time`)+2*sd(dsmo$`Retention Time`)))
dfructose_peaks = fructose %>%
filter(Peak == 1) %>%
select(-Analyte)
dglucose_peaks = glucose %>%
filter(Peak == 1) %>%
select(-Analyte)
dsucrose_peaks = sucrose %>%
filter(Peak == 1) %>%
select(-Analyte)
dsucrose_peaks = dsucrose_peaks[-c(3),]
xsucrose_peaks = sucrose %>%
filter(`Retention Time` < 12.80 & `Retention Time` > 10.97) %>%
mutate(Peak = as.character("IS"))
sucrose_x_is = data.frame(Peak = numeric(),
Retention_time = numeric(),
Area = numeric())
sucrose_is = data.frame("Concentration" = sucrose_peaks$Concentration, "Fructose Peak" = sucrose_peaks$Area, "IS Peak" = xsucrose_peaks$Area)
sucrose_is = sucrose_is %>%
mutate(Response_Factor = (sucrose_is$Fructose.Peak/sucrose_is$Concentration)/(sucrose_is$IS.Peak/0.5))
sucrose_peaks = sucrose_peaks %>%
mutate(response_factor = (sucrose_peaks$Area/sucrose_peaks$Concentration)/dsucrose_peaks$Area)
print("Sucrose Peaks F Mean and SD")
[1] "Sucrose Peaks F Mean and SD"
mean(sucrose_peaks$response_factor)
[1] 3.869912
sd(sucrose_peaks$response_factor)
[1] 1.220331
print("DSMO Peaks Mean and SD")
[1] "DSMO Peaks Mean and SD"
mean(dsmo$Area)
[1] 11.10546
sd(dsmo$Area)
[1] 4.655197
print("DSMO F, sd, and CI")
[1] "DSMO F, sd, and CI"
dmso_RFF = mean(sucrose_peaks$response_factor)
dmso_RFF_sd = sd(sucrose_peaks$response_factor)
dmso_RFF
[1] 3.869912
dmso_RFF_sd
[1] 1.220331
dmso_RFF_low = mean(sucrose_peaks$response_factor) - 2 * sd(sucrose_peaks$response_factor)
dmso_RFF_low
[1] 1.42925
dmso_RFF_high = mean(sucrose_peaks$response_factor) + 2 * sd(sucrose_peaks$response_factor)
dmso_RFF_high
[1] 6.310574
print("Xylose F, sd, and CI")
[1] "Xylose F, sd, and CI"
mean(sucrose_is$Response_Factor)
[1] 1.17316
sd(sucrose_is$Response_Factor)
[1] 2.408369
mean(sucrose_is$Response_Factor) - 2 * sd(sucrose_is$Response_Factor)
[1] -3.643578
mean(sucrose_is$Response_Factor) + 2 * sd(sucrose_is$Response_Factor)
[1] 5.989898
cereal_data = cereal_data %>%
mutate(peak_type = case_when(
Ret_time >= 5.676919 & Ret_time <= 7.391209 ~ "DSMO",
Ret_time >= 8.363270 & Ret_time <= 8.595879 ~ "Sucrose",
Ret_time >= 10.119791 & Ret_time < 10.296231 ~ "Fructose",
Ret_time >= 10.296231 & Ret_time <= 10.653432 ~ "Fructose or Glucose",
Ret_time >= 10.653432 & Ret_time <= 10.724288 ~ "Fructose",
Ret_time >= 10.978320 & Ret_time <= 12.796417 ~ "Xylose",
TRUE ~ "Outside of 95% CI"
))
choco = cereal_data %>%
filter(Sample =="Choco") %>%
select(-Sample)
special_k = cereal_data %>%
filter(Sample =="Special_k") %>%
select(-Sample)
corn = cereal_data %>%
filter(Sample =="corn") %>%
select(-Sample)
#sucrose in solution (lowest conc. to test LOQ)
(corn$Area[2] * 5.0 / (corn$Area[1] * dmso_RFF_high))
[1] 8.580379
#g sugar per 100 g if sugar is evenly distributed
((corn$Area[2] * 5.0 / (corn$Area[1] * dmso_RFF_low)) * 0.1 / 11.36) * 100
[1] 33.34945
((corn$Area[2] * 5.0 / (corn$Area[1] * dmso_RFF_high)) * 0.1 / 11.36) * 100
[1] 7.553151
#g sugar per 100 g if sugar is all in there
((corn$Area[2] * 5.0 / (corn$Area[1] * dmso_RFF_low)) * 0.1 / 11.36) * 100 * 56.1042 / 67.2568
[1] 27.81941
((corn$Area[2] * 5.0 / (corn$Area[1] * dmso_RFF_high)) * 0.1 / 11.36) * 100 * 56.1042 / 67.2568
[1] 6.300679
LS0tDQp0aXRsZTogIlByb2plY3QgMSBEYXRhIEFuYWx5c2lzOiBTdWdhcnMgaW4gQ2VyZWFsIg0KYXV0aG9yOiAiSmFjb2IgRWhyYmFrZXIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJzdGF0aXgpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KDQpgYGB7cn0NCmRhdGEgPSByZWFkX2RlbGltKCJQcm9qZWN0XzFfaW50ZWdyYXRpb25fZGF0YS5jc3YiLCBkZWxpbSA9ICcsJykNCmNlcmVhbF9kYXRhID0gcmVhZF9kZWxpbSgiY2VyZWFsX3NhbXBsZXMuY3N2IiwgZGVsaW0gPSAnLCcpDQpgYGANCg0KYGBge3J9DQojU2VwYXJhdGUgcGVha3MgYnkgdmFyaWFibGVzDQpmcnVjdG9zZSA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoQW5hbHl0ZSA9PSAiRnJ1Y3Rvc2UiKQ0KDQpnbHVjb3NlID0gZGF0YSAlPiUgDQogIGZpbHRlcihBbmFseXRlID09ICJHbHVjb3NlIikNCg0Kc3Vjcm9zZSA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoQW5hbHl0ZSA9PSAiU3Vjcm9zZSIpDQoNCnh5bG9zZSA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoQW5hbHl0ZSA9PSAiWHlsb3NlIikNCg0KZHNtbyA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoUGVhayA9PSAxKQ0KYGBgDQoNCmBgYHtyfQ0KZnJ1Y3Rvc2VfcGVha3MgPSBmcnVjdG9zZSAlPiUgDQogIGZpbHRlcihQZWFrID09IDIpICU+JSANCiAgc2VsZWN0KC1BbmFseXRlKSAlPiUgDQogIHNlbGVjdCgtUGVhaykNCg0KZ2x1Y29zZV9wZWFrcyA9IGdsdWNvc2UgJT4lIA0KICBmaWx0ZXIoUGVhayA9PSAyKSAlPiUgDQogIHNlbGVjdCgtQW5hbHl0ZSkgJT4lIA0KICBzZWxlY3QoLVBlYWspDQoNCnN1Y3Jvc2VfcGVha3MgPSBzdWNyb3NlICU+JSANCiAgZmlsdGVyKFBlYWsgPT0gMikgJT4lIA0KICBzZWxlY3QoLUFuYWx5dGUpICU+JSANCiAgc2VsZWN0KC1QZWFrKQ0KDQpzdWNyb3NlX3BlYWtzID0gc3Vjcm9zZV9wZWFrc1stYygzKSxdDQoNCnh5bG9zZV9wZWFrcyA9IHh5bG9zZSAlPiUgDQogIGZpbHRlcihgUmV0ZW50aW9uIFRpbWVgPjEwKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9ZnJ1Y3Rvc2VfcGVha3MsIG1hcHBpbmc9YWVzKHg9Q29uY2VudHJhdGlvbiwgeT1BcmVhKSkgKyANCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDIpICsgDQogIGdndGl0bGUoIkZydWN0b3NlIikrDQogIHRoZW1lKHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KGZhY2U9J2JvbGQnLCBzaXplID0gMjAsIGhqdXN0ID0gMC41KSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgnYXp1cmUyJykpDQoNCmdncGxvdChkYXRhPWdsdWNvc2VfcGVha3MsIG1hcHBpbmc9YWVzKHg9Q29uY2VudHJhdGlvbiwgeT1BcmVhKSkgKyANCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDIpICsgDQogIGdndGl0bGUoIkdsdWNvc2UiKSsNCiAgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X3RleHQoZmFjZT0nYm9sZCcsIHNpemUgPSAyMCwgaGp1c3QgPSAwLjUpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KCdhenVyZTInKSkNCg0KZ2dwbG90KGRhdGE9c3Vjcm9zZV9wZWFrcywgbWFwcGluZz1hZXMoeD1Db25jZW50cmF0aW9uLCB5PUFyZWEpKSArIA0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiLCBzaXplID0gMikgKyANCiAgZ2d0aXRsZSgiU3Vjcm9zZSIpKw0KICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChmYWNlPSdib2xkJywgc2l6ZSA9IDIwLCBoanVzdCA9IDAuNSksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoJ2F6dXJlMicpKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpICsNCiAgeGxhYigiQ29uY2VudHJhdGlvbiAoZy9MKSIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KR3J1YmJzX21heCA9IGZ1bmN0aW9uKHBlYWtzID0gdGliYmxlKCkpIHsNCiAgZ3J1YmJzX21heCA9IG1heChwZWFrcyRBcmVhKQ0KICBncnViYnNfYXZnID0gbWVhbihwZWFrcyRBcmVhKQ0KICBncnViYnNfcmVnID0gbG0oQXJlYSB+IENvbmNlbnRyYXRpb24gKzAsIGRhdGE9cGVha3MpDQogIA0KICBHX2NhbGMgPSBhYnMoZ3J1YmJzX21heC1ncnViYnNfYXZnKS9ncnViYnNfcmVnJGNvZWZmaWNlbnRzWzFdDQogIA0KICByZXR1cm4oR19jYWxjKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KU3Vjcm9zZV9yZWcgPSBsbShBcmVhIH4gQ29uY2VudHJhdGlvbiswLCBkYXRhPSBzdWNyb3NlX3BlYWtzKQ0Kc3VtbWFyeShTdWNyb3NlX3JlZykNCmBgYA0KYGBge3J9DQpzdWNyb3NlX3BlYWtzID0gc3Vjcm9zZV9wZWFrcyAlPiUgDQogIG11dGF0ZShzaWdfcHJlZCA9IENvbmNlbnRyYXRpb24gKiBTdWNyb3NlX3JlZyRjb2VmZmljaWVudHNbMV0pICU+JSANCiAgbXV0YXRlKHJlc2lkID0gQXJlYSAtIHNpZ19wcmVkKQ0KDQpnZ3Bsb3QoZGF0YT1zdWNyb3NlX3BlYWtzLCBtYXBwaW5nPWFlcyh4PUNvbmNlbnRyYXRpb24sIHk9cmVzaWQpKSArIA0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiLCBzaXplID0gMikgKyANCiAgZ2d0aXRsZSgiU3Vjcm9zZSBSZXNpZHVhbCIpKw0KICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChmYWNlPSdib2xkJywgc2l6ZSA9IDIwLCBoanVzdCA9IDAuNSksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoJ2F6dXJlMicpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApDQpgYGANCg0KYGBge3J9DQpzdWNfcmVzX3NkID0gc2Qoc3Vjcm9zZV9wZWFrcyRyZXNpZCkNCkxPRCA9IDMgKnN1Y19yZXNfc2QgLyBhcy5udW1lcmljKFN1Y3Jvc2VfcmVnJGNvZWZmaWNpZW50c1sxXSkNCkxPUSA9IDEwICpzdWNfcmVzX3NkIC8gYXMubnVtZXJpYyhTdWNyb3NlX3JlZyRjb2VmZmljaWVudHNbMV0pDQpMT0QNCkxPUQ0KYGBgDQoNCmBgYHtyfQ0KRnJ1Y3Rvc2VfcmVnID0gbG0oQXJlYSB+IENvbmNlbnRyYXRpb24sIGRhdGE9IGZydWN0b3NlX3BlYWtzKQ0Kc3VtbWFyeShGcnVjdG9zZV9yZWcpDQpgYGANCg0KYGBge3J9DQpHbHVjb3NlX3JlZyA9IGxtKEFyZWEgfiBDb25jZW50cmF0aW9uLCBkYXRhPSBnbHVjb3NlX3BlYWtzKQ0Kc3VtbWFyeShHbHVjb3NlX3JlZykNCmBgYA0KDQpgYGB7cn0NClJfdGltZXMgPSBkYXRhLmZyYW1lKEFuYWx5dGUgPSBjaGFyYWN0ZXIoKSwgDQogICAgICAgICAgICAgICAgICAgICBhdmdfcl90aW1lID0gbnVtZXJpYygpLA0KICAgICAgICAgICAgICAgICAgICAgc2Rfcl90aW1lID0gbnVtZXJpYygpLA0KICAgICAgICAgICAgICAgICAgICAgcl9jaV9sb3cgPSBudW1lcmljKCksIA0KICAgICAgICAgICAgICAgICAgICAgcl9jaV9oaWdoID0gbnVtZXJpYygpKQ0KDQpSX3RpbWVzID0gcmJpbmQoUl90aW1lcywgZGF0YS5mcmFtZShBbmFseXRlID0gIlN1Y3Jvc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZnX3JfdGltZSA9IG1lYW4oc3Vjcm9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX3JfdGltZSA9IHNkKHN1Y3Jvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2xvdyA9IG1lYW4oc3Vjcm9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKS0yKnNkKHN1Y3Jvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2hpZ2ggPSBtZWFuKHN1Y3Jvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkrMipzZChzdWNyb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApKSkNCg0KUl90aW1lcyA9IHJiaW5kKFJfdGltZXMsIGRhdGEuZnJhbWUoQW5hbHl0ZSA9ICJGcnVjdG9zZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdmdfcl90aW1lID0gbWVhbihmcnVjdG9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX3JfdGltZSA9IHNkKGZydWN0b3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcl9jaV9sb3cgPSBtZWFuKGZydWN0b3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLTIqc2QoZnJ1Y3Rvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2hpZ2ggPSBtZWFuKGZydWN0b3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApKzIqc2QoZnJ1Y3Rvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkpKQ0KDQpSX3RpbWVzID0gcmJpbmQoUl90aW1lcywgZGF0YS5mcmFtZShBbmFseXRlID0gIkdsdWNvc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZnX3JfdGltZSA9IG1lYW4oZ2x1Y29zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX3JfdGltZSA9IHNkKGdsdWNvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2xvdyA9IG1lYW4oZ2x1Y29zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKS0yKnNkKGdsdWNvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2hpZ2ggPSBtZWFuKGdsdWNvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkrMipzZChnbHVjb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApKSkNCg0KUl90aW1lcyA9IHJiaW5kKFJfdGltZXMsIGRhdGEuZnJhbWUoQW5hbHl0ZSA9ICJYeWxvc2UiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZnX3JfdGltZSA9IG1lYW4oeHlsb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Rfcl90aW1lID0gc2QoeHlsb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcl9jaV9sb3cgPSBtZWFuKHh5bG9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKS0yKnNkKHh5bG9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJfY2lfaGlnaCA9IG1lYW4oeHlsb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApKzIqc2QoeHlsb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApKSkNCg0KUl90aW1lcyA9IHJiaW5kKFJfdGltZXMsIGRhdGEuZnJhbWUoQW5hbHl0ZSA9ICJEU01PIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF2Z19yX3RpbWUgPSBtZWFuKGRzbW8kYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9yX3RpbWUgPSBzZChkc21vJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcl9jaV9sb3cgPSBtZWFuKGRzbW8kYFJldGVudGlvbiBUaW1lYCktMipzZChkc21vJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcl9jaV9oaWdoID0gbWVhbihkc21vJGBSZXRlbnRpb24gVGltZWApKzIqc2QoZHNtbyRgUmV0ZW50aW9uIFRpbWVgKSkpDQpgYGANCg0KDQpgYGB7cn0NCmRmcnVjdG9zZV9wZWFrcyA9IGZydWN0b3NlICU+JSANCiAgICBmaWx0ZXIoUGVhayA9PSAxKSAlPiUgDQogIHNlbGVjdCgtQW5hbHl0ZSkNCg0KZGdsdWNvc2VfcGVha3MgPSBnbHVjb3NlICU+JSANCiAgZmlsdGVyKFBlYWsgPT0gMSkgJT4lIA0KICBzZWxlY3QoLUFuYWx5dGUpDQoNCmRzdWNyb3NlX3BlYWtzID0gc3Vjcm9zZSAlPiUgDQogIGZpbHRlcihQZWFrID09IDEpICU+JSANCiAgc2VsZWN0KC1BbmFseXRlKQ0KDQpkc3Vjcm9zZV9wZWFrcyA9IGRzdWNyb3NlX3BlYWtzWy1jKDMpLF0NCg0KeHN1Y3Jvc2VfcGVha3MgPSBzdWNyb3NlICU+JSANCiAgZmlsdGVyKGBSZXRlbnRpb24gVGltZWAgPCAxMi44MCAmIGBSZXRlbnRpb24gVGltZWAgPiAxMC45NykgJT4lIA0KICBtdXRhdGUoUGVhayA9IGFzLmNoYXJhY3RlcigiSVMiKSkNCg0Kc3Vjcm9zZV94X2lzID0gZGF0YS5mcmFtZShQZWFrID0gbnVtZXJpYygpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICBSZXRlbnRpb25fdGltZSA9IG51bWVyaWMoKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgIEFyZWEgPSBudW1lcmljKCkpIA0KDQoNCmBgYA0KDQpgYGB7cn0NCnN1Y3Jvc2VfaXMgPSBkYXRhLmZyYW1lKCJDb25jZW50cmF0aW9uIiA9IHN1Y3Jvc2VfcGVha3MkQ29uY2VudHJhdGlvbiwgIkZydWN0b3NlIFBlYWsiID0gc3Vjcm9zZV9wZWFrcyRBcmVhLCAiSVMgUGVhayIgPSB4c3Vjcm9zZV9wZWFrcyRBcmVhKQ0KDQpzdWNyb3NlX2lzID0gc3Vjcm9zZV9pcyAlPiUgDQogIG11dGF0ZShSZXNwb25zZV9GYWN0b3IgPSAoc3Vjcm9zZV9pcyRGcnVjdG9zZS5QZWFrL3N1Y3Jvc2VfaXMkQ29uY2VudHJhdGlvbikvKHN1Y3Jvc2VfaXMkSVMuUGVhay8wLjUpKQ0KYGBgDQoNCmBgYHtyfQ0Kc3Vjcm9zZV9wZWFrcyA9IHN1Y3Jvc2VfcGVha3MgJT4lIA0KICBtdXRhdGUocmVzcG9uc2VfZmFjdG9yID0gKHN1Y3Jvc2VfcGVha3MkQXJlYS9zdWNyb3NlX3BlYWtzJENvbmNlbnRyYXRpb24pL2RzdWNyb3NlX3BlYWtzJEFyZWEpDQpgYGANCg0KYGBge3J9DQpwcmludCgiU3Vjcm9zZSBQZWFrcyBGIE1lYW4gYW5kIFNEIikNCm1lYW4oc3Vjcm9zZV9wZWFrcyRyZXNwb25zZV9mYWN0b3IpDQpzZChzdWNyb3NlX3BlYWtzJHJlc3BvbnNlX2ZhY3RvcikNCg0KcHJpbnQoIkRTTU8gUGVha3MgTWVhbiBhbmQgU0QiKQ0KbWVhbihkc21vJEFyZWEpDQpzZChkc21vJEFyZWEpDQpgYGANCg0KYGBge3J9DQpwcmludCgiRFNNTyBGLCBzZCwgYW5kIENJIikNCmRtc29fUkZGID0gbWVhbihzdWNyb3NlX3BlYWtzJHJlc3BvbnNlX2ZhY3RvcikNCmRtc29fUkZGX3NkID0gc2Qoc3Vjcm9zZV9wZWFrcyRyZXNwb25zZV9mYWN0b3IpDQpkbXNvX1JGRg0KZG1zb19SRkZfc2QNCmRtc29fUkZGX2xvdyA9IG1lYW4oc3Vjcm9zZV9wZWFrcyRyZXNwb25zZV9mYWN0b3IpIC0gMiAqIHNkKHN1Y3Jvc2VfcGVha3MkcmVzcG9uc2VfZmFjdG9yKQ0KZG1zb19SRkZfbG93DQpkbXNvX1JGRl9oaWdoID0gbWVhbihzdWNyb3NlX3BlYWtzJHJlc3BvbnNlX2ZhY3RvcikgKyAyICogc2Qoc3Vjcm9zZV9wZWFrcyRyZXNwb25zZV9mYWN0b3IpDQpkbXNvX1JGRl9oaWdoDQoNCnByaW50KCJYeWxvc2UgRiwgc2QsIGFuZCBDSSIpDQptZWFuKHN1Y3Jvc2VfaXMkUmVzcG9uc2VfRmFjdG9yKQ0Kc2Qoc3Vjcm9zZV9pcyRSZXNwb25zZV9GYWN0b3IpDQptZWFuKHN1Y3Jvc2VfaXMkUmVzcG9uc2VfRmFjdG9yKSAtIDIgKiBzZChzdWNyb3NlX2lzJFJlc3BvbnNlX0ZhY3RvcikNCm1lYW4oc3Vjcm9zZV9pcyRSZXNwb25zZV9GYWN0b3IpICsgMiAqIHNkKHN1Y3Jvc2VfaXMkUmVzcG9uc2VfRmFjdG9yKQ0KYGBgDQoNCmBgYHtyfQ0KY2VyZWFsX2RhdGEgPSBjZXJlYWxfZGF0YSAlPiUgDQogIG11dGF0ZShwZWFrX3R5cGUgPSBjYXNlX3doZW4oDQogICAgUmV0X3RpbWUgPj0gNS42NzY5MTkgJiBSZXRfdGltZSA8PSA3LjM5MTIwOSB+ICJEU01PIiwNCiAgICBSZXRfdGltZSA+PSA4LjM2MzI3MCAmIFJldF90aW1lIDw9IDguNTk1ODc5IH4gIlN1Y3Jvc2UiLA0KICAgIFJldF90aW1lID49IDEwLjExOTc5MSAmIFJldF90aW1lIDwgMTAuMjk2MjMxIH4gIkZydWN0b3NlIiwNCiAgICBSZXRfdGltZSA+PSAxMC4yOTYyMzEgJiBSZXRfdGltZSA8PSAxMC42NTM0MzIgfiAiRnJ1Y3Rvc2Ugb3IgR2x1Y29zZSIsDQogICAgUmV0X3RpbWUgPj0gMTAuNjUzNDMyICYgUmV0X3RpbWUgPD0gMTAuNzI0Mjg4IH4gIkZydWN0b3NlIiwNCiAgICBSZXRfdGltZSA+PSAxMC45NzgzMjAgJiBSZXRfdGltZSA8PSAxMi43OTY0MTcgfiAiWHlsb3NlIiwNCiAgICBUUlVFIH4gIk91dHNpZGUgb2YgOTUlIENJIg0KICApKQ0KYGBgDQoNCmBgYHtyfQ0KY2hvY28gPSBjZXJlYWxfZGF0YSAlPiUgDQogIGZpbHRlcihTYW1wbGUgPT0iQ2hvY28iKSAlPiUgDQogIHNlbGVjdCgtU2FtcGxlKQ0KDQpzcGVjaWFsX2sgPSBjZXJlYWxfZGF0YSAlPiUgDQogIGZpbHRlcihTYW1wbGUgPT0iU3BlY2lhbF9rIikgJT4lIA0KICBzZWxlY3QoLVNhbXBsZSkNCg0KY29ybiA9IGNlcmVhbF9kYXRhICU+JSANCiAgZmlsdGVyKFNhbXBsZSA9PSJjb3JuIikgJT4lIA0KICBzZWxlY3QoLVNhbXBsZSkNCmBgYA0KDQpgYGB7cn0NCiNzdWNyb3NlIGluIHNvbHV0aW9uIChsb3dlc3QgY29uYy4gdG8gdGVzdCBMT1EpDQooY29ybiRBcmVhWzJdICogNS4wIC8gKGNvcm4kQXJlYVsxXSAqIGRtc29fUkZGX2hpZ2gpKQ0KIA0KI2cgc3VnYXIgcGVyIDEwMCBnIGlmIHN1Z2FyIGlzIGV2ZW5seSBkaXN0cmlidXRlZA0KKChjb3JuJEFyZWFbMl0gKiA1LjAgLyAoY29ybiRBcmVhWzFdICogZG1zb19SRkZfbG93KSkgKiAwLjEgLyAxMS4zNikgKiAxMDANCigoY29ybiRBcmVhWzJdICogNS4wIC8gKGNvcm4kQXJlYVsxXSAqIGRtc29fUkZGX2hpZ2gpKSAqIDAuMSAvIDExLjM2KSAqIDEwMA0KDQojZyBzdWdhciBwZXIgMTAwIGcgaWYgc3VnYXIgaXMgYWxsIGluIHRoZXJlDQooKGNvcm4kQXJlYVsyXSAqIDUuMCAvIChjb3JuJEFyZWFbMV0gKiBkbXNvX1JGRl9sb3cpKSAqIDAuMSAvIDExLjM2KSAqIDEwMCAqIDU2LjEwNDIgLyA2Ny4yNTY4DQooKGNvcm4kQXJlYVsyXSAqIDUuMCAvIChjb3JuJEFyZWFbMV0gKiBkbXNvX1JGRl9oaWdoKSkgKiAwLjEgLyAxMS4zNikgKiAxMDAgKiA1Ni4xMDQyIC8gNjcuMjU2OA0KYGBgDQoNCg==