Flight Summary
Flight Statistics
Data normalized across several flight logs, spanning from NS45 to NS80, excepting NS54, NS55, and NS68 (NS54 is reserved for a flight still in development, and both NS55 and NS68 failed to record location data).
Due to a settings issue, before NS59, the cell tracker hardware stopped recording above 12.1 km (except for NS53). This limit is shown as a grey horizontal line in the figures depicting altitude.
require(ggplot2)
Loading required package: ggplot2
require(directlabels)
Loading required package: directlabels
require(scales)
Loading required package: scales
source("setup.R")
flight_times <- read_flight_times("flight_times.txt")
flight_data <- read_flight_data("flight_data/", calculate_difftime = TRUE)
Ascent Rate
Ascent Rate vs Time of Year
ggplot(flight_data,
aes(
x = as.Date(format(DateTime, format = "%m-%d"), format = "%m-%d"),
y = Ascent_Rate_m_s,
colour = Flight
)) +
geom_point() + geom_path() +
geom_hline(yintercept = 0, alpha = 0.2) +
scale_x_date(
date_breaks = "1 month",
labels = date_format("%b"),
limits = as.Date(c("01-01", "12-31"), format = "%m-%d"),
expand = c(0, 0)
) +
geom_dl(aes(label = gsub("NS", "", Flight)),
method = list(cex = 0.8, dl.trans(y = y + 0.2), "top.bumpup")) + guides(colour = FALSE) +
labs(title = "Ascent Rate vs Time of Year", x = "Time of Year", y = "Ascent Rate (m/s)")
Ascent Rate After Burst
ggplot(flight_data,
aes(x = burst_difftime / 60,
y = Ascent_Rate_m_s,
colour = Flight)) +
geom_path() +
xlim(-0.5, 3) +
geom_dl(aes(label = gsub("NS", "", Flight)), method = list("smart.grid", "small.box.labels")) + guides(colour = FALSE) +
labs(title = "Ascent Rate After Burst", x = "Time Since Burst (minutes)", y = "Ascent Rate (m/s)")
Ascent Rate vs Altitude
ggplot(flight_data,
aes(x = Altitude_m / 1000,
y = Ascent_Rate_m_s,
colour = Flight)) +
geom_path() +
geom_dl(aes(label = gsub("NS", "", Flight)),
method = list("far.from.others.borders", "small.box.labels")) + guides(colour = FALSE) +
labs(title = "Ascent Rate vs Altitude", x = "Altitude (km)", y = "Ascent Rate (m/s)")
Ground Speed
Ground Speed vs Time of Year
ggplot(flight_data,
aes(
x = as.Date(format(DateTime, format = "%m-%d"), format = "%m-%d"),
y = Ground_Speed_m_s,
colour = Flight
)) +
geom_point() + geom_path() +
scale_x_date(
date_breaks = "1 month",
labels = date_format("%b"),
limits = as.Date(c("01-01", "12-31"), format = "%m-%d"),
expand = c(0, 0)
) +
geom_dl(aes(label = gsub("NS", "", Flight)),
method = list(cex = 0.8, dl.trans(y = y + 0.2), "top.bumpup")) + guides(colour = FALSE) +
labs(title = "Ground Speed vs Time of Year", x = "Time of Year", y = "Ground Speed (m/s)")
Ground Speed vs Altitude
ggplot(
flight_data,
aes(
x = Altitude_m / 1000,
y = Ground_Speed_m_s,
colour = as.POSIXlt(DateTime)$yday
)
) +
geom_point() +
scale_colour_gradient2(
limits = c(0, 366),
low = "green",
mid = "red",
midpoint = 366 / 2,
high = "blue"
) +
labs(
title = "Ground Speed vs Altitude",
x = "Altitude (km)",
y = "Ground Speed (m/s)",
colour = "Day of Year"
) +
theme(
legend.position = c(1, 1),
legend.direction = "horizontal",
legend.justification = "right"
)
Green: late winter, Yellow: spring, Red: summer, Purple: autumn, Blue: early winter
Ascent and Descent Durations
For flights with definite burst and landing times, we can extract the times it took for the balloon to ascend and descend from max altitude.
flight_durations <- data.frame()
for (current_flight in flight_times$Flight)
{
if (!is.na(flight_times$Launch_Time[flight_times$Flight == current_flight]) &&
!is.na(flight_times$Burst_Time[flight_times$Flight == current_flight]) &&
!is.na(flight_times$Landing_Time[flight_times$Flight == current_flight]))
{
current_ascent_duration <-
as.numeric(with(
flight_times,
difftime(Launch_Time[Flight == current_flight], Burst_Time[Flight == current_flight], units = "mins")
)) * -1
current_descent_duration <-
as.numeric(with(
flight_times,
difftime(Landing_Time[Flight == current_flight], Burst_Time[Flight == current_flight], units = "mins")
))
flight_durations <- rbind(
flight_durations,
data.frame(
Flight = current_flight,
Date = flight_times$Date[flight_times$Flight == current_flight],
Ascent_Duration_min = current_ascent_duration,
Descent_Duration_min = current_descent_duration,
Ratio = current_ascent_duration / current_descent_duration
)
)
}
}
rm(current_flight,
current_ascent_duration,
current_descent_duration)
rmarkdown::paged_table(flight_durations)
On average, ascent takes 69 minutes, while descent takes 36 minutes, with a ratio of 2.
Ascent Duration vs Descent Duration
ggplot(
flight_durations,
aes(
x = Descent_Duration_min,
y = Ascent_Duration_min,
colour = as.POSIXlt(Date)$yday
)
) +
geom_point(size = 0.1) + geom_abline(slope = 1:3) +
scale_colour_gradient2(
limits = c(0, 366),
low = "green",
mid = "red",
midpoint = 366 / 2,
high = "blue"
) +
geom_dl(aes(label = gsub("NS", "", Flight)), method = list(cex = 0.8)) +
labs(
title = "Ascent Duration vs Descent Duration",
x = "Descent Duration (minutes)",
y = "Ascent Duration (minutes)",
colour = "Day of Year"
) +
coord_fixed(ratio = 1) +
scale_x_continuous(breaks = seq(
from = 0,
to = max(flight_data$Downrange_Distance_m),
by = 10
)) +
scale_y_continuous(breaks = seq(
from = 0,
to = max(flight_data$Altitude_m),
by = 10
)) +
theme(
legend.position = c(1, 0.96),
legend.direction = "horizontal",
legend.justification = "right"
)
Green: late winter, Yellow: spring, Red: summer, Purple: autumn, Blue: early winter
LS0tCnRpdGxlOiAiRmxpZ2h0IEFuYWx5c2lzIgpvdXRwdXQ6CiAgaHRtbF9ub3RlYm9vazogCiAgICBjb2RlX2ZvbGRpbmc6IGhpZGUKICAgIHRvYzogeWVzCiAgICBudW1iZXJfc2VjdGlvbnM6IHllcwogICAgdG9jX2Zsb2F0OiAKICAgICAgICBjb2xsYXBzZWQ6IGZhbHNlCi0tLQoKW0ZsaWdodCBTdW1tYXJ5XShmbGlnaHRfc3VtbWFyeS5uYi5odG1sKQoKW0ZsaWdodCBTdGF0aXN0aWNzXShmbGlnaHRfc3RhdGlzdGljcy5uYi5odG1sKQoKRGF0YSBub3JtYWxpemVkIGFjcm9zcyBzZXZlcmFsIGZsaWdodCBsb2dzLCBzcGFubmluZyBmcm9tIGByIG1pbihsZXZlbHMoZmxpZ2h0X2RhdGEkRmxpZ2h0KSlgIHRvIGByIG1heChsZXZlbHMoZmxpZ2h0X2RhdGEkRmxpZ2h0KSlgLCBleGNlcHRpbmcgTlM1NCwgTlM1NSwgYW5kIE5TNjggKE5TNTQgaXMgcmVzZXJ2ZWQgZm9yIGEgZmxpZ2h0IHN0aWxsIGluIGRldmVsb3BtZW50LCBhbmQgYm90aCBOUzU1IGFuZCBOUzY4IGZhaWxlZCB0byByZWNvcmQgbG9jYXRpb24gZGF0YSkuCgpEdWUgdG8gYSBzZXR0aW5ncyBpc3N1ZSwgYmVmb3JlIE5TNTksIHRoZSBjZWxsIHRyYWNrZXIgaGFyZHdhcmUgc3RvcHBlZCByZWNvcmRpbmcgYWJvdmUgMTIuMSBrbSAoZXhjZXB0IGZvciBOUzUzKS4gVGhpcyBsaW1pdCBpcyBzaG93biBhcyBhIGdyZXkgaG9yaXpvbnRhbCBsaW5lIGluIHRoZSBmaWd1cmVzIGRlcGljdGluZyBhbHRpdHVkZS4KCmBgYHtyIHNldHVwfQpyZXF1aXJlKGdncGxvdDIpCnJlcXVpcmUoZGlyZWN0bGFiZWxzKQpyZXF1aXJlKHNjYWxlcykKCnNvdXJjZSgic2V0dXAuUiIpCgpmbGlnaHRfdGltZXMgPC0gcmVhZF9mbGlnaHRfdGltZXMoImZsaWdodF90aW1lcy50eHQiKQpmbGlnaHRfZGF0YSA8LSByZWFkX2ZsaWdodF9kYXRhKCJmbGlnaHRfZGF0YS8iLCBjYWxjdWxhdGVfZGlmZnRpbWUgPSBUUlVFKQpgYGAKCiMgQXNjZW50IFJhdGUKCiMjIEFzY2VudCBSYXRlIHZzIFRpbWUgb2YgWWVhcgoKYGBge3IgYXNjZW50X3JhdGVfdnNfdGltZV9vZl95ZWFyLCBmaWcuaGVpZ2h0PTcuNDE2NDA3OSwgZmlnLndpZHRoPTEyfQpnZ3Bsb3QoZmxpZ2h0X2RhdGEsCiAgICAgICBhZXMoCiAgICAgICAgICAgeCA9IGFzLkRhdGUoZm9ybWF0KERhdGVUaW1lLCBmb3JtYXQgPSAiJW0tJWQiKSwgZm9ybWF0ID0gIiVtLSVkIiksCiAgICAgICAgICAgeSA9IEFzY2VudF9SYXRlX21fcywKICAgICAgICAgICBjb2xvdXIgPSBGbGlnaHQKICAgICAgICkpICsKICAgIGdlb21fcG9pbnQoKSArIGdlb21fcGF0aCgpICsKICAgIGdlb21faGxpbmUoeWludGVyY2VwdCA9IDAsIGFscGhhID0gMC4yKSArCiAgICBzY2FsZV94X2RhdGUoCiAgICAgICAgZGF0ZV9icmVha3MgPSAiMSBtb250aCIsCiAgICAgICAgbGFiZWxzID0gZGF0ZV9mb3JtYXQoIiViIiksCiAgICAgICAgbGltaXRzID0gYXMuRGF0ZShjKCIwMS0wMSIsICIxMi0zMSIpLCBmb3JtYXQgPSAiJW0tJWQiKSwKICAgICAgICBleHBhbmQgPSBjKDAsIDApCiAgICApICsKICAgIGdlb21fZGwoYWVzKGxhYmVsID0gZ3N1YigiTlMiLCAiIiwgRmxpZ2h0KSksCiAgICAgICAgICAgIG1ldGhvZCA9IGxpc3QoY2V4ID0gMC44LCBkbC50cmFucyh5ID0geSArIDAuMiksICJ0b3AuYnVtcHVwIikpICsgZ3VpZGVzKGNvbG91ciA9IEZBTFNFKSArCiAgICBsYWJzKHRpdGxlID0gIkFzY2VudCBSYXRlIHZzIFRpbWUgb2YgWWVhciIsIHggPSAiVGltZSBvZiBZZWFyIiwgeSA9ICJBc2NlbnQgUmF0ZSAobS9zKSIpCmBgYAoKIyMgQXNjZW50IFJhdGUgQWZ0ZXIgQnVyc3QKCmBgYHtyIGFzY2VudF9yYXRlX2FmdGVyX2J1cnN0LCBmaWcuaGVpZ2h0PTcuNDE2NDA3OSwgZmlnLndpZHRoPTEyfQpnZ3Bsb3QoZmxpZ2h0X2RhdGEsCiAgICAgICBhZXMoeCA9IGJ1cnN0X2RpZmZ0aW1lIC8gNjAsCiAgICAgICAgICAgeSA9IEFzY2VudF9SYXRlX21fcywKICAgICAgICAgICBjb2xvdXIgPSBGbGlnaHQpKSArCiAgICBnZW9tX3BhdGgoKSArCiAgICB4bGltKC0wLjUsIDMpICsKICAgIGdlb21fZGwoYWVzKGxhYmVsID0gZ3N1YigiTlMiLCAiIiwgRmxpZ2h0KSksIG1ldGhvZCA9IGxpc3QoInNtYXJ0LmdyaWQiLCAic21hbGwuYm94LmxhYmVscyIpKSArIGd1aWRlcyhjb2xvdXIgPSBGQUxTRSkgKwogICAgbGFicyh0aXRsZSA9ICJBc2NlbnQgUmF0ZSBBZnRlciBCdXJzdCIsIHggPSAiVGltZSBTaW5jZSBCdXJzdCAobWludXRlcykiLCB5ID0gIkFzY2VudCBSYXRlIChtL3MpIikKYGBgCgojIyBBc2NlbnQgUmF0ZSB2cyBBbHRpdHVkZQoKYGBge3IgYXNjZW50X3JhdGVfdnNfYWx0aXR1ZGUsIGZpZy5oZWlnaHQ9Ny40MTY0MDc5LCBmaWcud2lkdGg9MTJ9CmdncGxvdChmbGlnaHRfZGF0YSwKICAgICAgIGFlcyh4ID0gQWx0aXR1ZGVfbSAvIDEwMDAsCiAgICAgICAgICAgeSA9IEFzY2VudF9SYXRlX21fcywKICAgICAgICAgICBjb2xvdXIgPSBGbGlnaHQpKSArCiAgICBnZW9tX3BhdGgoKSArCiAgICBnZW9tX2RsKGFlcyhsYWJlbCA9IGdzdWIoIk5TIiwgIiIsIEZsaWdodCkpLAogICAgICAgICAgICBtZXRob2QgPSBsaXN0KCJmYXIuZnJvbS5vdGhlcnMuYm9yZGVycyIsICJzbWFsbC5ib3gubGFiZWxzIikpICsgZ3VpZGVzKGNvbG91ciA9IEZBTFNFKSArCiAgICBsYWJzKHRpdGxlID0gIkFzY2VudCBSYXRlIHZzIEFsdGl0dWRlIiwgeCA9ICJBbHRpdHVkZSAoa20pIiwgeSA9ICJBc2NlbnQgUmF0ZSAobS9zKSIpCmBgYAoKIyBHcm91bmQgU3BlZWQKCiMjIEdyb3VuZCBTcGVlZCB2cyBUaW1lIG9mIFllYXIKCmBgYHtyIGdyb3VuZF9zcGVlZF92c190aW1lX29mX3llYXIsIGZpZy5oZWlnaHQ9Ny40MTY0MDc5LCBmaWcud2lkdGg9MTJ9CmdncGxvdChmbGlnaHRfZGF0YSwKICAgICAgIGFlcygKICAgICAgICAgICB4ID0gYXMuRGF0ZShmb3JtYXQoRGF0ZVRpbWUsIGZvcm1hdCA9ICIlbS0lZCIpLCBmb3JtYXQgPSAiJW0tJWQiKSwKICAgICAgICAgICB5ID0gR3JvdW5kX1NwZWVkX21fcywKICAgICAgICAgICBjb2xvdXIgPSBGbGlnaHQKICAgICAgICkpICsKICAgIGdlb21fcG9pbnQoKSArIGdlb21fcGF0aCgpICsKICAgIHNjYWxlX3hfZGF0ZSgKICAgICAgICBkYXRlX2JyZWFrcyA9ICIxIG1vbnRoIiwKICAgICAgICBsYWJlbHMgPSBkYXRlX2Zvcm1hdCgiJWIiKSwKICAgICAgICBsaW1pdHMgPSBhcy5EYXRlKGMoIjAxLTAxIiwgIjEyLTMxIiksIGZvcm1hdCA9ICIlbS0lZCIpLAogICAgICAgIGV4cGFuZCA9IGMoMCwgMCkKICAgICkgKwogICAgZ2VvbV9kbChhZXMobGFiZWwgPSBnc3ViKCJOUyIsICIiLCBGbGlnaHQpKSwKICAgICAgICAgICAgbWV0aG9kID0gbGlzdChjZXggPSAwLjgsIGRsLnRyYW5zKHkgPSB5ICsgMC4yKSwgInRvcC5idW1wdXAiKSkgKyBndWlkZXMoY29sb3VyID0gRkFMU0UpICsKICAgIGxhYnModGl0bGUgPSAiR3JvdW5kIFNwZWVkIHZzIFRpbWUgb2YgWWVhciIsIHggPSAiVGltZSBvZiBZZWFyIiwgeSA9ICJHcm91bmQgU3BlZWQgKG0vcykiKQpgYGAKCiMjIEdyb3VuZCBTcGVlZCB2cyBBbHRpdHVkZQoKYGBge3IgZ3JvdW5kX3NwZWVkX3ZzX2FsdGl0dWRlLCBmaWcuaGVpZ2h0PTcuNDE2NDA3OSwgZmlnLndpZHRoPTEyfQpnZ3Bsb3QoCiAgICBmbGlnaHRfZGF0YSwKICAgIGFlcygKICAgICAgICB4ID0gQWx0aXR1ZGVfbSAvIDEwMDAsCiAgICAgICAgeSA9IEdyb3VuZF9TcGVlZF9tX3MsCiAgICAgICAgY29sb3VyID0gYXMuUE9TSVhsdChEYXRlVGltZSkkeWRheQogICAgKQopICsKICAgIGdlb21fcG9pbnQoKSArCiAgICBzY2FsZV9jb2xvdXJfZ3JhZGllbnQyKAogICAgICAgIGxpbWl0cyA9IGMoMCwgMzY2KSwKICAgICAgICBsb3cgPSAiZ3JlZW4iLAogICAgICAgIG1pZCA9ICJyZWQiLAogICAgICAgIG1pZHBvaW50ID0gMzY2IC8gMiwKICAgICAgICBoaWdoID0gImJsdWUiCiAgICApICsKICAgIGxhYnMoCiAgICAgICAgdGl0bGUgPSAiR3JvdW5kIFNwZWVkIHZzIEFsdGl0dWRlIiwKICAgICAgICB4ID0gIkFsdGl0dWRlIChrbSkiLAogICAgICAgIHkgPSAiR3JvdW5kIFNwZWVkIChtL3MpIiwKICAgICAgICBjb2xvdXIgPSAiRGF5IG9mIFllYXIiCiAgICApICsKICAgIHRoZW1lKAogICAgICAgIGxlZ2VuZC5wb3NpdGlvbiA9IGMoMSwgMSksCiAgICAgICAgbGVnZW5kLmRpcmVjdGlvbiA9ICJob3Jpem9udGFsIiwKICAgICAgICBsZWdlbmQuanVzdGlmaWNhdGlvbiA9ICJyaWdodCIKICAgICkKYGBgCgpHcmVlbjogbGF0ZSB3aW50ZXIsIFllbGxvdzogc3ByaW5nLCBSZWQ6IHN1bW1lciwgUHVycGxlOiBhdXR1bW4sIEJsdWU6IGVhcmx5IHdpbnRlcgoKIyBBc2NlbnQgYW5kIERlc2NlbnQgRHVyYXRpb25zCgpGb3IgZmxpZ2h0cyB3aXRoIGRlZmluaXRlIGJ1cnN0IGFuZCBsYW5kaW5nIHRpbWVzLCB3ZSBjYW4gZXh0cmFjdCB0aGUgdGltZXMgaXQgdG9vayBmb3IgdGhlIGJhbGxvb24gdG8gYXNjZW5kIGFuZCBkZXNjZW5kIGZyb20gbWF4IGFsdGl0dWRlLiAKCmBgYHtyIGR1cmF0aW9uX3JhdGlvc30KZmxpZ2h0X2R1cmF0aW9ucyA8LSBkYXRhLmZyYW1lKCkKCmZvciAoY3VycmVudF9mbGlnaHQgaW4gZmxpZ2h0X3RpbWVzJEZsaWdodCkKewogICAgaWYgKCFpcy5uYShmbGlnaHRfdGltZXMkTGF1bmNoX1RpbWVbZmxpZ2h0X3RpbWVzJEZsaWdodCA9PSBjdXJyZW50X2ZsaWdodF0pICYmCiAgICAgICAgIWlzLm5hKGZsaWdodF90aW1lcyRCdXJzdF9UaW1lW2ZsaWdodF90aW1lcyRGbGlnaHQgPT0gY3VycmVudF9mbGlnaHRdKSAmJgogICAgICAgICFpcy5uYShmbGlnaHRfdGltZXMkTGFuZGluZ19UaW1lW2ZsaWdodF90aW1lcyRGbGlnaHQgPT0gY3VycmVudF9mbGlnaHRdKSkKICAgIHsKICAgICAgICBjdXJyZW50X2FzY2VudF9kdXJhdGlvbiA8LQogICAgICAgICAgICBhcy5udW1lcmljKHdpdGgoCiAgICAgICAgICAgICAgICBmbGlnaHRfdGltZXMsCiAgICAgICAgICAgICAgICBkaWZmdGltZShMYXVuY2hfVGltZVtGbGlnaHQgPT0gY3VycmVudF9mbGlnaHRdLCBCdXJzdF9UaW1lW0ZsaWdodCA9PSBjdXJyZW50X2ZsaWdodF0sIHVuaXRzID0gIm1pbnMiKQogICAgICAgICAgICApKSAqIC0xCiAgICAgICAgY3VycmVudF9kZXNjZW50X2R1cmF0aW9uIDwtCiAgICAgICAgICAgIGFzLm51bWVyaWMod2l0aCgKICAgICAgICAgICAgICAgIGZsaWdodF90aW1lcywKICAgICAgICAgICAgICAgIGRpZmZ0aW1lKExhbmRpbmdfVGltZVtGbGlnaHQgPT0gY3VycmVudF9mbGlnaHRdLCBCdXJzdF9UaW1lW0ZsaWdodCA9PSBjdXJyZW50X2ZsaWdodF0sIHVuaXRzID0gIm1pbnMiKQogICAgICAgICAgICApKQogICAgICAgIAogICAgICAgIGZsaWdodF9kdXJhdGlvbnMgPC0gcmJpbmQoCiAgICAgICAgICAgIGZsaWdodF9kdXJhdGlvbnMsCiAgICAgICAgICAgIGRhdGEuZnJhbWUoCiAgICAgICAgICAgICAgICBGbGlnaHQgPSBjdXJyZW50X2ZsaWdodCwKICAgICAgICAgICAgICAgIERhdGUgPSBmbGlnaHRfdGltZXMkRGF0ZVtmbGlnaHRfdGltZXMkRmxpZ2h0ID09IGN1cnJlbnRfZmxpZ2h0XSwKICAgICAgICAgICAgICAgIEFzY2VudF9EdXJhdGlvbl9taW4gPSBjdXJyZW50X2FzY2VudF9kdXJhdGlvbiwKICAgICAgICAgICAgICAgIERlc2NlbnRfRHVyYXRpb25fbWluID0gY3VycmVudF9kZXNjZW50X2R1cmF0aW9uLAogICAgICAgICAgICAgICAgUmF0aW8gPSBjdXJyZW50X2FzY2VudF9kdXJhdGlvbiAvIGN1cnJlbnRfZGVzY2VudF9kdXJhdGlvbgogICAgICAgICAgICApCiAgICAgICAgKQogICAgfQp9CgpybShjdXJyZW50X2ZsaWdodCwKICAgY3VycmVudF9hc2NlbnRfZHVyYXRpb24sCiAgIGN1cnJlbnRfZGVzY2VudF9kdXJhdGlvbikKCnJtYXJrZG93bjo6cGFnZWRfdGFibGUoZmxpZ2h0X2R1cmF0aW9ucykKYGBgCgpPbiBhdmVyYWdlLCBhc2NlbnQgdGFrZXMgYHIgc2lnbmlmKG1lYW4oZmxpZ2h0X2R1cmF0aW9ucyRBc2NlbnRfRHVyYXRpb25fbWluKSwgZGlnaXRzID0gMilgIG1pbnV0ZXMsIHdoaWxlIGRlc2NlbnQgdGFrZXMgYHIgc2lnbmlmKG1lYW4oZmxpZ2h0X2R1cmF0aW9ucyREZXNjZW50X0R1cmF0aW9uX21pbiksIGRpZ2l0cyA9IDIpYCBtaW51dGVzLCB3aXRoIGEgcmF0aW8gb2YgYHIgc2lnbmlmKG1lYW4oZmxpZ2h0X2R1cmF0aW9ucyRSYXRpbyksIGRpZ2l0cyA9IDIpYC4KCiMjIEFzY2VudCBEdXJhdGlvbiB2cyBEZXNjZW50IER1cmF0aW9uCgpgYGB7ciBjdXJyZW50X2FzY2VudF9kdXJhdGlvbl92c19jdXJyZW50X2Rlc2NlbnRfZHVyYXRpb24sIGZpZy5oZWlnaHQ9MTIsIGZpZy53aWR0aD03LjQxNjQwNzl9CmdncGxvdCgKICAgIGZsaWdodF9kdXJhdGlvbnMsCiAgICBhZXMoCiAgICAgICAgeCA9IERlc2NlbnRfRHVyYXRpb25fbWluLAogICAgICAgIHkgPSBBc2NlbnRfRHVyYXRpb25fbWluLAogICAgICAgIGNvbG91ciA9IGFzLlBPU0lYbHQoRGF0ZSkkeWRheQogICAgKQopICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuMSkgKyBnZW9tX2FibGluZShzbG9wZSA9IDE6MykgKwogICAgc2NhbGVfY29sb3VyX2dyYWRpZW50MigKICAgICAgICBsaW1pdHMgPSBjKDAsIDM2NiksCiAgICAgICAgbG93ID0gImdyZWVuIiwKICAgICAgICBtaWQgPSAicmVkIiwKICAgICAgICBtaWRwb2ludCA9IDM2NiAvIDIsCiAgICAgICAgaGlnaCA9ICJibHVlIgogICAgKSArCiAgICBnZW9tX2RsKGFlcyhsYWJlbCA9IGdzdWIoIk5TIiwgIiIsIEZsaWdodCkpLCBtZXRob2QgPSBsaXN0KGNleCA9IDAuOCkpICsKICAgIGxhYnMoCiAgICAgICAgdGl0bGUgPSAiQXNjZW50IER1cmF0aW9uIHZzIERlc2NlbnQgRHVyYXRpb24iLAogICAgICAgIHggPSAiRGVzY2VudCBEdXJhdGlvbiAobWludXRlcykiLAogICAgICAgIHkgPSAiQXNjZW50IER1cmF0aW9uIChtaW51dGVzKSIsCiAgICAgICAgY29sb3VyID0gIkRheSBvZiBZZWFyIgogICAgKSArCiAgICBjb29yZF9maXhlZChyYXRpbyA9IDEpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoCiAgICAgICAgZnJvbSA9IDAsCiAgICAgICAgdG8gPSBtYXgoZmxpZ2h0X2RhdGEkRG93bnJhbmdlX0Rpc3RhbmNlX20pLAogICAgICAgIGJ5ID0gMTAKICAgICkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoCiAgICAgICAgZnJvbSA9IDAsCiAgICAgICAgdG8gPSBtYXgoZmxpZ2h0X2RhdGEkQWx0aXR1ZGVfbSksCiAgICAgICAgYnkgPSAxMAogICAgKSkgKwogICAgdGhlbWUoCiAgICAgICAgbGVnZW5kLnBvc2l0aW9uID0gYygxLCAwLjk2KSwKICAgICAgICBsZWdlbmQuZGlyZWN0aW9uID0gImhvcml6b250YWwiLAogICAgICAgIGxlZ2VuZC5qdXN0aWZpY2F0aW9uID0gInJpZ2h0IgogICAgKQpgYGAKR3JlZW46IGxhdGUgd2ludGVyLCBZZWxsb3c6IHNwcmluZywgUmVkOiBzdW1tZXIsIFB1cnBsZTogYXV0dW1uLCBCbHVlOiBlYXJseSB3aW50ZXIKCmBgYHtyIHRlYXJkb3duLCBpbmNsdWRlPUZBTFNFfQpybShyZWFkX2ZsaWdodF90aW1lcywgcmVhZF9mbGlnaHRfZGF0YSkKCnJtKHNtYWxsLmJveC5sYWJlbHMpCiNybShmbGlnaHRfdGltZXMpCiNybShmbGlnaHRfZGF0YSkKYGBg