library(RxODE)
library(tidyverse)
library(knitr)
Model definition
# Define model ##########
ode <- "
TBP = VP*RB/CLB;
CONC = A1/VC*0.16;
CPLXP =  ((KD*VP+A2+TBP)-((KD*VP+A2+TBP)^2-4*A2*TBP)^0.5)/2;
FAP = A2 - CPLXP;
RO = 100*CPLXP / (VP*RB/CLB);
d/dt(A1) = - A1*CLA/VC - Q*A1/VC + Q*FAP/VP;
d/dt(A2) =  -CPLXP*CLB/VP + Q*A1/VC -  Q*FAP/VP;
"
# Compile model ##########
mod1 <- RxODE(model = ode, modName = "mod1")
 
Sensitivity parameter setting
time.interval <- 1
test.dose <- c(50,100,250,400,500)
test.exp <- seq(0.75,0.85, 0.01)
 
PK parameters & simulation
data <- data.frame(time = seq(0, 21*24, time.interval),
                     CONC = 0)
for (i in test.dose) {
  for (j in test.exp) {
    DOSEmm3 = i   # Dose 
    All_ex = j    # Exponent
  BW = 70                      # Average bodyweight of monkey in 12 mg/kg group
  CLA_est = 1.16                     # Separet variable for senstivity analysis
  V_est = 128                  # Separet variable for senstivity analysis
  VP_est = 126                   # Separet variable for senstivity analysis
    
  
  CLA = CLA_est*(BW/3)**All_ex    # CL_ex  (mL/h)
  VC  = V_est*(BW/3)                    # Central volume of distribution (mL)
  Q    = 8.75 * (BW/3)**All_ex    # Intercompartmental clearance (mL/h)
  VP  = VP_est*(BW/3)           
  RB = 335 * (BW/3)**All_ex        # RB_ex  ; Target synthesis rate (pmol/h)
  CLB = 2.39*(BW/3)**All_ex        # Target & Complex clearance (mL/h)
  KD  = 4.5                            # Equilibrium binding constant (nM)
  TBP = VP*RB/CLB                  # Total binding target in peripheral
  # Simulate a single dose ##########
  MWlig = 150000  # Molecular weight of mAb
  DOSE = DOSEmm3 * 1.73
  DOSEnM = DOSE*1e-3/MWlig*1e12  #Dose as nanomole
  duration = 2   # infusion duration
  infrate = DOSEnM / duration  # inusion rate"
  sampling.day = 21  # sampling time as day
  sampling.time = 24*sampling.day   # sampling time as hour
  
params <- c(CLA = CLA, VC = VC, Q = Q, VP = VP, CLB = CLB, RB = RB, KD = KD)
inits <- c(0, 0)   
# Initialize event table ##########
ev <- eventTable()
ev$add.dosing(dose = DOSEnM, nbr.doses = 1, dosing.to =1, rate = infrate)#, dosing.interval = 168)
ev$add.sampling(seq(0, sampling.time, time.interval))
#integration
data2 <- as.data.frame(mod1$run(params, ev, inits))
data2 <- data2[,c(1,5)]
colnames(data2) <- c("time", paste("dose",i,"exp",j, sep="-"))
data  <- merge(data, data2, by = "time")
  }}
 
Data management for NCA
data <- data[, -2]
data.long <-
  data %>%
  gather(2:ncol(data), key = "group", value = "CONC")
data3 <- separate(data.long,
                 group, into = c("a", "dose", "b","exp"), sep = "-")
data3 <- data3[,c(1,3,5,6)]
#colnames(test) <- c("time","dose", "exp","conc")
unique(data3[,c("dose", "exp")])
nrow(unique(data3[,c("dose", "exp")]))
[1] 55
data3$NID <- paste(data3$dose, data3$exp, sep = "-")
data3$ID <- factor(data3$NID, label=1:length(unique(data3$NID)))
# Simulated Conc-Time profile by dose
ggplot(data3, aes(time, CONC, group = ID, colour = factor(exp))) + 
  geom_line() +
  scale_y_continuous(trans = "log10") +
  facet_wrap(~dose, ncol = 2, scales="free_y")

 
