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 %>% slice(3:5))$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] 0.1470493
LOQ
[1] 0.4901644
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
#Based on Calibration Curve
(corn$Area[2]/Sucrose_reg$coefficients[1]) #Concentration in solution
Concentration
4.741
(corn$Area[2]/Sucrose_reg$coefficients[1]) * 0.1 #Mass in solution
Concentration
0.4741
(((corn$Area[2]/Sucrose_reg$coefficients[1]) * 0.1)/11.36) * 100 #g/100 g in corn flakes
Concentration
4.173415
corn_ci_low =((corn$Area[2]/(Sucrose_reg$coefficients[1]+(1.96*1.002)) * 0.1)/11.36) * 100 #g/100 g in corn flakes lower CI
corn_ci_high = ((corn$Area[2]/(Sucrose_reg$coefficients[1]-(1.96*1.002)) * 0.1)/11.36) * 100 #g/100 g in corn flakes lower CI
cat("The concentration of sucrose in cereal is between", corn_ci_low, "g/100 g and", corn_ci_high, "g/100 g")
The concentration of sucrose in cereal is between 3.780717 g/100 g and 4.657147 g/100 g
LS0tDQp0aXRsZTogIlByb2plY3QgMSBEYXRhIEFuYWx5c2lzOiBTdWdhcnMgaW4gQ2VyZWFsIg0KYXV0aG9yOiAiSmFrZSBFaHJiYWtlciBhbmQgRXZhbiBNYXRoZXIiDQpvdXRwdXQ6IGh0bWxfbm90ZWJvb2sNCi0tLQ0KDQpgYGB7cn0NCmxpYnJhcnkoZHBseXIpDQpsaWJyYXJ5KGdncGxvdDIpDQpsaWJyYXJ5KHJzdGF0aXgpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmBgYA0KDQpgYGB7cn0NCmRhdGEgPSByZWFkX2RlbGltKCJQcm9qZWN0XzFfaW50ZWdyYXRpb25fZGF0YS5jc3YiLCBkZWxpbSA9ICcsJykNCmNlcmVhbF9kYXRhID0gcmVhZF9kZWxpbSgiY2VyZWFsX3NhbXBsZXMuY3N2IiwgZGVsaW0gPSAnLCcpDQpgYGANCg0KYGBge3J9DQojU2VwYXJhdGUgcGVha3MgYnkgdmFyaWFibGVzDQpmcnVjdG9zZSA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoQW5hbHl0ZSA9PSAiRnJ1Y3Rvc2UiKQ0KDQpnbHVjb3NlID0gZGF0YSAlPiUgDQogIGZpbHRlcihBbmFseXRlID09ICJHbHVjb3NlIikNCg0Kc3Vjcm9zZSA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoQW5hbHl0ZSA9PSAiU3Vjcm9zZSIpDQoNCnh5bG9zZSA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoQW5hbHl0ZSA9PSAiWHlsb3NlIikNCg0KZHNtbyA9IGRhdGEgJT4lIA0KICBmaWx0ZXIoUGVhayA9PSAxKQ0KYGBgDQoNCmBgYHtyfQ0KZnJ1Y3Rvc2VfcGVha3MgPSBmcnVjdG9zZSAlPiUgDQogIGZpbHRlcihQZWFrID09IDIpICU+JSANCiAgc2VsZWN0KC1BbmFseXRlKSAlPiUgDQogIHNlbGVjdCgtUGVhaykNCg0KZ2x1Y29zZV9wZWFrcyA9IGdsdWNvc2UgJT4lIA0KICBmaWx0ZXIoUGVhayA9PSAyKSAlPiUgDQogIHNlbGVjdCgtQW5hbHl0ZSkgJT4lIA0KICBzZWxlY3QoLVBlYWspDQoNCnN1Y3Jvc2VfcGVha3MgPSBzdWNyb3NlICU+JSANCiAgZmlsdGVyKFBlYWsgPT0gMikgJT4lIA0KICBzZWxlY3QoLUFuYWx5dGUpICU+JSANCiAgc2VsZWN0KC1QZWFrKQ0KDQpzdWNyb3NlX3BlYWtzID0gc3Vjcm9zZV9wZWFrc1stYygzKSxdDQoNCnh5bG9zZV9wZWFrcyA9IHh5bG9zZSAlPiUgDQogIGZpbHRlcihgUmV0ZW50aW9uIFRpbWVgPjEwKQ0KYGBgDQoNCmBgYHtyfQ0KZ2dwbG90KGRhdGE9ZnJ1Y3Rvc2VfcGVha3MsIG1hcHBpbmc9YWVzKHg9Q29uY2VudHJhdGlvbiwgeT1BcmVhKSkgKyANCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDIpICsgDQogIGdndGl0bGUoIkZydWN0b3NlIikrDQogIHRoZW1lKHBsb3QudGl0bGU9ZWxlbWVudF90ZXh0KGZhY2U9J2JvbGQnLCBzaXplID0gMjAsIGhqdXN0ID0gMC41KSwgcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfcmVjdCgnYXp1cmUyJykpDQoNCmdncGxvdChkYXRhPWdsdWNvc2VfcGVha3MsIG1hcHBpbmc9YWVzKHg9Q29uY2VudHJhdGlvbiwgeT1BcmVhKSkgKyANCiAgZ2VvbV9wb2ludChjb2xvciA9ICJibHVlIiwgc2l6ZSA9IDIpICsgDQogIGdndGl0bGUoIkdsdWNvc2UiKSsNCiAgdGhlbWUocGxvdC50aXRsZT1lbGVtZW50X3RleHQoZmFjZT0nYm9sZCcsIHNpemUgPSAyMCwgaGp1c3QgPSAwLjUpLCBwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9yZWN0KCdhenVyZTInKSkNCg0KZ2dwbG90KGRhdGE9c3Vjcm9zZV9wZWFrcywgbWFwcGluZz1hZXMoeD1Db25jZW50cmF0aW9uLCB5PUFyZWEpKSArIA0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiLCBzaXplID0gMikgKyANCiAgZ2d0aXRsZSgiU3Vjcm9zZSIpKw0KICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChmYWNlPSdib2xkJywgc2l6ZSA9IDIwLCBoanVzdCA9IDAuNSksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoJ2F6dXJlMicpKSArDQogIGdlb21fc21vb3RoKG1ldGhvZCA9ICdsbScpICsNCiAgeGxhYigiQ29uY2VudHJhdGlvbiAoZy9MKSIpDQoNCmBgYA0KDQoNCmBgYHtyfQ0KR3J1YmJzX21heCA9IGZ1bmN0aW9uKHBlYWtzID0gdGliYmxlKCkpIHsNCiAgZ3J1YmJzX21heCA9IG1heChwZWFrcyRBcmVhKQ0KICBncnViYnNfYXZnID0gbWVhbihwZWFrcyRBcmVhKQ0KICBncnViYnNfcmVnID0gbG0oQXJlYSB+IENvbmNlbnRyYXRpb24gKzAsIGRhdGE9cGVha3MpDQogIA0KICBHX2NhbGMgPSBhYnMoZ3J1YmJzX21heC1ncnViYnNfYXZnKS9ncnViYnNfcmVnJGNvZWZmaWNlbnRzWzFdDQogIA0KICByZXR1cm4oR19jYWxjKQ0KfQ0KYGBgDQoNCmBgYHtyfQ0KU3Vjcm9zZV9yZWcgPSBsbShBcmVhIH4gQ29uY2VudHJhdGlvbiswLCBkYXRhPSBzdWNyb3NlX3BlYWtzKQ0Kc3VtbWFyeShTdWNyb3NlX3JlZykNCmBgYA0KYGBge3J9DQpzdWNyb3NlX3BlYWtzID0gc3Vjcm9zZV9wZWFrcyAlPiUgDQogIG11dGF0ZShzaWdfcHJlZCA9IENvbmNlbnRyYXRpb24gKiBTdWNyb3NlX3JlZyRjb2VmZmljaWVudHNbMV0pICU+JSANCiAgbXV0YXRlKHJlc2lkID0gQXJlYSAtIHNpZ19wcmVkKQ0KDQpnZ3Bsb3QoZGF0YT1zdWNyb3NlX3BlYWtzLCBtYXBwaW5nPWFlcyh4PUNvbmNlbnRyYXRpb24sIHk9cmVzaWQpKSArIA0KICBnZW9tX3BvaW50KGNvbG9yID0gImJsdWUiLCBzaXplID0gMikgKyANCiAgZ2d0aXRsZSgiU3Vjcm9zZSBSZXNpZHVhbCIpKw0KICB0aGVtZShwbG90LnRpdGxlPWVsZW1lbnRfdGV4dChmYWNlPSdib2xkJywgc2l6ZSA9IDIwLCBoanVzdCA9IDAuNSksIHBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X3JlY3QoJ2F6dXJlMicpKSArDQogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDApDQpgYGANCg0KYGBge3J9DQpzdWNfcmVzX3NkID0gc2QoKHN1Y3Jvc2VfcGVha3MgJT4lIHNsaWNlKDM6NSkpJHJlc2lkKQ0KTE9EID0gMyAqc3VjX3Jlc19zZCAvIGFzLm51bWVyaWMoU3Vjcm9zZV9yZWckY29lZmZpY2llbnRzWzFdKQ0KTE9RID0gMTAgKnN1Y19yZXNfc2QgLyBhcy5udW1lcmljKFN1Y3Jvc2VfcmVnJGNvZWZmaWNpZW50c1sxXSkNCkxPRA0KTE9RDQpgYGANCg0KYGBge3J9DQpGcnVjdG9zZV9yZWcgPSBsbShBcmVhIH4gQ29uY2VudHJhdGlvbiwgZGF0YT0gZnJ1Y3Rvc2VfcGVha3MpDQpzdW1tYXJ5KEZydWN0b3NlX3JlZykNCmBgYA0KDQpgYGB7cn0NCkdsdWNvc2VfcmVnID0gbG0oQXJlYSB+IENvbmNlbnRyYXRpb24sIGRhdGE9IGdsdWNvc2VfcGVha3MpDQpzdW1tYXJ5KEdsdWNvc2VfcmVnKQ0KYGBgDQoNCmBgYHtyfQ0KUl90aW1lcyA9IGRhdGEuZnJhbWUoQW5hbHl0ZSA9IGNoYXJhY3RlcigpLCANCiAgICAgICAgICAgICAgICAgICAgIGF2Z19yX3RpbWUgPSBudW1lcmljKCksDQogICAgICAgICAgICAgICAgICAgICBzZF9yX3RpbWUgPSBudW1lcmljKCksDQogICAgICAgICAgICAgICAgICAgICByX2NpX2xvdyA9IG51bWVyaWMoKSwgDQogICAgICAgICAgICAgICAgICAgICByX2NpX2hpZ2ggPSBudW1lcmljKCkpDQoNClJfdGltZXMgPSByYmluZChSX3RpbWVzLCBkYXRhLmZyYW1lKEFuYWx5dGUgPSAiU3Vjcm9zZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdmdfcl90aW1lID0gbWVhbihzdWNyb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Rfcl90aW1lID0gc2Qoc3Vjcm9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJfY2lfbG93ID0gbWVhbihzdWNyb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLTIqc2Qoc3Vjcm9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJfY2lfaGlnaCA9IG1lYW4oc3Vjcm9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSsyKnNkKHN1Y3Jvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkpKQ0KDQpSX3RpbWVzID0gcmJpbmQoUl90aW1lcywgZGF0YS5mcmFtZShBbmFseXRlID0gIkZydWN0b3NlIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF2Z19yX3RpbWUgPSBtZWFuKGZydWN0b3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Rfcl90aW1lID0gc2QoZnJ1Y3Rvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2xvdyA9IG1lYW4oZnJ1Y3Rvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCktMipzZChmcnVjdG9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJfY2lfaGlnaCA9IG1lYW4oZnJ1Y3Rvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkrMipzZChmcnVjdG9zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSkpDQoNClJfdGltZXMgPSByYmluZChSX3RpbWVzLCBkYXRhLmZyYW1lKEFuYWx5dGUgPSAiR2x1Y29zZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdmdfcl90aW1lID0gbWVhbihnbHVjb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc2Rfcl90aW1lID0gc2QoZ2x1Y29zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJfY2lfbG93ID0gbWVhbihnbHVjb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLTIqc2QoZ2x1Y29zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJfY2lfaGlnaCA9IG1lYW4oZ2x1Y29zZV9wZWFrcyRgUmV0ZW50aW9uIFRpbWVgKSsyKnNkKGdsdWNvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkpKQ0KDQpSX3RpbWVzID0gcmJpbmQoUl90aW1lcywgZGF0YS5mcmFtZShBbmFseXRlID0gIlh5bG9zZSIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBhdmdfcl90aW1lID0gbWVhbih4eWxvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzZF9yX3RpbWUgPSBzZCh4eWxvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2xvdyA9IG1lYW4oeHlsb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLTIqc2QoeHlsb3NlX3BlYWtzJGBSZXRlbnRpb24gVGltZWApLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcl9jaV9oaWdoID0gbWVhbih4eWxvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkrMipzZCh4eWxvc2VfcGVha3MkYFJldGVudGlvbiBUaW1lYCkpKQ0KDQpSX3RpbWVzID0gcmJpbmQoUl90aW1lcywgZGF0YS5mcmFtZShBbmFseXRlID0gIkRTTU8iLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXZnX3JfdGltZSA9IG1lYW4oZHNtbyRgUmV0ZW50aW9uIFRpbWVgKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHNkX3JfdGltZSA9IHNkKGRzbW8kYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2xvdyA9IG1lYW4oZHNtbyRgUmV0ZW50aW9uIFRpbWVgKS0yKnNkKGRzbW8kYFJldGVudGlvbiBUaW1lYCksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByX2NpX2hpZ2ggPSBtZWFuKGRzbW8kYFJldGVudGlvbiBUaW1lYCkrMipzZChkc21vJGBSZXRlbnRpb24gVGltZWApKSkNCmBgYA0KDQoNCmBgYHtyfQ0KZGZydWN0b3NlX3BlYWtzID0gZnJ1Y3Rvc2UgJT4lIA0KICAgIGZpbHRlcihQZWFrID09IDEpICU+JSANCiAgc2VsZWN0KC1BbmFseXRlKQ0KDQpkZ2x1Y29zZV9wZWFrcyA9IGdsdWNvc2UgJT4lIA0KICBmaWx0ZXIoUGVhayA9PSAxKSAlPiUgDQogIHNlbGVjdCgtQW5hbHl0ZSkNCg0KZHN1Y3Jvc2VfcGVha3MgPSBzdWNyb3NlICU+JSANCiAgZmlsdGVyKFBlYWsgPT0gMSkgJT4lIA0KICBzZWxlY3QoLUFuYWx5dGUpDQoNCmRzdWNyb3NlX3BlYWtzID0gZHN1Y3Jvc2VfcGVha3NbLWMoMyksXQ0KDQp4c3Vjcm9zZV9wZWFrcyA9IHN1Y3Jvc2UgJT4lIA0KICBmaWx0ZXIoYFJldGVudGlvbiBUaW1lYCA8IDEyLjgwICYgYFJldGVudGlvbiBUaW1lYCA+IDEwLjk3KSAlPiUgDQogIG11dGF0ZShQZWFrID0gYXMuY2hhcmFjdGVyKCJJUyIpKQ0KDQpzdWNyb3NlX3hfaXMgPSBkYXRhLmZyYW1lKFBlYWsgPSBudW1lcmljKCksDQogICAgICAgICAgICAgICAgICAgICAgICAgIFJldGVudGlvbl90aW1lID0gbnVtZXJpYygpLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgQXJlYSA9IG51bWVyaWMoKSkgDQoNCg0KYGBgDQoNCmBgYHtyfQ0Kc3Vjcm9zZV9pcyA9IGRhdGEuZnJhbWUoIkNvbmNlbnRyYXRpb24iID0gc3Vjcm9zZV9wZWFrcyRDb25jZW50cmF0aW9uLCAiRnJ1Y3Rvc2UgUGVhayIgPSBzdWNyb3NlX3BlYWtzJEFyZWEsICJJUyBQZWFrIiA9IHhzdWNyb3NlX3BlYWtzJEFyZWEpDQoNCnN1Y3Jvc2VfaXMgPSBzdWNyb3NlX2lzICU+JSANCiAgbXV0YXRlKFJlc3BvbnNlX0ZhY3RvciA9IChzdWNyb3NlX2lzJEZydWN0b3NlLlBlYWsvc3Vjcm9zZV9pcyRDb25jZW50cmF0aW9uKS8oc3Vjcm9zZV9pcyRJUy5QZWFrLzAuNSkpDQpgYGANCg0KYGBge3J9DQpzdWNyb3NlX3BlYWtzID0gc3Vjcm9zZV9wZWFrcyAlPiUgDQogIG11dGF0ZShyZXNwb25zZV9mYWN0b3IgPSAoc3Vjcm9zZV9wZWFrcyRBcmVhL3N1Y3Jvc2VfcGVha3MkQ29uY2VudHJhdGlvbikvZHN1Y3Jvc2VfcGVha3MkQXJlYSkNCmBgYA0KDQpgYGB7cn0NCnByaW50KCJTdWNyb3NlIFBlYWtzIEYgTWVhbiBhbmQgU0QiKQ0KbWVhbihzdWNyb3NlX3BlYWtzJHJlc3BvbnNlX2ZhY3RvcikNCnNkKHN1Y3Jvc2VfcGVha3MkcmVzcG9uc2VfZmFjdG9yKQ0KDQpwcmludCgiRFNNTyBQZWFrcyBNZWFuIGFuZCBTRCIpDQptZWFuKGRzbW8kQXJlYSkNCnNkKGRzbW8kQXJlYSkNCmBgYA0KDQpgYGB7cn0NCnByaW50KCJEU01PIEYsIHNkLCBhbmQgQ0kiKQ0KZG1zb19SRkYgPSBtZWFuKHN1Y3Jvc2VfcGVha3MkcmVzcG9uc2VfZmFjdG9yKQ0KZG1zb19SRkZfc2QgPSBzZChzdWNyb3NlX3BlYWtzJHJlc3BvbnNlX2ZhY3RvcikNCmRtc29fUkZGDQpkbXNvX1JGRl9zZA0KZG1zb19SRkZfbG93ID0gbWVhbihzdWNyb3NlX3BlYWtzJHJlc3BvbnNlX2ZhY3RvcikgLSAyICogc2Qoc3Vjcm9zZV9wZWFrcyRyZXNwb25zZV9mYWN0b3IpDQpkbXNvX1JGRl9sb3cNCmRtc29fUkZGX2hpZ2ggPSBtZWFuKHN1Y3Jvc2VfcGVha3MkcmVzcG9uc2VfZmFjdG9yKSArIDIgKiBzZChzdWNyb3NlX3BlYWtzJHJlc3BvbnNlX2ZhY3RvcikNCmRtc29fUkZGX2hpZ2gNCg0KcHJpbnQoIlh5bG9zZSBGLCBzZCwgYW5kIENJIikNCm1lYW4oc3Vjcm9zZV9pcyRSZXNwb25zZV9GYWN0b3IpDQpzZChzdWNyb3NlX2lzJFJlc3BvbnNlX0ZhY3RvcikNCm1lYW4oc3Vjcm9zZV9pcyRSZXNwb25zZV9GYWN0b3IpIC0gMiAqIHNkKHN1Y3Jvc2VfaXMkUmVzcG9uc2VfRmFjdG9yKQ0KbWVhbihzdWNyb3NlX2lzJFJlc3BvbnNlX0ZhY3RvcikgKyAyICogc2Qoc3Vjcm9zZV9pcyRSZXNwb25zZV9GYWN0b3IpDQpgYGANCg0KYGBge3J9DQpjZXJlYWxfZGF0YSA9IGNlcmVhbF9kYXRhICU+JSANCiAgbXV0YXRlKHBlYWtfdHlwZSA9IGNhc2Vfd2hlbigNCiAgICBSZXRfdGltZSA+PSA1LjY3NjkxOSAmIFJldF90aW1lIDw9IDcuMzkxMjA5IH4gIkRTTU8iLA0KICAgIFJldF90aW1lID49IDguMzYzMjcwICYgUmV0X3RpbWUgPD0gOC41OTU4NzkgfiAiU3Vjcm9zZSIsDQogICAgUmV0X3RpbWUgPj0gMTAuMTE5NzkxICYgUmV0X3RpbWUgPCAxMC4yOTYyMzEgfiAiRnJ1Y3Rvc2UiLA0KICAgIFJldF90aW1lID49IDEwLjI5NjIzMSAmIFJldF90aW1lIDw9IDEwLjY1MzQzMiB+ICJGcnVjdG9zZSBvciBHbHVjb3NlIiwNCiAgICBSZXRfdGltZSA+PSAxMC42NTM0MzIgJiBSZXRfdGltZSA8PSAxMC43MjQyODggfiAiRnJ1Y3Rvc2UiLA0KICAgIFJldF90aW1lID49IDEwLjk3ODMyMCAmIFJldF90aW1lIDw9IDEyLjc5NjQxNyB+ICJYeWxvc2UiLA0KICAgIFRSVUUgfiAiT3V0c2lkZSBvZiA5NSUgQ0kiDQogICkpDQpgYGANCg0KYGBge3J9DQpjaG9jbyA9IGNlcmVhbF9kYXRhICU+JSANCiAgZmlsdGVyKFNhbXBsZSA9PSJDaG9jbyIpICU+JSANCiAgc2VsZWN0KC1TYW1wbGUpDQoNCnNwZWNpYWxfayA9IGNlcmVhbF9kYXRhICU+JSANCiAgZmlsdGVyKFNhbXBsZSA9PSJTcGVjaWFsX2siKSAlPiUgDQogIHNlbGVjdCgtU2FtcGxlKQ0KDQpjb3JuID0gY2VyZWFsX2RhdGEgJT4lIA0KICBmaWx0ZXIoU2FtcGxlID09ImNvcm4iKSAlPiUgDQogIHNlbGVjdCgtU2FtcGxlKQ0KYGBgDQoNCmBgYHtyfQ0KI3N1Y3Jvc2UgaW4gc29sdXRpb24gKGxvd2VzdCBjb25jLiB0byB0ZXN0IExPUSkNCihjb3JuJEFyZWFbMl0gKiA1LjAgLyAoY29ybiRBcmVhWzFdICogZG1zb19SRkZfaGlnaCkpDQogDQojZyBzdWdhciBwZXIgMTAwIGcgaWYgc3VnYXIgaXMgZXZlbmx5IGRpc3RyaWJ1dGVkDQooKGNvcm4kQXJlYVsyXSAqIDUuMCAvIChjb3JuJEFyZWFbMV0gKiBkbXNvX1JGRl9sb3cpKSAqIDAuMSAvIDExLjM2KSAqIDEwMA0KKChjb3JuJEFyZWFbMl0gKiA1LjAgLyAoY29ybiRBcmVhWzFdICogZG1zb19SRkZfaGlnaCkpICogMC4xIC8gMTEuMzYpICogMTAwDQoNCiNnIHN1Z2FyIHBlciAxMDAgZyBpZiBzdWdhciBpcyBhbGwgaW4gdGhlcmUNCigoY29ybiRBcmVhWzJdICogNS4wIC8gKGNvcm4kQXJlYVsxXSAqIGRtc29fUkZGX2xvdykpICogMC4xIC8gMTEuMzYpICogMTAwICogNTYuMTA0MiAvIDY3LjI1NjgNCigoY29ybiRBcmVhWzJdICogNS4wIC8gKGNvcm4kQXJlYVsxXSAqIGRtc29fUkZGX2hpZ2gpKSAqIDAuMSAvIDExLjM2KSAqIDEwMCAqIDU2LjEwNDIgLyA2Ny4yNTY4DQoNCiNCYXNlZCBvbiBDYWxpYnJhdGlvbiBDdXJ2ZQ0KKGNvcm4kQXJlYVsyXS9TdWNyb3NlX3JlZyRjb2VmZmljaWVudHNbMV0pICNDb25jZW50cmF0aW9uIGluIHNvbHV0aW9uDQooY29ybiRBcmVhWzJdL1N1Y3Jvc2VfcmVnJGNvZWZmaWNpZW50c1sxXSkgKiAwLjEgI01hc3MgaW4gc29sdXRpb24NCigoKGNvcm4kQXJlYVsyXS9TdWNyb3NlX3JlZyRjb2VmZmljaWVudHNbMV0pICogMC4xKS8xMS4zNikgKiAxMDAgI2cvMTAwIGcgaW4gY29ybiBmbGFrZXMNCmNvcm5fY2lfbG93ID0oKGNvcm4kQXJlYVsyXS8oU3Vjcm9zZV9yZWckY29lZmZpY2llbnRzWzFdKygxLjk2KjEuMDAyKSkgKiAwLjEpLzExLjM2KSAqIDEwMCAjZy8xMDAgZyBpbiBjb3JuIGZsYWtlcyBsb3dlciBDSQ0KY29ybl9jaV9oaWdoID0gKChjb3JuJEFyZWFbMl0vKFN1Y3Jvc2VfcmVnJGNvZWZmaWNpZW50c1sxXS0oMS45NioxLjAwMikpICogMC4xKS8xMS4zNikgKiAxMDAgI2cvMTAwIGcgaW4gY29ybiBmbGFrZXMgbG93ZXIgQ0kNCmNhdCgiVGhlIGNvbmNlbnRyYXRpb24gb2Ygc3Vjcm9zZSBpbiBjZXJlYWwgaXMgYmV0d2VlbiIsIGNvcm5fY2lfbG93LCAiZy8xMDAgZyBhbmQiLCBjb3JuX2NpX2hpZ2gsICJnLzEwMCBnIikNCmBgYA0KDQo=