Flight Analysis
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)
require(ggmap)
require(directlabels)
require(scales)
source("setup.R")
flight_times <- read_flight_times("flight_times.txt")
flight_data <- read_flight_data("flight_data/", calculate_difftime = TRUE)
Summary
Flight Times
This table shows launch time, burst time, burst altitude, landing time, and masses of each flight.
rmarkdown::paged_table(read.csv("flight_times.txt"))
Map
Usually, the program launches balloons from the parking lot of Clear Spring Elementary School in Clear Spring, MD. However, flight predictions sometimes force launches from further west to avoid landing in either Baltimore or the Chesapeake Bay.
# get data excluding NS69 (eclipse launch in South Carolina)
maryland_flights <- flight_data[flight_data$Flight != "NS69",]
# get map tile
if (!exists("map"))
{
map <-
get_map(location = c(
min(maryland_flights$Longitude),
min(maryland_flights$Latitude),
max(maryland_flights$Longitude),
max(maryland_flights$Latitude)
),
maptype = "roadmap")
}
# plot base layer to map tile
ggmap(map,
base_layer = ggplot(maryland_flights,
aes(
x = Longitude, y = Latitude, colour = Flight
)),
extent = "normal") +
geom_point() + geom_path() +
geom_dl(aes(label = gsub("NS", "", Flight)),
method = list("far.from.others.borders", "small.box.labels")) + guides(colour = FALSE) +
labs(title = "Maryland Flights", x = "Longitude", y = "Latitude")
D. Kahle and H. Wickham. ggmap: Spatial Visualization with ggplot2. The R Journal, 5(1), 144-161.
Altitude vs Downrange Distance
ggplot(flight_data,
aes(
x = Downrange_Distance_m / 1000,
y = Altitude_m / 1000,
colour = Flight
)) +
geom_point(size = 0.75) + geom_path(alpha = 0.3) +
coord_fixed(ratio = 3) +
scale_x_continuous(breaks = seq(
from = 0,
to = max(flight_data$Downrange_Distance_m),
by = 30
)) +
scale_y_continuous(breaks = seq(
from = 0,
to = max(flight_data$Altitude_m),
by = 10
)) +
geom_hline(yintercept = 12.1, alpha = 0.2) +
geom_dl(aes(label = gsub("NS", "", Flight)),
method = list("far.from.others.borders", "small.box.labels")) + guides(colour = FALSE) +
labs(title = "Altitude vs Downrange Distance", x = "Downrange Distance (km)", y = "Altitude (km)")
axes to 1:3 scale
Altitude
Altitude vs Date
ggplot(flight_data,
aes(x = DateTime,
y = Altitude_m / 1000,
colour = Flight)) +
geom_point() + geom_path() +
geom_hline(yintercept = 12.1, alpha = 0.2) +
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 = "Altitude vs Date", x = "Date", y = "Altitude (km)")
Altitude vs Time of Year
ggplot(flight_data,
aes(
x = as.Date(format(DateTime, format = "%m-%d"), format = "%m-%d"),
y = Altitude_m / 1000,
colour = Flight
)) +
geom_point() + geom_path() +
geom_hline(yintercept = 12.100, 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 = "Altitude vs Time of Year", x = "Time of Year", y = "Altitude (km)")
Altitude vs Time After Launch
ggplot(flight_data,
aes(
x = launch_difftime / 60,
y = Altitude_m / 1000,
colour = Flight
)) +
geom_point(size = 0.75) + geom_path() +
geom_hline(yintercept = 12.100, alpha = 0.2) +
geom_dl(aes(label = gsub("NS", "", Flight)),
method = list("far.from.others.borders", "small.box.labels")) + guides(colour = FALSE) +
labs(title = "Altitude vs Time After Launch", x = "Time After Launch (minutes)", y = "Altitude (km)")
Downrange Distance
Using a geodesic, we can calculate distance between coordinate points to get downrange distance. Downrange distance represents the distance from the coordinates of the launch site to the coordinates of the data point.
Downrange Distance vs Time of Year
ggplot(flight_data,
aes(
x = as.Date(format(DateTime, format = "%m-%d"), format = "%m-%d"),
y = Downrange_Distance_m / 1000,
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 = "Downrange Distance vs Time of Year", x = "Time of Year", y = "Downrange Distance (km)")
Downrange Distance vs Time After Launch
ggplot(
flight_data,
aes(
x = launch_difftime / 60,
y = Downrange_Distance_m / 1000,
colour = Flight
)
) +
geom_point(size = 0.75) + geom_path() +
geom_dl(aes(label = gsub("NS", "", Flight)),
method = list("far.from.others.borders", "small.box.labels")) + guides(colour = FALSE) +
labs(title = "Downrange Distance vs Time After Launch", x = "Time After Launch (minutes)", y = "Downrange Distance (km)")
LS0tCnRpdGxlOiAiRmxpZ2h0IFN1bW1hcnkiCm91dHB1dDoKICBodG1sX25vdGVib29rOiAKICAgIGNvZGVfZm9sZGluZzogaGlkZQogICAgdG9jOiB5ZXMKICAgIG51bWJlcl9zZWN0aW9uczogeWVzCiAgICB0b2NfZmxvYXQ6IAogICAgICAgIGNvbGxhcHNlZDogZmFsc2UKLS0tCgpbRmxpZ2h0IEFuYWx5c2lzXShmbGlnaHRfYW5hbHlzaXMubmIuaHRtbCkKCltGbGlnaHQgU3RhdGlzdGljc10oZmxpZ2h0X3N0YXRpc3RpY3MubmIuaHRtbCkKCkRhdGEgbm9ybWFsaXplZCBhY3Jvc3Mgc2V2ZXJhbCBmbGlnaHQgbG9ncywgc3Bhbm5pbmcgZnJvbSBgciBtaW4obGV2ZWxzKGZsaWdodF9kYXRhJEZsaWdodCkpYCB0byBgciBtYXgobGV2ZWxzKGZsaWdodF9kYXRhJEZsaWdodCkpYCwgZXhjZXB0aW5nIE5TNTQsIE5TNTUsIGFuZCBOUzY4IChOUzU0IGlzIHJlc2VydmVkIGZvciBhIGZsaWdodCBzdGlsbCBpbiBkZXZlbG9wbWVudCwgYW5kIGJvdGggTlM1NSBhbmQgTlM2OCBmYWlsZWQgdG8gcmVjb3JkIGxvY2F0aW9uIGRhdGEpLgoKRHVlIHRvIGEgc2V0dGluZ3MgaXNzdWUsIGJlZm9yZSBOUzU5LCB0aGUgY2VsbCB0cmFja2VyIGhhcmR3YXJlIHN0b3BwZWQgcmVjb3JkaW5nIGFib3ZlIDEyLjEga20gKGV4Y2VwdCBmb3IgTlM1MykuIFRoaXMgbGltaXQgaXMgc2hvd24gYXMgYSBncmV5IGhvcml6b250YWwgbGluZSBpbiB0aGUgZmlndXJlcyBkZXBpY3RpbmcgYWx0aXR1ZGUuCgpgYGB7ciBzZXR1cH0KcmVxdWlyZShnZ3Bsb3QyKQpyZXF1aXJlKGdnbWFwKQpyZXF1aXJlKGRpcmVjdGxhYmVscykKcmVxdWlyZShzY2FsZXMpCgpzb3VyY2UoInNldHVwLlIiKQoKZmxpZ2h0X3RpbWVzIDwtIHJlYWRfZmxpZ2h0X3RpbWVzKCJmbGlnaHRfdGltZXMudHh0IikKZmxpZ2h0X2RhdGEgPC0gcmVhZF9mbGlnaHRfZGF0YSgiZmxpZ2h0X2RhdGEvIiwgY2FsY3VsYXRlX2RpZmZ0aW1lID0gVFJVRSkKYGBgCgojIFN1bW1hcnkKCiMjIEZsaWdodCBUaW1lcwoKVGhpcyB0YWJsZSBzaG93cyBsYXVuY2ggdGltZSwgYnVyc3QgdGltZSwgYnVyc3QgYWx0aXR1ZGUsIGxhbmRpbmcgdGltZSwgYW5kIG1hc3NlcyBvZiBlYWNoIGZsaWdodC4KCmBgYHtyIGZsaWdodF90aW1lcywgZmlnLmhlaWdodD03LjQxNjQwNzksIGZpZy53aWR0aD0xMn0Kcm1hcmtkb3duOjpwYWdlZF90YWJsZShyZWFkLmNzdigiZmxpZ2h0X3RpbWVzLnR4dCIpKQpgYGAKCiMjIE1hcAoKVXN1YWxseSwgdGhlIHByb2dyYW0gbGF1bmNoZXMgYmFsbG9vbnMgZnJvbSB0aGUgcGFya2luZyBsb3Qgb2YgW0NsZWFyIFNwcmluZyBFbGVtZW50YXJ5IFNjaG9vbCBpbiBDbGVhciBTcHJpbmcsIE1EXShodHRwczovL3d3dy5nb29nbGUuY29tL21hcHMvcGxhY2UvQ2xlYXIrU3ByaW5nK0VsZW1lbnRhcnkrU2Nob29sL0AzOS42NTY3Mzk5LC03Ny45MzU1NjE2LDE3ei9kYXRhPSE0bTUhM200ITFzMHg4OWNhMWZkZGRlYjM1M2Q5OjB4NzFjYjFiMjJiMzAyYzk4ZCE4bTIhM2QzOS42NTY3MDghNGQtNzcuOTM0MTc2NikuIEhvd2V2ZXIsIGZsaWdodCBwcmVkaWN0aW9ucyBzb21ldGltZXMgZm9yY2UgbGF1bmNoZXMgZnJvbSBmdXJ0aGVyIHdlc3QgdG8gYXZvaWQgbGFuZGluZyBpbiBlaXRoZXIgQmFsdGltb3JlIG9yIHRoZSBDaGVzYXBlYWtlIEJheS4KCmBgYHtyIGNvb3JkaW5hdGVzX21hcCwgZmlnLmhlaWdodD0xMCwgZmlnLndpZHRoPTEyfQojIGdldCBkYXRhIGV4Y2x1ZGluZyBOUzY5IChlY2xpcHNlIGxhdW5jaCBpbiBTb3V0aCBDYXJvbGluYSkKbWFyeWxhbmRfZmxpZ2h0cyA8LSBmbGlnaHRfZGF0YVtmbGlnaHRfZGF0YSRGbGlnaHQgIT0gIk5TNjkiLF0KCiMgZ2V0IG1hcCB0aWxlCmlmICghZXhpc3RzKCJtYXAiKSkKewogICAgbWFwIDwtCiAgICAgICAgZ2V0X21hcChsb2NhdGlvbiA9IGMoCiAgICAgICAgICAgIG1pbihtYXJ5bGFuZF9mbGlnaHRzJExvbmdpdHVkZSksCiAgICAgICAgICAgIG1pbihtYXJ5bGFuZF9mbGlnaHRzJExhdGl0dWRlKSwKICAgICAgICAgICAgbWF4KG1hcnlsYW5kX2ZsaWdodHMkTG9uZ2l0dWRlKSwKICAgICAgICAgICAgbWF4KG1hcnlsYW5kX2ZsaWdodHMkTGF0aXR1ZGUpCiAgICAgICAgKSwKICAgICAgICBtYXB0eXBlID0gInJvYWRtYXAiKQp9CgojIHBsb3QgYmFzZSBsYXllciB0byBtYXAgdGlsZQpnZ21hcChtYXAsCiAgICAgIGJhc2VfbGF5ZXIgPSBnZ3Bsb3QobWFyeWxhbmRfZmxpZ2h0cywKICAgICAgICAgICAgICAgICAgICAgICAgICBhZXMoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHggPSBMb25naXR1ZGUsIHkgPSBMYXRpdHVkZSwgY29sb3VyID0gRmxpZ2h0CiAgICAgICAgICAgICAgICAgICAgICAgICAgKSksCiAgICAgIGV4dGVudCA9ICJub3JtYWwiKSArCiAgICBnZW9tX3BvaW50KCkgKyBnZW9tX3BhdGgoKSArCiAgICBnZW9tX2RsKGFlcyhsYWJlbCA9IGdzdWIoIk5TIiwgIiIsIEZsaWdodCkpLAogICAgICAgICAgICBtZXRob2QgPSBsaXN0KCJmYXIuZnJvbS5vdGhlcnMuYm9yZGVycyIsICJzbWFsbC5ib3gubGFiZWxzIikpICsgZ3VpZGVzKGNvbG91ciA9IEZBTFNFKSArCiAgICBsYWJzKHRpdGxlID0gIk1hcnlsYW5kIEZsaWdodHMiLCB4ID0gIkxvbmdpdHVkZSIsIHkgPSAiTGF0aXR1ZGUiKQpgYGAKCltELiBLYWhsZSBhbmQgSC4gV2lja2hhbS4gZ2dtYXA6IFNwYXRpYWwgVmlzdWFsaXphdGlvbiB3aXRoIGdncGxvdDIuIFRoZSBSIEpvdXJuYWwsIDUoMSksIDE0NC0xNjEuXShodHRwOi8vam91cm5hbC5yLXByb2plY3Qub3JnL2FyY2hpdmUvMjAxMy0xL2thaGxlLXdpY2toYW0ucGRmKQoKIyMgQWx0aXR1ZGUgdnMgRG93bnJhbmdlIERpc3RhbmNlCgpgYGB7ciBhbHRpdHVkZV92c19kb3ducmFuZ2VfZGlzdGFuY2UsIGZpZy5oZWlnaHQ9Ny40MTY0MDc5LCBmaWcud2lkdGg9MTJ9CmdncGxvdChmbGlnaHRfZGF0YSwKICAgICAgIGFlcygKICAgICAgICAgICB4ID0gRG93bnJhbmdlX0Rpc3RhbmNlX20gLyAxMDAwLAogICAgICAgICAgIHkgPSBBbHRpdHVkZV9tIC8gMTAwMCwKICAgICAgICAgICBjb2xvdXIgPSBGbGlnaHQKICAgICAgICkpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuNzUpICsgZ2VvbV9wYXRoKGFscGhhID0gMC4zKSArCiAgICBjb29yZF9maXhlZChyYXRpbyA9IDMpICsKICAgIHNjYWxlX3hfY29udGludW91cyhicmVha3MgPSBzZXEoCiAgICAgICAgZnJvbSA9IDAsCiAgICAgICAgdG8gPSBtYXgoZmxpZ2h0X2RhdGEkRG93bnJhbmdlX0Rpc3RhbmNlX20pLAogICAgICAgIGJ5ID0gMzAKICAgICkpICsKICAgIHNjYWxlX3lfY29udGludW91cyhicmVha3MgPSBzZXEoCiAgICAgICAgZnJvbSA9IDAsCiAgICAgICAgdG8gPSBtYXgoZmxpZ2h0X2RhdGEkQWx0aXR1ZGVfbSksCiAgICAgICAgYnkgPSAxMAogICAgKSkgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTIuMSwgYWxwaGEgPSAwLjIpICsKICAgIGdlb21fZGwoYWVzKGxhYmVsID0gZ3N1YigiTlMiLCAiIiwgRmxpZ2h0KSksCiAgICAgICAgICAgIG1ldGhvZCA9IGxpc3QoImZhci5mcm9tLm90aGVycy5ib3JkZXJzIiwgInNtYWxsLmJveC5sYWJlbHMiKSkgKyBndWlkZXMoY29sb3VyID0gRkFMU0UpICsKICAgIGxhYnModGl0bGUgPSAiQWx0aXR1ZGUgdnMgRG93bnJhbmdlIERpc3RhbmNlIiwgeCA9ICJEb3ducmFuZ2UgRGlzdGFuY2UgKGttKSIsIHkgPSAiQWx0aXR1ZGUgKGttKSIpCmBgYApheGVzIHRvIDE6MyBzY2FsZQoKIyBBbHRpdHVkZQoKIyMgQWx0aXR1ZGUgdnMgRGF0ZQoKYGBge3IgYWx0aXR1ZGVfdnNfZGF0ZSwgZmlnLmhlaWdodD03LjQxNjQwNzksIGZpZy53aWR0aD0xMn0KZ2dwbG90KGZsaWdodF9kYXRhLAogICAgICAgYWVzKHggPSBEYXRlVGltZSwKICAgICAgICAgICB5ID0gQWx0aXR1ZGVfbSAvIDEwMDAsCiAgICAgICAgICAgY29sb3VyID0gRmxpZ2h0KSkgKwogICAgZ2VvbV9wb2ludCgpICsgZ2VvbV9wYXRoKCkgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTIuMSwgYWxwaGEgPSAwLjIpICsKICAgIGdlb21fZGwoYWVzKGxhYmVsID0gZ3N1YigiTlMiLCAiIiwgRmxpZ2h0KSksCiAgICAgICAgICAgIG1ldGhvZCA9IGxpc3QoY2V4ID0gMC44LCBkbC50cmFucyh5ID0geSArIDAuMiksICJ0b3AuYnVtcHVwIikpICsgZ3VpZGVzKGNvbG91ciA9IEZBTFNFKSArCiAgICBsYWJzKHRpdGxlID0gIkFsdGl0dWRlIHZzIERhdGUiLCB4ID0gIkRhdGUiLCB5ID0gIkFsdGl0dWRlIChrbSkiKQpgYGAKCiMjIEFsdGl0dWRlIHZzIFRpbWUgb2YgWWVhcgoKYGBge3IgYWx0aXR1ZGVfdnNfdGltZV9vZl95ZWFyLCBmaWcuaGVpZ2h0PTcuNDE2NDA3OSwgZmlnLndpZHRoPTEyfQpnZ3Bsb3QoZmxpZ2h0X2RhdGEsCiAgICAgICBhZXMoCiAgICAgICAgICAgeCA9IGFzLkRhdGUoZm9ybWF0KERhdGVUaW1lLCBmb3JtYXQgPSAiJW0tJWQiKSwgZm9ybWF0ID0gIiVtLSVkIiksCiAgICAgICAgICAgeSA9IEFsdGl0dWRlX20gLyAxMDAwLAogICAgICAgICAgIGNvbG91ciA9IEZsaWdodAogICAgICAgKSkgKwogICAgZ2VvbV9wb2ludCgpICsgZ2VvbV9wYXRoKCkgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTIuMTAwLCBhbHBoYSA9IDAuMikgKwogICAgc2NhbGVfeF9kYXRlKAogICAgICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLAogICAgICAgIGxhYmVscyA9IGRhdGVfZm9ybWF0KCIlYiIpLAogICAgICAgIGxpbWl0cyA9IGFzLkRhdGUoYygiMDEtMDEiLCAiMTItMzEiKSwgZm9ybWF0ID0gIiVtLSVkIiksCiAgICAgICAgZXhwYW5kID0gYygwLCAwKQogICAgKSArCiAgICBnZW9tX2RsKGFlcyhsYWJlbCA9IGdzdWIoIk5TIiwgIiIsIEZsaWdodCkpLAogICAgICAgICAgICBtZXRob2QgPSBsaXN0KGNleCA9IDAuOCwgZGwudHJhbnMoeSA9IHkgKyAwLjIpLCAidG9wLmJ1bXB1cCIpKSArIGd1aWRlcyhjb2xvdXIgPSBGQUxTRSkgKwogICAgbGFicyh0aXRsZSA9ICJBbHRpdHVkZSB2cyBUaW1lIG9mIFllYXIiLCB4ID0gIlRpbWUgb2YgWWVhciIsIHkgPSAiQWx0aXR1ZGUgKGttKSIpCmBgYAoKIyMgQWx0aXR1ZGUgdnMgVGltZSBBZnRlciBMYXVuY2gKCmBgYHtyIGFsdGl0dWRlX3ZzX3RpbWVfYWZ0ZXJfbGF1bmNoLCBmaWcuaGVpZ2h0PTcuNDE2NDA3OSwgZmlnLndpZHRoPTEyfQpnZ3Bsb3QoZmxpZ2h0X2RhdGEsCiAgICAgICBhZXMoCiAgICAgICAgICAgeCA9IGxhdW5jaF9kaWZmdGltZSAvIDYwLAogICAgICAgICAgIHkgPSBBbHRpdHVkZV9tIC8gMTAwMCwKICAgICAgICAgICBjb2xvdXIgPSBGbGlnaHQKICAgICAgICkpICsKICAgIGdlb21fcG9pbnQoc2l6ZSA9IDAuNzUpICsgZ2VvbV9wYXRoKCkgKwogICAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gMTIuMTAwLCBhbHBoYSA9IDAuMikgKwogICAgZ2VvbV9kbChhZXMobGFiZWwgPSBnc3ViKCJOUyIsICIiLCBGbGlnaHQpKSwKICAgICAgICAgICAgbWV0aG9kID0gbGlzdCgiZmFyLmZyb20ub3RoZXJzLmJvcmRlcnMiLCAic21hbGwuYm94LmxhYmVscyIpKSArIGd1aWRlcyhjb2xvdXIgPSBGQUxTRSkgKwogICAgbGFicyh0aXRsZSA9ICJBbHRpdHVkZSB2cyBUaW1lIEFmdGVyIExhdW5jaCIsIHggPSAiVGltZSBBZnRlciBMYXVuY2ggKG1pbnV0ZXMpIiwgeSA9ICJBbHRpdHVkZSAoa20pIikKYGBgCgojIERvd25yYW5nZSBEaXN0YW5jZQoKVXNpbmcgYSBnZW9kZXNpYywgd2UgY2FuIGNhbGN1bGF0ZSBkaXN0YW5jZSBiZXR3ZWVuIGNvb3JkaW5hdGUgcG9pbnRzIHRvIGdldCBkb3ducmFuZ2UgZGlzdGFuY2UuIERvd25yYW5nZSBkaXN0YW5jZSByZXByZXNlbnRzIHRoZSBkaXN0YW5jZSBmcm9tIHRoZSBjb29yZGluYXRlcyBvZiB0aGUgbGF1bmNoIHNpdGUgdG8gdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBkYXRhIHBvaW50LiAKCiMjIERvd25yYW5nZSBEaXN0YW5jZSB2cyBUaW1lIG9mIFllYXIKCmBgYHtyIGRvd25yYW5nZV9kaXN0YW5jZV92c190aW1lX29mX3llYXIsIGZpZy5oZWlnaHQ9Ny40MTY0MDc5LCBmaWcud2lkdGg9MTJ9CmdncGxvdChmbGlnaHRfZGF0YSwKICAgICAgIGFlcygKICAgICAgICAgICB4ID0gYXMuRGF0ZShmb3JtYXQoRGF0ZVRpbWUsIGZvcm1hdCA9ICIlbS0lZCIpLCBmb3JtYXQgPSAiJW0tJWQiKSwKICAgICAgICAgICB5ID0gRG93bnJhbmdlX0Rpc3RhbmNlX20gLyAxMDAwLAogICAgICAgICAgIGNvbG91ciA9IEZsaWdodAogICAgICAgKSkgKwogICAgZ2VvbV9wb2ludCgpICsgZ2VvbV9wYXRoKCkgKwogICAgc2NhbGVfeF9kYXRlKAogICAgICAgIGRhdGVfYnJlYWtzID0gIjEgbW9udGgiLAogICAgICAgIGxhYmVscyA9IGRhdGVfZm9ybWF0KCIlYiIpLAogICAgICAgIGxpbWl0cyA9IGFzLkRhdGUoYygiMDEtMDEiLCAiMTItMzEiKSwgZm9ybWF0ID0gIiVtLSVkIiksCiAgICAgICAgZXhwYW5kID0gYygwLCAwKQogICAgKSArCiAgICBnZW9tX2RsKGFlcyhsYWJlbCA9IGdzdWIoIk5TIiwgIiIsIEZsaWdodCkpLAogICAgICAgICAgICBtZXRob2QgPSBsaXN0KGNleCA9IDAuOCwgZGwudHJhbnMoeSA9IHkgKyAwLjIpLCAidG9wLmJ1bXB1cCIpKSArIGd1aWRlcyhjb2xvdXIgPSBGQUxTRSkgKwogICAgbGFicyh0aXRsZSA9ICJEb3ducmFuZ2UgRGlzdGFuY2UgdnMgVGltZSBvZiBZZWFyIiwgeCA9ICJUaW1lIG9mIFllYXIiLCB5ID0gIkRvd25yYW5nZSBEaXN0YW5jZSAoa20pIikKYGBgCgojIyBEb3ducmFuZ2UgRGlzdGFuY2UgdnMgVGltZSBBZnRlciBMYXVuY2gKCmBgYHtyIGRvd25yYW5nZV9kaXN0YW5jZV92c190aW1lX2FmdGVyX2xhdW5jaCwgZmlnLmhlaWdodD03LjQxNjQwNzksIGZpZy53aWR0aD0xMn0KZ2dwbG90KAogICAgZmxpZ2h0X2RhdGEsCiAgICBhZXMoCiAgICAgICAgeCA9IGxhdW5jaF9kaWZmdGltZSAvIDYwLAogICAgICAgIHkgPSBEb3ducmFuZ2VfRGlzdGFuY2VfbSAvIDEwMDAsCiAgICAgICAgY29sb3VyID0gRmxpZ2h0CiAgICApCikgKwogICAgZ2VvbV9wb2ludChzaXplID0gMC43NSkgKyBnZW9tX3BhdGgoKSArCiAgICBnZW9tX2RsKGFlcyhsYWJlbCA9IGdzdWIoIk5TIiwgIiIsIEZsaWdodCkpLAogICAgICAgICAgICBtZXRob2QgPSBsaXN0KCJmYXIuZnJvbS5vdGhlcnMuYm9yZGVycyIsICJzbWFsbC5ib3gubGFiZWxzIikpICsgZ3VpZGVzKGNvbG91ciA9IEZBTFNFKSArCiAgICBsYWJzKHRpdGxlID0gIkRvd25yYW5nZSBEaXN0YW5jZSB2cyBUaW1lIEFmdGVyIExhdW5jaCIsIHggPSAiVGltZSBBZnRlciBMYXVuY2ggKG1pbnV0ZXMpIiwgeSA9ICJEb3ducmFuZ2UgRGlzdGFuY2UgKGttKSIpCmBgYAoKYGBge3IgdGVhcmRvd24sIGluY2x1ZGU9RkFMU0V9CnJtKHJlYWRfZmxpZ2h0X3RpbWVzLCByZWFkX2ZsaWdodF9kYXRhKQoKcm0oc21hbGwuYm94LmxhYmVscykKI3JtKGZsaWdodF9kYXRhKQoKcm0obWFyeWxhbmRfZmxpZ2h0cykKI3JtKG1hcCkKYGBg