NCA analysis using NonCompart package and data management
nca_data <- NonCompart::tabNCA(data3, "ID", "time", "CONC")
nca_data <- as.data.frame(nca_data)
nca_AUC <- nca_data %>% select(ID, AUCIFO) %>% arrange(ID)
nca_AUC %>% knitr::kable()
| 1 | 
2880.2896 | 
| 2 | 
2791.0786 | 
| 3 | 
2704.6087 | 
| 4 | 
2620.8024 | 
| 5 | 
2539.5781 | 
| 6 | 
2460.8623 | 
| 7 | 
2384.5782 | 
| 8 | 
2310.6513 | 
| 9 | 
2239.0111 | 
| 10 | 
2169.5871 | 
| 11 | 
2102.3122 | 
| 12 | 
13672.2490 | 
| 13 | 
13249.2327 | 
| 14 | 
12842.4774 | 
| 15 | 
12446.4734 | 
| 16 | 
12062.4019 | 
| 17 | 
11689.8248 | 
| 18 | 
11328.4733 | 
| 19 | 
10978.0702 | 
| 20 | 
10638.2945 | 
| 21 | 
10308.8649 | 
| 22 | 
9989.5197 | 
| 23 | 
28778.0455 | 
| 24 | 
27784.3324 | 
| 25 | 
26844.6364 | 
| 26 | 
25954.3595 | 
| 27 | 
25111.8013 | 
| 28 | 
24312.3893 | 
| 29 | 
23548.3455 | 
| 30 | 
22814.1826 | 
| 31 | 
22105.8150 | 
| 32 | 
21420.6236 | 
| 33 | 
20757.2407 | 
| 34 | 
1059.1385 | 
| 35 | 
1026.3169 | 
| 36 | 
994.5086 | 
| 37 | 
963.6836 | 
| 38 | 
933.8118 | 
| 39 | 
904.8641 | 
| 40 | 
876.8120 | 
| 41 | 
849.6285 | 
| 42 | 
823.2866 | 
| 43 | 
797.7608 | 
| 44 | 
773.0256 | 
| 45 | 
40699.8388 | 
| 46 | 
39226.1353 | 
| 47 | 
37816.8056 | 
| 48 | 
36471.3114 | 
| 49 | 
35193.2682 | 
| 50 | 
33973.7577 | 
| 51 | 
32819.6687 | 
| 52 | 
31728.0985 | 
| 53 | 
30694.9231 | 
| 54 | 
29714.2862 | 
| 55 | 
28779.7284 | 
 
data_sub <- 
  data3 %>% 
  select(ID, dose, exp) %>% 
  arrange(ID)
data_sub <- data_sub[!duplicated(data_sub$ID),]
data_sub <- merge(data_sub, nca_AUC, by="ID")
#AUC obs
AUC_obs <- read.csv(file="Cetuxmab_AUC.csv", header = T, stringsAsFactors = F, nrow = 5)
colnames(AUC_obs) <- c("dose","AUCOBS")
## merge AUCobs and AUCsim
data_all <- merge(data_sub, AUC_obs, by="dose") %>%
  select(ID, dose, exp,  AUCSIM=AUCIFO, AUCOBS) %>%
  arrange(ID)
knitr::kable(data_all)
| 1 | 
100 | 
0.75 | 
2880.2896 | 
2380 | 
| 2 | 
100 | 
0.76 | 
2791.0786 | 
2380 | 
| 3 | 
100 | 
0.77 | 
2704.6087 | 
2380 | 
| 4 | 
100 | 
0.78 | 
2620.8024 | 
2380 | 
| 5 | 
100 | 
0.79 | 
2539.5781 | 
2380 | 
| 6 | 
100 | 
0.8 | 
2460.8623 | 
2380 | 
| 7 | 
100 | 
0.81 | 
2384.5782 | 
2380 | 
| 8 | 
100 | 
0.82 | 
2310.6513 | 
2380 | 
| 9 | 
100 | 
0.83 | 
2239.0111 | 
2380 | 
| 10 | 
100 | 
0.84 | 
2169.5871 | 
2380 | 
| 11 | 
100 | 
0.85 | 
2102.3122 | 
2380 | 
| 12 | 
250 | 
0.75 | 
13672.2490 | 
14600 | 
| 13 | 
250 | 
0.76 | 
13249.2327 | 
14600 | 
| 14 | 
250 | 
0.77 | 
12842.4774 | 
14600 | 
| 15 | 
250 | 
0.78 | 
12446.4734 | 
14600 | 
| 16 | 
250 | 
0.79 | 
12062.4019 | 
14600 | 
| 17 | 
250 | 
0.8 | 
11689.8248 | 
14600 | 
| 18 | 
250 | 
0.81 | 
11328.4733 | 
14600 | 
| 19 | 
250 | 
0.82 | 
10978.0702 | 
14600 | 
| 20 | 
250 | 
0.83 | 
10638.2945 | 
14600 | 
| 21 | 
250 | 
0.84 | 
10308.8649 | 
14600 | 
| 22 | 
250 | 
0.85 | 
9989.5197 | 
14600 | 
| 23 | 
400 | 
0.75 | 
28778.0455 | 
19000 | 
| 24 | 
400 | 
0.76 | 
27784.3324 | 
19000 | 
| 25 | 
400 | 
0.77 | 
26844.6364 | 
19000 | 
| 26 | 
400 | 
0.78 | 
25954.3595 | 
19000 | 
| 27 | 
400 | 
0.79 | 
25111.8013 | 
19000 | 
| 28 | 
400 | 
0.8 | 
24312.3893 | 
19000 | 
| 29 | 
400 | 
0.81 | 
23548.3455 | 
19000 | 
| 30 | 
400 | 
0.82 | 
22814.1826 | 
19000 | 
| 31 | 
400 | 
0.83 | 
22105.8150 | 
19000 | 
| 32 | 
400 | 
0.84 | 
21420.6236 | 
19000 | 
| 33 | 
400 | 
0.85 | 
20757.2407 | 
19000 | 
| 34 | 
50 | 
0.75 | 
1059.1385 | 
795 | 
| 35 | 
50 | 
0.76 | 
1026.3169 | 
795 | 
| 36 | 
50 | 
0.77 | 
994.5086 | 
795 | 
| 37 | 
50 | 
0.78 | 
963.6836 | 
795 | 
| 38 | 
50 | 
0.79 | 
933.8118 | 
795 | 
| 39 | 
50 | 
0.8 | 
904.8641 | 
795 | 
| 40 | 
50 | 
0.81 | 
876.8120 | 
795 | 
| 41 | 
50 | 
0.82 | 
849.6285 | 
795 | 
| 42 | 
50 | 
0.83 | 
823.2866 | 
795 | 
| 43 | 
50 | 
0.84 | 
797.7608 | 
795 | 
| 44 | 
50 | 
0.85 | 
773.0256 | 
795 | 
| 45 | 
500 | 
0.75 | 
40699.8388 | 
30870 | 
| 46 | 
500 | 
0.76 | 
39226.1353 | 
30870 | 
| 47 | 
500 | 
0.77 | 
37816.8056 | 
30870 | 
| 48 | 
500 | 
0.78 | 
36471.3114 | 
30870 | 
| 49 | 
500 | 
0.79 | 
35193.2682 | 
30870 | 
| 50 | 
500 | 
0.8 | 
33973.7577 | 
30870 | 
| 51 | 
500 | 
0.81 | 
32819.6687 | 
30870 | 
| 52 | 
500 | 
0.82 | 
31728.0985 | 
30870 | 
| 53 | 
500 | 
0.83 | 
30694.9231 | 
30870 | 
| 54 | 
500 | 
0.84 | 
29714.2862 | 
30870 | 
| 55 | 
500 | 
0.85 | 
28779.7284 | 
30870 | 
 
Plot the result.
data_all_ex_long <-
  data_all_ex %>%
  gather(2:5, key = "evaluation", value = "performance")
ggplot(data_all_ex_long, aes(exp, performance)) + 
  geom_point() +
  facet_wrap(~evaluation, scales="free_y")

 
LS0tDQp0aXRsZTogIkdDMTExOCBzZW5zaXRpdml0eSBhbmFseXNpcyBvZiBleHBvbmVudCINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazogZGVmYXVsdA0KICBodG1sX2RvY3VtZW50OiBkZWZhdWx0DQogIHBkZl9kb2N1bWVudDogZGVmYXVsdA0KLS0tDQoNCmBgYHtyLCBtZXNzYWdlPUYsIHdhcm5pbmc9Rn0NCmxpYnJhcnkoUnhPREUpDQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoa25pdHIpDQpgYGANCg0KIyMgTW9kZWwgZGVmaW5pdGlvbg0KYGBge3J9DQojIERlZmluZSBtb2RlbCAjIyMjIyMjIyMjDQpvZGUgPC0gIg0KVEJQID0gVlAqUkIvQ0xCOw0KQ09OQyA9IEExL1ZDKjAuMTY7DQpDUExYUCA9ICAoKEtEKlZQK0EyK1RCUCktKChLRCpWUCtBMitUQlApXjItNCpBMipUQlApXjAuNSkvMjsNCkZBUCA9IEEyIC0gQ1BMWFA7DQpSTyA9IDEwMCpDUExYUCAvIChWUCpSQi9DTEIpOw0KZC9kdChBMSkgPSAtIEExKkNMQS9WQyAtIFEqQTEvVkMgKyBRKkZBUC9WUDsNCmQvZHQoQTIpID0gIC1DUExYUCpDTEIvVlAgKyBRKkExL1ZDIC0gIFEqRkFQL1ZQOw0KIg0KIyBDb21waWxlIG1vZGVsICMjIyMjIyMjIyMNCm1vZDEgPC0gUnhPREUobW9kZWwgPSBvZGUsIG1vZE5hbWUgPSAibW9kMSIpDQpgYGANCg0KIyMgU2Vuc2l0aXZpdHkgcGFyYW1ldGVyIHNldHRpbmcNCmBgYHtyfQ0KdGltZS5pbnRlcnZhbCA8LSAxDQp0ZXN0LmRvc2UgPC0gYyg1MCwxMDAsMjUwLDQwMCw1MDApDQp0ZXN0LmV4cCA8LSBzZXEoMC43NSwwLjg1LCAwLjAxKQ0KYGBgDQoNCiMjIFBLIHBhcmFtZXRlcnMgJiBzaW11bGF0aW9uDQpgYGB7cn0NCmRhdGEgPC0gZGF0YS5mcmFtZSh0aW1lID0gc2VxKDAsIDIxKjI0LCB0aW1lLmludGVydmFsKSwNCiAgICAgICAgICAgICAgICAgICAgIENPTkMgPSAwKQ0KDQpmb3IgKGkgaW4gdGVzdC5kb3NlKSB7DQogIGZvciAoaiBpbiB0ZXN0LmV4cCkgew0KICAgIERPU0VtbTMgPSBpICAgIyBEb3NlIA0KICAgIEFsbF9leCA9IGogICAgIyBFeHBvbmVudA0KDQogIEJXID0gNzAgICAgICAgICAgICAgICAgICAgICAgIyBBdmVyYWdlIGJvZHl3ZWlnaHQgb2YgbW9ua2V5IGluIDEyIG1nL2tnIGdyb3VwDQogIENMQV9lc3QgPSAxLjE2ICAgICAgICAJCQkgIyBTZXBhcmV0IHZhcmlhYmxlIGZvciBzZW5zdGl2aXR5IGFuYWx5c2lzDQogIFZfZXN0ID0gMTI4ICAgICAgICAgICAgIAkgICAjIFNlcGFyZXQgdmFyaWFibGUgZm9yIHNlbnN0aXZpdHkgYW5hbHlzaXMNCiAgVlBfZXN0ID0gMTI2ICAgICAgICAgICAgIAkJICMgU2VwYXJldCB2YXJpYWJsZSBmb3Igc2Vuc3Rpdml0eSBhbmFseXNpcw0KICAgIA0KICANCiAgQ0xBID0gQ0xBX2VzdCooQlcvMykqKkFsbF9leCAgICAjIENMX2V4ICAobUwvaCkNCiAgVkMgID0gVl9lc3QqKEJXLzMpICAgIAkJCSAgICAjIENlbnRyYWwgdm9sdW1lIG9mIGRpc3RyaWJ1dGlvbiAobUwpDQogIFEgICAgPSA4Ljc1ICogKEJXLzMpKipBbGxfZXggICAgIyBJbnRlcmNvbXBhcnRtZW50YWwgY2xlYXJhbmNlIChtTC9oKQ0KICBWUCAgPSBWUF9lc3QqKEJXLzMpICAgICAgICAgICANCiAgUkIgPSAzMzUgKiAoQlcvMykqKkFsbF9leCAgICAgICAgIyBSQl9leAk7IFRhcmdldCBzeW50aGVzaXMgcmF0ZSAocG1vbC9oKQ0KICBDTEIgPSAyLjM5KihCVy8zKSoqQWxsX2V4ICAgICAgICAjIFRhcmdldCAmIENvbXBsZXggY2xlYXJhbmNlIChtTC9oKQ0KICBLRCAgPSA0LjUgICAgCQkJICAgICAgICAgICAgICAgIyBFcXVpbGlicml1bSBiaW5kaW5nIGNvbnN0YW50IChuTSkNCiAgVEJQID0gVlAqUkIvQ0xCICAgICAgICAgICAgICAgICAgIyBUb3RhbCBiaW5kaW5nIHRhcmdldCBpbiBwZXJpcGhlcmFsDQoNCiAgIyBTaW11bGF0ZSBhIHNpbmdsZSBkb3NlICMjIyMjIyMjIyMNCiAgTVdsaWcgPSAxNTAwMDAgICMgTW9sZWN1bGFyIHdlaWdodCBvZiBtQWINCiAgRE9TRSA9IERPU0VtbTMgKiAxLjczDQogIERPU0VuTSA9IERPU0UqMWUtMy9NV2xpZyoxZTEyICAjRG9zZSBhcyBuYW5vbW9sZQ0KICBkdXJhdGlvbiA9IDIgICAjIGluZnVzaW9uIGR1cmF0aW9uDQogIGluZnJhdGUgPSBET1NFbk0gLyBkdXJhdGlvbiAgIyBpbnVzaW9uIHJhdGUiDQogIHNhbXBsaW5nLmRheSA9IDIxICAjIHNhbXBsaW5nIHRpbWUgYXMgZGF5DQogIHNhbXBsaW5nLnRpbWUgPSAyNCpzYW1wbGluZy5kYXkgICAjIHNhbXBsaW5nIHRpbWUgYXMgaG91cg0KICANCnBhcmFtcyA8LSBjKENMQSA9IENMQSwgVkMgPSBWQywgUSA9IFEsIFZQID0gVlAsIENMQiA9IENMQiwgUkIgPSBSQiwgS0QgPSBLRCkNCmluaXRzIDwtIGMoMCwgMCkgICANCg0KIyBJbml0aWFsaXplIGV2ZW50IHRhYmxlICMjIyMjIyMjIyMNCmV2IDwtIGV2ZW50VGFibGUoKQ0KZXYkYWRkLmRvc2luZyhkb3NlID0gRE9TRW5NLCBuYnIuZG9zZXMgPSAxLCBkb3NpbmcudG8gPTEsIHJhdGUgPSBpbmZyYXRlKSMsIGRvc2luZy5pbnRlcnZhbCA9IDE2OCkNCmV2JGFkZC5zYW1wbGluZyhzZXEoMCwgc2FtcGxpbmcudGltZSwgdGltZS5pbnRlcnZhbCkpDQoNCiNpbnRlZ3JhdGlvbg0KZGF0YTIgPC0gYXMuZGF0YS5mcmFtZShtb2QxJHJ1bihwYXJhbXMsIGV2LCBpbml0cykpDQpkYXRhMiA8LSBkYXRhMlssYygxLDUpXQ0KDQpjb2xuYW1lcyhkYXRhMikgPC0gYygidGltZSIsIHBhc3RlKCJkb3NlIixpLCJleHAiLGosIHNlcD0iLSIpKQ0KZGF0YSAgPC0gbWVyZ2UoZGF0YSwgZGF0YTIsIGJ5ID0gInRpbWUiKQ0KICB9fQ0KYGBgDQoNCiMjIERhdGEgbWFuYWdlbWVudCBmb3IgTkNBDQpgYGB7cn0NCmRhdGEgPC0gZGF0YVssIC0yXQ0KZGF0YS5sb25nIDwtDQogIGRhdGEgJT4lDQogIGdhdGhlcigyOm5jb2woZGF0YSksIGtleSA9ICJncm91cCIsIHZhbHVlID0gIkNPTkMiKQ0KDQpkYXRhMyA8LSBzZXBhcmF0ZShkYXRhLmxvbmcsDQogICAgICAgICAgICAgICAgIGdyb3VwLCBpbnRvID0gYygiYSIsICJkb3NlIiwgImIiLCJleHAiKSwgc2VwID0gIi0iKQ0KZGF0YTMgPC0gZGF0YTNbLGMoMSwzLDUsNildDQojY29sbmFtZXModGVzdCkgPC0gYygidGltZSIsImRvc2UiLCAiZXhwIiwiY29uYyIpDQoNCnVuaXF1ZShkYXRhM1ssYygiZG9zZSIsICJleHAiKV0pDQpucm93KHVuaXF1ZShkYXRhM1ssYygiZG9zZSIsICJleHAiKV0pKQ0KDQpkYXRhMyROSUQgPC0gcGFzdGUoZGF0YTMkZG9zZSwgZGF0YTMkZXhwLCBzZXAgPSAiLSIpDQpkYXRhMyRJRCA8LSBmYWN0b3IoZGF0YTMkTklELCBsYWJlbD0xOmxlbmd0aCh1bmlxdWUoZGF0YTMkTklEKSkpDQoNCiMgU2ltdWxhdGVkIENvbmMtVGltZSBwcm9maWxlIGJ5IGRvc2UNCmdncGxvdChkYXRhMywgYWVzKHRpbWUsIENPTkMsIGdyb3VwID0gSUQsIGNvbG91ciA9IGZhY3RvcihleHApKSkgKyANCiAgZ2VvbV9saW5lKCkgKw0KICBzY2FsZV95X2NvbnRpbnVvdXModHJhbnMgPSAibG9nMTAiKSArDQogIGZhY2V0X3dyYXAofmRvc2UsIG5jb2wgPSAyLCBzY2FsZXM9ImZyZWVfeSIpDQpgYGANCg0KIyMgTkNBIGFuYWx5c2lzIHVzaW5nIE5vbkNvbXBhcnQgcGFja2FnZSBhbmQgZGF0YSBtYW5hZ2VtZW50DQpgYGB7cn0NCm5jYV9kYXRhIDwtIE5vbkNvbXBhcnQ6OnRhYk5DQShkYXRhMywgIklEIiwgInRpbWUiLCAiQ09OQyIpDQpuY2FfZGF0YSA8LSBhcy5kYXRhLmZyYW1lKG5jYV9kYXRhKQ0KbmNhX0FVQyA8LSBuY2FfZGF0YSAlPiUgc2VsZWN0KElELCBBVUNJRk8pICU+JSBhcnJhbmdlKElEKQ0KbmNhX0FVQyAlPiUga25pdHI6OmthYmxlKCkNCg0KZGF0YV9zdWIgPC0gDQogIGRhdGEzICU+JSANCiAgc2VsZWN0KElELCBkb3NlLCBleHApICU+JSANCiAgYXJyYW5nZShJRCkNCmRhdGFfc3ViIDwtIGRhdGFfc3ViWyFkdXBsaWNhdGVkKGRhdGFfc3ViJElEKSxdDQpkYXRhX3N1YiA8LSBtZXJnZShkYXRhX3N1YiwgbmNhX0FVQywgYnk9IklEIikNCg0KI0FVQyBvYnMNCkFVQ19vYnMgPC0gcmVhZC5jc3YoZmlsZT0iQ2V0dXhtYWJfQVVDLmNzdiIsIGhlYWRlciA9IFQsIHN0cmluZ3NBc0ZhY3RvcnMgPSBGLCBucm93ID0gNSkNCmNvbG5hbWVzKEFVQ19vYnMpIDwtIGMoImRvc2UiLCJBVUNPQlMiKQ0KIyMgbWVyZ2UgQVVDb2JzIGFuZCBBVUNzaW0NCmRhdGFfYWxsIDwtIG1lcmdlKGRhdGFfc3ViLCBBVUNfb2JzLCBieT0iZG9zZSIpICU+JQ0KICBzZWxlY3QoSUQsIGRvc2UsIGV4cCwgIEFVQ1NJTT1BVUNJRk8sIEFVQ09CUykgJT4lDQogIGFycmFuZ2UoSUQpDQprbml0cjo6a2FibGUoZGF0YV9hbGwpDQpgYGANCg0KIyMgQ2FsY3VsYXRlIHByZWRpY3RpdmUgcGVyZm9ybWFuY2UgKFBQRSwgUk1TRSwgQUZFLCBBQUZFKQ0KYGBge3J9DQojIEluZGl2aWR1YWwgcHJlZGljdGl2ZSBwZXJmb3JtYW5jZQ0KZGF0YV9hbGwgPC0NCiAgZGF0YV9hbGwgJT4lDQogIG11dGF0ZShQUEVpID0gKEFVQ1NJTS1BVUNPQlMpL0FVQ09CUywNCiAgICAgICAgIFJNU0VpID0gKEFVQ1NJTS1BVUNPQlMpXjIsDQogICAgICAgICBBRkVpID0gbG9nMTAoQVVDU0lNL0FVQ09CUyksDQogICAgICAgICBBQUZFaSA9IGFicyhBRkVpKSkNCmtuaXRyOjprYWJsZShkYXRhX2FsbCkNCg0KIyBNZWFuIGJ5IGV4cG9uZW50DQpkYXRhX2FsbF9leCA8LQ0KICBkYXRhX2FsbCAlPiUNCiAgZ3JvdXBfYnkoZXhwKSAlPiUNCiAgc3VtbWFyaXNlKFBQRT1zdW0oUFBFaSkvNSoxMDAsDQogICAgICAgICAgICBSTVNFID0gc3FydChzdW0oUk1TRWkpLzUpLA0KICAgICAgICAgICAgQUZFID0gMTBeKG1lYW4oQUZFaSkpLA0KICAgICAgICAgICAgQUFGRSA9IDEwXihtZWFuKEFBRkVpKSkpDQprbml0cjo6a2FibGUoZGF0YV9hbGxfZXgpDQoNCmBgYA0KDQojIyBQbG90IHRoZSByZXN1bHQuDQpgYGB7cn0NCmRhdGFfYWxsX2V4X2xvbmcgPC0NCiAgZGF0YV9hbGxfZXggJT4lDQogIGdhdGhlcigyOjUsIGtleSA9ICJldmFsdWF0aW9uIiwgdmFsdWUgPSAicGVyZm9ybWFuY2UiKQ0KDQpnZ3Bsb3QoZGF0YV9hbGxfZXhfbG9uZywgYWVzKGV4cCwgcGVyZm9ybWFuY2UpKSArIA0KICBnZW9tX3BvaW50KCkgKw0KICBmYWNldF93cmFwKH5ldmFsdWF0aW9uLCBzY2FsZXM9ImZyZWVfeSIpDQpgYGANCg==