Vietnam War Casualties
Estimates of casualties of the Vietnam War vary widely. Estimates include both civilian and military deaths in North and South Vietnam, Laos, and Cambodia.
The war persisted from 1955 to 1975 and most of the fighting took place in South Vietnam; accordingly it suffered the most casualties. The war also spilled over into the neighboring countries of Cambodia and Laos which also endured casualties from aerial and ground fighting.
Civilian deaths caused by both sides amounted to a significant percentage of total deaths. Civilian deaths were partly caused by assassinations, massacres and terror tactics. Civilian deaths were also caused by mortar and artillery, extensive aerial bombing and the use of firepower in military operations conducted in heavily populated areas. Some 365,000 Vietnamese civilians are estimated by one source to have died as a result of the war during the period of American involvement.
A number of incidents occurred during the war in which civilians were deliberately targeted or killed. The best-known are the Massacre at Huế and the My Lai massacre.
According to The Virtual Wall Vietnam Veterans Memorial , the number of U.S casualties during Vietnam War was 58,226.
Collecting Data for 58,226 US Deaths
In this section I present R codes for collecting detailed data (first name, last name, gender, death date, category, birth date, service number, rank, death location, and other information) for 58,226 US Deaths during Vietnam War.
# https://www.honorstates.org/index.php?page=wars&war=Vietnam+Conflict&do=states
# https://laahgp.genealogyvillage.com/MilitaryIndex/vietnam-war-causalities.html
# https://www.jstor.org/stable/2137774?seq=1#page_scan_tab_contents
# https://www.nwitimes.com/the-region-fallen-of-the-vietnam-war/table_1f7fde93-a183-5f1c-ae69-ccac4fdebb5e.html
# http://www.vietnammemorial.com/vietnam-memorial-list-of-heroes.html
# Korean https://www.vvmf.org/Wall-of-Faces/?fbclid=IwAR3JJi8fPklR5QtfRHGfN0oxaDjf4uuHmHFDxulYqICS1aBuzjJIrEmKIqs
# Load some R packages and clear workspace:
rm (list = ls ())
library (rvest)
library (xml2)
library (tidyverse)
#=============================================
# Stage 1: Get links for all soldiers
#=============================================
get_panel_link <- function (url) {
# Create an html document from the url:
webpage <- xml2:: read_html (url)
# Extract the URLs:
url_ <- webpage %>%
rvest:: html_nodes ("a" ) %>%
rvest:: html_attr ("href" )
# Extract the link text:
link_ <- webpage %>%
rvest:: html_nodes ("a" ) %>%
rvest:: html_text ()
return (data_frame (link = link_, url = url_))
}
all_panels <- "http://www.virtualwall.org/iPanels.htm"
panel_links <- get_panel_link (all_panels)
# All suffixes:
all_suffix <- panel_links$ url[str_detect (panel_links$ url, "iPanels/ipan" )] %>% na.omit ()
all_suffix <- str_sub (all_suffix, start = 2 , end = str_count (all_suffix))
all_names_InPanel <- paste0 ("http://www.virtualwall.org" , all_suffix)
# All soldier links:
get_link_for_soldiers <- function (panel_selected) {
soldier_suffix <- get_panel_link (panel_selected)
soldier_suffix %>%
filter (! str_detect (url, "misspelledname" )) %>%
filter (! str_detect (url, "noscriptIndexMenu" )) %>%
filter (! str_detect (url, "index" )) %>%
filter (! str_detect (url, "ipan" )) %>%
mutate (url = paste0 ("http://www.VirtualWall.org" , str_sub (url, start = 3 , end = str_count (url)))) %>%
rename (name = link, link_for_soldier = url) %>%
return ()
}
lapply (all_names_InPanel, get_link_for_soldiers) -> link_soldiers_list
do.call ("bind_rows" , link_soldiers_list) -> df_link_soldiers
df_link_soldiers %>%
filter (! duplicated (link_for_soldier)) -> df_link_soldiers
# Save our data:
write.csv (df_link_soldiers, "df_link_soldiers.csv" , row.names = FALSE )
#=============================================
# Stage 2: Get data for all soldiers
#=============================================
# Function for collecting all from a soldier:
collect_all_DataSoldier <- function (my_link) {
pg <- read_html (my_link)
html_text (pg, trim = TRUE ) %>%
str_split (" \\\n " , simplify = TRUE ) %>%
as.character () %>%
str_squish () %>%
.[3 : 27 ] -> m
m %>%
str_split (" \\ /" , simplify = TRUE ) %>%
data.frame () %>%
mutate_all (as.character) -> df
df_date <- df %>%
slice (c (17 : 19 )) %>%
mutate (my_date = paste0 (X1, X2, X3)) %>%
select (my_date, X5)
t (df_date %>% select (my_date)) %>%
as.data.frame () -> df_date_soldier
names (df_date_soldier) <- c ("birth" , "start" , "cas_date" )
df_remain <- df %>%
slice (- c (17 : 19 )) %>%
select (X1, X3)
t (df_remain %>% select (X1)) %>%
as.data.frame () -> df
names (df) <- c (df_remain$ X3[1 : 2 ], "notKnown" , "Grade_at_loss" , df_remain$ X3[5 : 22 ])
all_data_soldier <- bind_cols (df, df_date_soldier)
return (all_data_soldier %>% mutate (link = my_link))
}
get_SoldierData <- function (link_selected) {
return (tryCatch (collect_all_DataSoldier (link_selected), error = function (e) {NULL }))
}
# Use this function:
df_link_soldiers <- read_csv ("df_link_soldiers.csv" )
soldier_links <- df_link_soldiers$ link_for_soldier
lapply (soldier_links, get_SoldierData) -> all_data_list
save (all_data_list, file = "all_data_list.RData" )
do.call ("bind_rows" , all_data_list) %>%
select (- V1) -> all_data_df
# Save our data:
write.csv (all_data_df, "all_us_deaths_in_Vietnam_war.csv" , row.names = FALSE )
US Fatal Deaths by Military Rank
#==================================================
# Stage 3: Data-preprocessing and visualization
#==================================================
library (tidyverse)
# Import data:
all_data_df <- read_csv ("C: \\ Users \\ Zbook \\ Documents \\ all_us_deaths_in_Vietnam_war.csv" )
all_data_df %>%
select (1 : 26 ) -> df_USdeaths
library (hrbrthemes)
library (scales)
my_colors <- c ("#3E606F" )
my_font <- "Roboto Condensed"
my_cleanText1 <- function (x) {
str_replace_all (x, "[^A-Za-z]" , " " ) %>%
str_squish () %>%
return ()
}
df_USdeaths %>%
mutate (Rank = my_cleanText1 (Rank)) %>%
group_by (Rank) %>%
count () %>%
ungroup () %>%
top_n (20 , n) %>%
arrange (n) %>%
mutate (Rank = factor (Rank, levels = Rank)) %>%
mutate (label = comma_format ()(n)) -> deaths_byRank
deaths_byRank %>%
ggplot (aes (Rank, n)) +
geom_col (width = 0.8 , fill = "firebrick" , color = "firebrick" ) +
coord_flip () +
theme_ft_rc () +
scale_y_continuous (expand = c (0.015 , 0 )) +
theme (panel.grid = element_blank ()) +
theme (axis.text.x = element_blank ()) +
theme (axis.text.y = element_text (color = "white" , size = 14 , family = my_font)) +
theme (plot.margin = unit (c (1.2 , 1.2 , 1.2 , 1.2 ), "cm" )) +
geom_text (aes (label = label), hjust = -0.2 , color = "white" , size = 5 , family = my_font) +
geom_text (data = deaths_byRank %>% slice (which.max (n)), aes (label = label), hjust = 1.1 , color = "white" , size = 5 , family = my_font) +
theme (plot.title = element_text (size = 23 )) +
theme (plot.subtitle = element_text (size = 14 , color = "grey90" )) +
theme (plot.caption = element_text (size = 12 , face = "italic" )) +
labs (x = NULL , y = NULL ,
title = "Figure 1: US Fatal Deaths by Military Rank" ,
subtitle = "Note: For top 20 by number of deaths." ,
caption = "Data Source: http://www.virtualwall.org" )
US Fatal Deaths by Location
df_USdeaths %>%
mutate (location = my_cleanText1 (location)) %>%
mutate (location1 = case_when (str_detect (location, "North Vietnam" ) ~ paste0 ("X Province" , location),
str_detect (location, "Cambodia" ) ~ paste0 ("Cambodia Province" , location),
str_detect (location, "Laos" ) ~ paste0 ("Laos Province" , location),
str_detect (location, "Thailand" ) ~ paste0 ("Thailand Province" , location),
str_detect (location, "China" ) ~ paste0 ("China Province" , location),
str_detect (location, "not reported" ) ~ paste0 ("Unknown Province" , location),
TRUE ~ location)) -> df_USdeaths_location1
df_USdeaths_location1 %>%
filter (str_detect (location1, "Province" )) %>%
pull (location1) %>%
str_split ("Province" , simplify = TRUE ) %>%
as.data.frame () %>%
mutate_all (as.character) %>%
mutate_all (str_squish) %>%
rename (Province = V1) %>%
mutate (Province = case_when (str_detect (Province, "X" ) ~ "North Vietnam" , TRUE ~ Province)) %>%
group_by (Province) %>%
count () %>%
ungroup () %>%
arrange (n) %>%
mutate (Province = factor (Province, levels = Province)) %>%
mutate (bar_color = case_when (str_detect (Province, "North Vietnam" ) ~ my_colors,
str_detect (Province, "Laos" ) ~ my_colors,
str_detect (Province, "Cambodia" ) ~ my_colors,
str_detect (Province, "Thailand" ) ~ my_colors,
TRUE ~ "firebrick" )) %>%
mutate (label = comma_format ()(n)) -> df_death_byProvince
df_death_byProvince %>%
ggplot (aes (Province, n)) +
geom_col (width = 0.8 , fill = "firebrick" , color = "firebrick" ) +
coord_flip () +
theme_ft_rc () +
scale_y_continuous (expand = c (0.01 , 0 )) +
theme (panel.grid = element_blank ()) +
theme (axis.text.x = element_blank ()) +
theme (axis.text.y = element_text (color = "white" , size = 11 , family = my_font)) +
theme (plot.margin = unit (c (1.2 , 1.2 , 1.2 , 1.2 ), "cm" )) +
geom_text (data = df_death_byProvince %>% slice (1 : 45 ), aes (label = label), hjust = -0.2 , color = "white" , size = 3.5 , family = my_font) +
geom_text (data = df_death_byProvince %>% slice (46 : 48 ), aes (label = label), hjust = 1.1 , color = "white" , size = 3.5 , family = my_font) +
theme (plot.title = element_text (size = 23 )) +
theme (plot.subtitle = element_text (size = 14 , color = "grey90" )) +
theme (plot.caption = element_text (size = 12 , face = "italic" )) +
labs (x = NULL , y = NULL ,
title = "Figure 2: US Fatal Deaths by Location" ,
subtitle = "Note: Unverified Locations are labelled as Unknown." ,
caption = "Data Source: http://www.virtualwall.org" )
Reflections Of My Life
VIDEO
The changing
Of sunlight to moonlight
Reflections of my life
Oh how they fill my eyes
The greetings
Of people in trouble
Reflections of my life
Oh how they fill my eyes
All my sorrows
Sad tomorrows
Take me back to my own home
All my cryings
Feel I’m dying, dying
Take me back to my own home
I’m changing, arranging
I’m changing, I’m changing everything
Oh, everything around me
The world is a bad place
A bad place, a terrible place to live
Oh, but I don’t wanna die
All my sorrows
Sad tomorrows
Take me back to my own home
All my cryings
Feel I’m dying, dying
Take me back to my own home
All my sorrows
Sad tomorrows
Take me back to my own home
All my cryings…
To Be Continued
LS0tDQp0aXRsZTogIlVTIE1pbGl0YXJ5IEZhdGFsIENhc3VhbHRpZXMgRHVyaW5nIHRoZSBWaWV0bmFtIFdhciINCnN1YnRpdGxlOiAiRGFpbHkgR3JhcGggU2VyaWVzIg0KYXV0aG9yOiAiTmd1eWVuIENoaSBEdW5nIg0Kb3V0cHV0Og0KICBodG1sX2RvY3VtZW50Og0KICAgIGNvZGVfZG93bmxvYWQ6IHllcw0KICAgIGNvZGVfZm9sZGluZzogaGlkZQ0KICAgIGhpZ2hsaWdodDogemVuYnVybg0KICAgIHRoZW1lOiBmbGF0bHkNCiAgICB0b2M6IHllcw0KICAgIHRvY19mbG9hdDogeWVzDQogIHdvcmRfZG9jdW1lbnQ6DQogICAgdG9jOiB5ZXMNCi0tLQ0KDQpgYGB7ciBzZXR1cCxpbmNsdWRlPUZBTFNFfQ0Ka25pdHI6Om9wdHNfY2h1bmskc2V0KGVjaG8gPSBUUlVFLCB3YXJuaW5nID0gRkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgZmlnLnJldGluYT0yKQ0KYGBgDQoNCg0KIVtdKEM6XFxVc2Vyc1xcWmJvb2tcXERlc2t0b3BcXHBpY1xcd2FyMTEuanBnKQ0KDQojIFZpZXRuYW0gV2FyIENhc3VhbHRpZXMNCg0KDQpFc3RpbWF0ZXMgb2YgY2FzdWFsdGllcyBvZiB0aGUgVmlldG5hbSBXYXIgdmFyeSB3aWRlbHkuIEVzdGltYXRlcyBpbmNsdWRlIGJvdGggY2l2aWxpYW4gYW5kIG1pbGl0YXJ5IGRlYXRocyBpbiBOb3J0aCBhbmQgU291dGggVmlldG5hbSwgTGFvcywgYW5kIENhbWJvZGlhLg0KDQpUaGUgd2FyIHBlcnNpc3RlZCBmcm9tIDE5NTUgdG8gMTk3NSBhbmQgbW9zdCBvZiB0aGUgZmlnaHRpbmcgdG9vayBwbGFjZSBpbiBTb3V0aCBWaWV0bmFtOyBhY2NvcmRpbmdseSBpdCBzdWZmZXJlZCB0aGUgbW9zdCBjYXN1YWx0aWVzLiBUaGUgd2FyIGFsc28gc3BpbGxlZCBvdmVyIGludG8gdGhlIG5laWdoYm9yaW5nIGNvdW50cmllcyBvZiBDYW1ib2RpYSBhbmQgTGFvcyB3aGljaCBhbHNvIGVuZHVyZWQgY2FzdWFsdGllcyBmcm9tIGFlcmlhbCBhbmQgZ3JvdW5kIGZpZ2h0aW5nLg0KDQpDaXZpbGlhbiBkZWF0aHMgY2F1c2VkIGJ5IGJvdGggc2lkZXMgYW1vdW50ZWQgdG8gYSBzaWduaWZpY2FudCBwZXJjZW50YWdlIG9mIHRvdGFsIGRlYXRocy4gQ2l2aWxpYW4gZGVhdGhzIHdlcmUgcGFydGx5IGNhdXNlZCBieSBhc3Nhc3NpbmF0aW9ucywgbWFzc2FjcmVzIGFuZCB0ZXJyb3IgdGFjdGljcy4gQ2l2aWxpYW4gZGVhdGhzIHdlcmUgYWxzbyBjYXVzZWQgYnkgbW9ydGFyIGFuZCBhcnRpbGxlcnksIGV4dGVuc2l2ZSBhZXJpYWwgYm9tYmluZyBhbmQgdGhlIHVzZSBvZiBmaXJlcG93ZXIgaW4gbWlsaXRhcnkgb3BlcmF0aW9ucyBjb25kdWN0ZWQgaW4gaGVhdmlseSBwb3B1bGF0ZWQgYXJlYXMuIFNvbWUgMzY1LDAwMCBWaWV0bmFtZXNlIGNpdmlsaWFucyBhcmUgZXN0aW1hdGVkIGJ5IG9uZSBzb3VyY2UgdG8gaGF2ZSBkaWVkIGFzIGEgcmVzdWx0IG9mIHRoZSB3YXIgZHVyaW5nIHRoZSBwZXJpb2Qgb2YgQW1lcmljYW4gaW52b2x2ZW1lbnQuDQoNCkEgbnVtYmVyIG9mIGluY2lkZW50cyBvY2N1cnJlZCBkdXJpbmcgdGhlIHdhciBpbiB3aGljaCBjaXZpbGlhbnMgd2VyZSBkZWxpYmVyYXRlbHkgdGFyZ2V0ZWQgb3Iga2lsbGVkLiBUaGUgYmVzdC1rbm93biBhcmUgdGhlIE1hc3NhY3JlIGF0IEh14bq/IGFuZCB0aGUgTXkgTGFpIG1hc3NhY3JlLg0KDQpBY2NvcmRpbmcgdG8gW1RoZSBWaXJ0dWFsIFdhbGwgVmlldG5hbSBWZXRlcmFucyBNZW1vcmlhbF0oaHR0cDovL3d3dy52aXJ0dWFsd2FsbC5vcmcvKSwgdGhlIG51bWJlciBvZiBVLlMgY2FzdWFsdGllcyBkdXJpbmcgVmlldG5hbSBXYXIgd2FzIDU4LDIyNi4gDQoNCiMgQ29sbGVjdGluZyBEYXRhIGZvciA1OCwyMjYgVVMgRGVhdGhzDQoNCkluIHRoaXMgc2VjdGlvbiBJIHByZXNlbnQgUiBjb2RlcyBmb3IgY29sbGVjdGluZyBkZXRhaWxlZCBkYXRhIChmaXJzdCBuYW1lLCBsYXN0IG5hbWUsIGdlbmRlciwgZGVhdGggZGF0ZSwgY2F0ZWdvcnksIGJpcnRoIGRhdGUsIHNlcnZpY2UgbnVtYmVyLCByYW5rLCBkZWF0aCBsb2NhdGlvbiwgYW5kIG90aGVyIGluZm9ybWF0aW9uKSBmb3IgNTgsMjI2IFVTIERlYXRocyBkdXJpbmcgVmlldG5hbSBXYXIuIA0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCg0KIyBodHRwczovL3d3dy5ob25vcnN0YXRlcy5vcmcvaW5kZXgucGhwP3BhZ2U9d2FycyZ3YXI9VmlldG5hbStDb25mbGljdCZkbz1zdGF0ZXMNCiMgaHR0cHM6Ly9sYWFoZ3AuZ2VuZWFsb2d5dmlsbGFnZS5jb20vTWlsaXRhcnlJbmRleC92aWV0bmFtLXdhci1jYXVzYWxpdGllcy5odG1sDQojIGh0dHBzOi8vd3d3LmpzdG9yLm9yZy9zdGFibGUvMjEzNzc3ND9zZXE9MSNwYWdlX3NjYW5fdGFiX2NvbnRlbnRzDQojIGh0dHBzOi8vd3d3Lm53aXRpbWVzLmNvbS90aGUtcmVnaW9uLWZhbGxlbi1vZi10aGUtdmlldG5hbS13YXIvdGFibGVfMWY3ZmRlOTMtYTE4My01ZjFjLWFlNjktY2NhYzRmZGViYjVlLmh0bWwNCiMgaHR0cDovL3d3dy52aWV0bmFtbWVtb3JpYWwuY29tL3ZpZXRuYW0tbWVtb3JpYWwtbGlzdC1vZi1oZXJvZXMuaHRtbA0KIyBLb3JlYW4gaHR0cHM6Ly93d3cudnZtZi5vcmcvV2FsbC1vZi1GYWNlcy8/ZmJjbGlkPUl3QVIzSkppOGZQa2xSNVF0ZlJIR2ZOMG94YURqZjR1dUhtSEZEeHVsWXFJQ1MxYUJ1empKSXJFbUtJcXMNCg0KDQojIExvYWQgc29tZSBSIHBhY2thZ2VzIGFuZCBjbGVhciB3b3Jrc3BhY2U6DQoNCnJtKGxpc3QgPSBscygpKQ0KbGlicmFyeShydmVzdCkNCmxpYnJhcnkoeG1sMikNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQojICAgIFN0YWdlIDE6ICBHZXQgbGlua3MgZm9yIGFsbCBzb2xkaWVycw0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQoNCmdldF9wYW5lbF9saW5rIDwtIGZ1bmN0aW9uKHVybCkgew0KICANCiAgIyBDcmVhdGUgYW4gaHRtbCBkb2N1bWVudCBmcm9tIHRoZSB1cmw6IA0KICB3ZWJwYWdlIDwtIHhtbDI6OnJlYWRfaHRtbCh1cmwpDQogIA0KICAjIEV4dHJhY3QgdGhlIFVSTHM6IA0KICB1cmxfIDwtIHdlYnBhZ2UgJT4lDQogICAgcnZlc3Q6Omh0bWxfbm9kZXMoImEiKSAlPiUNCiAgICBydmVzdDo6aHRtbF9hdHRyKCJocmVmIikNCiAgDQogICMgRXh0cmFjdCB0aGUgbGluayB0ZXh0OiANCiAgbGlua18gPC0gd2VicGFnZSAlPiUNCiAgICBydmVzdDo6aHRtbF9ub2RlcygiYSIpICU+JQ0KICAgIHJ2ZXN0OjpodG1sX3RleHQoKQ0KICByZXR1cm4oZGF0YV9mcmFtZShsaW5rID0gbGlua18sIHVybCA9IHVybF8pKQ0KfQ0KDQoNCmFsbF9wYW5lbHMgPC0gImh0dHA6Ly93d3cudmlydHVhbHdhbGwub3JnL2lQYW5lbHMuaHRtIg0KcGFuZWxfbGlua3MgPC0gZ2V0X3BhbmVsX2xpbmsoYWxsX3BhbmVscykNCg0KDQojIEFsbCBzdWZmaXhlczogDQoNCmFsbF9zdWZmaXggPC0gcGFuZWxfbGlua3MkdXJsW3N0cl9kZXRlY3QocGFuZWxfbGlua3MkdXJsLCAiaVBhbmVscy9pcGFuIildICU+JSBuYS5vbWl0KCkNCmFsbF9zdWZmaXggPC0gc3RyX3N1YihhbGxfc3VmZml4LCBzdGFydCA9IDIsIGVuZCA9IHN0cl9jb3VudChhbGxfc3VmZml4KSkNCmFsbF9uYW1lc19JblBhbmVsIDwtIHBhc3RlMCgiaHR0cDovL3d3dy52aXJ0dWFsd2FsbC5vcmciLCBhbGxfc3VmZml4KQ0KDQoNCiMgQWxsIHNvbGRpZXIgbGlua3M6IA0KDQpnZXRfbGlua19mb3Jfc29sZGllcnMgPC0gZnVuY3Rpb24ocGFuZWxfc2VsZWN0ZWQpIHsNCiAgDQogIHNvbGRpZXJfc3VmZml4IDwtIGdldF9wYW5lbF9saW5rKHBhbmVsX3NlbGVjdGVkKQ0KICANCiAgc29sZGllcl9zdWZmaXggJT4lIA0KICAgIGZpbHRlcighc3RyX2RldGVjdCh1cmwsICJtaXNzcGVsbGVkbmFtZSIpKSAlPiUgDQogICAgZmlsdGVyKCFzdHJfZGV0ZWN0KHVybCwgIm5vc2NyaXB0SW5kZXhNZW51IikpICU+JSANCiAgICBmaWx0ZXIoIXN0cl9kZXRlY3QodXJsLCAiaW5kZXgiKSkgJT4lIA0KICAgIGZpbHRlcighc3RyX2RldGVjdCh1cmwsICJpcGFuIikpICU+JSANCiAgICBtdXRhdGUodXJsID0gcGFzdGUwKCJodHRwOi8vd3d3LlZpcnR1YWxXYWxsLm9yZyIsIHN0cl9zdWIodXJsLCBzdGFydCA9IDMsIGVuZCA9IHN0cl9jb3VudCh1cmwpKSkpICU+JSANCiAgICByZW5hbWUobmFtZSA9IGxpbmssIGxpbmtfZm9yX3NvbGRpZXIgPSB1cmwpICU+JSANCiAgICByZXR1cm4oKQ0KICANCn0NCg0KDQpsYXBwbHkoYWxsX25hbWVzX0luUGFuZWwsIGdldF9saW5rX2Zvcl9zb2xkaWVycykgLT4gbGlua19zb2xkaWVyc19saXN0DQpkby5jYWxsKCJiaW5kX3Jvd3MiLCBsaW5rX3NvbGRpZXJzX2xpc3QpIC0+IGRmX2xpbmtfc29sZGllcnMNCg0KZGZfbGlua19zb2xkaWVycyAlPiUgDQogIGZpbHRlcighZHVwbGljYXRlZChsaW5rX2Zvcl9zb2xkaWVyKSkgLT4gZGZfbGlua19zb2xkaWVycw0KDQoNCiMgU2F2ZSBvdXIgZGF0YTogDQoNCndyaXRlLmNzdihkZl9saW5rX3NvbGRpZXJzLCAiZGZfbGlua19zb2xkaWVycy5jc3YiLCByb3cubmFtZXMgPSBGQUxTRSkNCg0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KIyAgICBTdGFnZSAyOiAgR2V0IGRhdGEgZm9yIGFsbCBzb2xkaWVycw0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PQ0KDQojIEZ1bmN0aW9uIGZvciBjb2xsZWN0aW5nIGFsbCBmcm9tIGEgc29sZGllcjogDQoNCmNvbGxlY3RfYWxsX0RhdGFTb2xkaWVyIDwtIGZ1bmN0aW9uKG15X2xpbmspIHsNCiAgDQogIHBnIDwtIHJlYWRfaHRtbChteV9saW5rKQ0KICANCiAgaHRtbF90ZXh0KHBnLCB0cmltID0gVFJVRSkgJT4lIA0KICAgIHN0cl9zcGxpdCgiXFxcbiIsIHNpbXBsaWZ5ID0gVFJVRSkgJT4lIA0KICAgIGFzLmNoYXJhY3RlcigpICU+JSANCiAgICBzdHJfc3F1aXNoKCkgJT4lIA0KICAgIC5bMzoyN10gLT4gbQ0KICANCiAgDQogIG0gJT4lIA0KICAgIHN0cl9zcGxpdCgiXFwvIiwgc2ltcGxpZnkgPSBUUlVFKSAlPiUgDQogICAgZGF0YS5mcmFtZSgpICU+JSANCiAgICBtdXRhdGVfYWxsKGFzLmNoYXJhY3RlcikgLT4gZGYNCiAgDQogIA0KICBkZl9kYXRlIDwtIGRmICU+JSANCiAgICBzbGljZShjKDE3OjE5KSkgJT4lIA0KICAgIG11dGF0ZShteV9kYXRlID0gcGFzdGUwKFgxLCBYMiwgWDMpKSAlPiUgDQogICAgc2VsZWN0KG15X2RhdGUsIFg1KQ0KICANCiAgdChkZl9kYXRlICU+JSBzZWxlY3QobXlfZGF0ZSkpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKCkgLT4gZGZfZGF0ZV9zb2xkaWVyDQogIA0KICBuYW1lcyhkZl9kYXRlX3NvbGRpZXIpIDwtIGMoImJpcnRoIiwgInN0YXJ0IiwgImNhc19kYXRlIikNCiAgDQoNCiAgZGZfcmVtYWluIDwtIGRmICU+JSANCiAgICBzbGljZSgtYygxNzoxOSkpICU+JSANCiAgICBzZWxlY3QoWDEsIFgzKQ0KICANCiAgdChkZl9yZW1haW4gJT4lIHNlbGVjdChYMSkpICU+JSANCiAgICBhcy5kYXRhLmZyYW1lKCkgLT4gZGYNCiAgDQogIA0KICBuYW1lcyhkZikgPC0gYyhkZl9yZW1haW4kWDNbMToyXSwgIm5vdEtub3duIiwgIkdyYWRlX2F0X2xvc3MiLCBkZl9yZW1haW4kWDNbNToyMl0pICAgDQogIGFsbF9kYXRhX3NvbGRpZXIgPC0gYmluZF9jb2xzKGRmLCBkZl9kYXRlX3NvbGRpZXIpDQogIHJldHVybihhbGxfZGF0YV9zb2xkaWVyICU+JSBtdXRhdGUobGluayA9IG15X2xpbmspKQ0KICANCn0NCg0KZ2V0X1NvbGRpZXJEYXRhIDwtIGZ1bmN0aW9uKGxpbmtfc2VsZWN0ZWQpIHsNCiAgcmV0dXJuKHRyeUNhdGNoKGNvbGxlY3RfYWxsX0RhdGFTb2xkaWVyKGxpbmtfc2VsZWN0ZWQpLCBlcnJvciA9IGZ1bmN0aW9uKGUpIHtOVUxMfSkpDQp9DQoNCg0KIyBVc2UgdGhpcyBmdW5jdGlvbjogDQoNCmRmX2xpbmtfc29sZGllcnMgPC0gcmVhZF9jc3YoImRmX2xpbmtfc29sZGllcnMuY3N2IikNCnNvbGRpZXJfbGlua3MgPC0gZGZfbGlua19zb2xkaWVycyRsaW5rX2Zvcl9zb2xkaWVyDQpsYXBwbHkoc29sZGllcl9saW5rcywgZ2V0X1NvbGRpZXJEYXRhKSAtPiBhbGxfZGF0YV9saXN0DQpzYXZlKGFsbF9kYXRhX2xpc3QsIGZpbGUgPSAiYWxsX2RhdGFfbGlzdC5SRGF0YSIpDQoNCmRvLmNhbGwoImJpbmRfcm93cyIsIGFsbF9kYXRhX2xpc3QpICU+JSANCiAgc2VsZWN0KC1WMSkgLT4gYWxsX2RhdGFfZGYNCg0KIyBTYXZlIG91ciBkYXRhOiANCndyaXRlLmNzdihhbGxfZGF0YV9kZiwgImFsbF91c19kZWF0aHNfaW5fVmlldG5hbV93YXIuY3N2Iiwgcm93Lm5hbWVzID0gRkFMU0UpDQpgYGANCg0KIyBVUyBGYXRhbCBEZWF0aHMgYnkgTWlsaXRhcnkgUmFuaw0KDQohW10oQzpcXFVzZXJzXFxaYm9va1xcRGVza3RvcFxccGljXFx3MS5qcGcpDQoNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQojPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT0NCiMgIFN0YWdlIDM6IERhdGEtcHJlcHJvY2Vzc2luZyBhbmQgdmlzdWFsaXphdGlvbg0KIz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09DQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KDQojIEltcG9ydCBkYXRhOiANCmFsbF9kYXRhX2RmIDwtIHJlYWRfY3N2KCJDOlxcVXNlcnNcXFpib29rXFxEb2N1bWVudHNcXGFsbF91c19kZWF0aHNfaW5fVmlldG5hbV93YXIuY3N2IikNCg0KYWxsX2RhdGFfZGYgJT4lIA0KICBzZWxlY3QoMToyNikgLT4gZGZfVVNkZWF0aHMNCg0KDQpsaWJyYXJ5KGhyYnJ0aGVtZXMpDQpsaWJyYXJ5KHNjYWxlcykNCm15X2NvbG9ycyA8LSBjKCIjM0U2MDZGIikNCm15X2ZvbnQgPC0gIlJvYm90byBDb25kZW5zZWQiDQoNCg0KbXlfY2xlYW5UZXh0MSA8LSBmdW5jdGlvbih4KSB7DQogIHN0cl9yZXBsYWNlX2FsbCh4LCAiW15BLVphLXpdIiwgIiAiKSAlPiUgDQogICAgc3RyX3NxdWlzaCgpICU+JSANCiAgICByZXR1cm4oKQ0KfQ0KDQoNCg0KZGZfVVNkZWF0aHMgJT4lIA0KICBtdXRhdGUoUmFuayA9IG15X2NsZWFuVGV4dDEoUmFuaykpICU+JSANCiAgZ3JvdXBfYnkoUmFuaykgJT4lIA0KICBjb3VudCgpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgdG9wX24oMjAsIG4pICU+JSANCiAgYXJyYW5nZShuKSAlPiUgDQogIG11dGF0ZShSYW5rID0gZmFjdG9yKFJhbmssIGxldmVscyA9IFJhbmspKSAlPiUgDQogIG11dGF0ZShsYWJlbCA9IGNvbW1hX2Zvcm1hdCgpKG4pKSAtPiBkZWF0aHNfYnlSYW5rDQoNCmRlYXRoc19ieVJhbmsgJT4lIA0KICBnZ3Bsb3QoYWVzKFJhbmssIG4pKSArIA0KICBnZW9tX2NvbCh3aWR0aCA9IDAuOCwgZmlsbCA9ICJmaXJlYnJpY2siLCBjb2xvciA9ICJmaXJlYnJpY2siKSArIA0KICBjb29yZF9mbGlwKCkgKyANCiAgdGhlbWVfZnRfcmMoKSArIA0KICBzY2FsZV95X2NvbnRpbnVvdXMoZXhwYW5kID0gYygwLjAxNSwgMCkpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxNCwgZmFtaWx5ID0gbXlfZm9udCkpICsgDQogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDEuMiwgMS4yLCAxLjIsIDEuMiksICJjbSIpKSArIA0KICBnZW9tX3RleHQoYWVzKGxhYmVsID0gbGFiZWwpLCBoanVzdCA9IC0wLjIsIGNvbG9yID0gIndoaXRlIiwgc2l6ZSA9IDUsIGZhbWlseSA9IG15X2ZvbnQpICsgDQogIGdlb21fdGV4dChkYXRhID0gZGVhdGhzX2J5UmFuayAlPiUgc2xpY2Uod2hpY2gubWF4KG4pKSwgYWVzKGxhYmVsID0gbGFiZWwpLCBoanVzdCA9IDEuMSwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gNSwgZmFtaWx5ID0gbXlfZm9udCkgKyANCiAgdGhlbWUocGxvdC50aXRsZSA9IGVsZW1lbnRfdGV4dChzaXplID0gMjMpKSArIA0KICB0aGVtZShwbG90LnN1YnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAxNCwgY29sb3IgPSAiZ3JleTkwIikpICsgDQogIHRoZW1lKHBsb3QuY2FwdGlvbiA9IGVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhY2UgPSAiaXRhbGljIikpICsgDQogIGxhYnMoeCA9IE5VTEwsIHkgPSBOVUxMLCANCiAgICAgICB0aXRsZSA9ICJGaWd1cmUgMTogVVMgRmF0YWwgRGVhdGhzIGJ5IE1pbGl0YXJ5IFJhbmsiLCANCiAgICAgICBzdWJ0aXRsZSA9ICJOb3RlOiBGb3IgdG9wIDIwIGJ5IG51bWJlciBvZiBkZWF0aHMuIiwgDQogICAgICAgY2FwdGlvbiA9ICJEYXRhIFNvdXJjZTogaHR0cDovL3d3dy52aXJ0dWFsd2FsbC5vcmciKQ0KDQoNCmBgYA0KDQojIFVTIEZhdGFsIERlYXRocyBieSBMb2NhdGlvbg0KDQohW10oQzpcXFVzZXJzXFxaYm9va1xcRGVza3RvcFxccGljXFx3Mi5qcGcpDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KZGZfVVNkZWF0aHMgJT4lIA0KICBtdXRhdGUobG9jYXRpb24gPSBteV9jbGVhblRleHQxKGxvY2F0aW9uKSkgJT4lIA0KICBtdXRhdGUobG9jYXRpb24xID0gY2FzZV93aGVuKHN0cl9kZXRlY3QobG9jYXRpb24sICJOb3J0aCBWaWV0bmFtIikgfiBwYXN0ZTAoIlggUHJvdmluY2UiLCBsb2NhdGlvbiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QobG9jYXRpb24sICJDYW1ib2RpYSIpIH4gcGFzdGUwKCJDYW1ib2RpYSBQcm92aW5jZSIsIGxvY2F0aW9uKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChsb2NhdGlvbiwgIkxhb3MiKSB+IHBhc3RlMCgiTGFvcyBQcm92aW5jZSIsIGxvY2F0aW9uKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChsb2NhdGlvbiwgIlRoYWlsYW5kIikgfiBwYXN0ZTAoIlRoYWlsYW5kIFByb3ZpbmNlIiwgbG9jYXRpb24pLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KGxvY2F0aW9uLCAiQ2hpbmEiKSB+IHBhc3RlMCgiQ2hpbmEgUHJvdmluY2UiLCBsb2NhdGlvbiksIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9kZXRlY3QobG9jYXRpb24sICJub3QgcmVwb3J0ZWQiKSB+IHBhc3RlMCgiVW5rbm93biBQcm92aW5jZSIsIGxvY2F0aW9uKSwgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVFJVRSB+IGxvY2F0aW9uKSkgLT4gZGZfVVNkZWF0aHNfbG9jYXRpb24xDQoNCg0KZGZfVVNkZWF0aHNfbG9jYXRpb24xICU+JSANCiAgZmlsdGVyKHN0cl9kZXRlY3QobG9jYXRpb24xLCAiUHJvdmluY2UiKSkgJT4lIA0KICBwdWxsKGxvY2F0aW9uMSkgJT4lIA0KICBzdHJfc3BsaXQoIlByb3ZpbmNlIiwgc2ltcGxpZnkgPSBUUlVFKSAlPiUgDQogIGFzLmRhdGEuZnJhbWUoKSAlPiUgDQogIG11dGF0ZV9hbGwoYXMuY2hhcmFjdGVyKSAlPiUgDQogIG11dGF0ZV9hbGwoc3RyX3NxdWlzaCkgJT4lIA0KICByZW5hbWUoUHJvdmluY2UgPSBWMSkgJT4lIA0KICBtdXRhdGUoUHJvdmluY2UgPSBjYXNlX3doZW4oc3RyX2RldGVjdChQcm92aW5jZSwgIlgiKSB+ICJOb3J0aCBWaWV0bmFtIiwgVFJVRSB+IFByb3ZpbmNlKSkgJT4lIA0KICBncm91cF9ieShQcm92aW5jZSkgJT4lIA0KICBjb3VudCgpICU+JSANCiAgdW5ncm91cCgpICU+JSANCiAgYXJyYW5nZShuKSAlPiUgDQogIG11dGF0ZShQcm92aW5jZSA9IGZhY3RvcihQcm92aW5jZSwgbGV2ZWxzID0gUHJvdmluY2UpKSAlPiUgDQogIG11dGF0ZShiYXJfY29sb3IgPSBjYXNlX3doZW4oc3RyX2RldGVjdChQcm92aW5jZSwgIk5vcnRoIFZpZXRuYW0iKSB+IG15X2NvbG9ycywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChQcm92aW5jZSwgIkxhb3MiKSB+IG15X2NvbG9ycywNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfZGV0ZWN0KFByb3ZpbmNlLCAiQ2FtYm9kaWEiKSB+IG15X2NvbG9ycywgDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX2RldGVjdChQcm92aW5jZSwgIlRoYWlsYW5kIikgfiBteV9jb2xvcnMsIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFRSVUUgfiAiZmlyZWJyaWNrIikpICU+JSANCiAgbXV0YXRlKGxhYmVsID0gY29tbWFfZm9ybWF0KCkobikpIC0+IGRmX2RlYXRoX2J5UHJvdmluY2UNCg0KDQoNCmRmX2RlYXRoX2J5UHJvdmluY2UgJT4lIA0KICBnZ3Bsb3QoYWVzKFByb3ZpbmNlLCBuKSkgKyANCiAgZ2VvbV9jb2wod2lkdGggPSAwLjgsIGZpbGwgPSAiZmlyZWJyaWNrIiwgY29sb3IgPSAiZmlyZWJyaWNrIikgKyANCiAgY29vcmRfZmxpcCgpICsgDQogIHRoZW1lX2Z0X3JjKCkgKyANCiAgc2NhbGVfeV9jb250aW51b3VzKGV4cGFuZCA9IGMoMC4wMSwgMCkpICsgDQogIHRoZW1lKHBhbmVsLmdyaWQgPSBlbGVtZW50X2JsYW5rKCkpICsgDQogIHRoZW1lKGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKSArIA0KICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfdGV4dChjb2xvciA9ICJ3aGl0ZSIsIHNpemUgPSAxMSwgZmFtaWx5ID0gbXlfZm9udCkpICsgDQogIHRoZW1lKHBsb3QubWFyZ2luID0gdW5pdChjKDEuMiwgMS4yLCAxLjIsIDEuMiksICJjbSIpKSArIA0KICBnZW9tX3RleHQoZGF0YSA9IGRmX2RlYXRoX2J5UHJvdmluY2UgJT4lIHNsaWNlKDE6NDUpLCBhZXMobGFiZWwgPSBsYWJlbCksIGhqdXN0ID0gLTAuMiwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMy41LCBmYW1pbHkgPSBteV9mb250KSArIA0KICBnZW9tX3RleHQoZGF0YSA9IGRmX2RlYXRoX2J5UHJvdmluY2UgJT4lIHNsaWNlKDQ2OjQ4KSwgYWVzKGxhYmVsID0gbGFiZWwpLCBoanVzdCA9IDEuMSwgY29sb3IgPSAid2hpdGUiLCBzaXplID0gMy41LCBmYW1pbHkgPSBteV9mb250KSArIA0KICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KHNpemUgPSAyMykpICsgDQogIHRoZW1lKHBsb3Quc3VidGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE0LCBjb2xvciA9ICJncmV5OTAiKSkgKyANCiAgdGhlbWUocGxvdC5jYXB0aW9uID0gZWxlbWVudF90ZXh0KHNpemUgPSAxMiwgZmFjZSA9ICJpdGFsaWMiKSkgKyANCiAgbGFicyh4ID0gTlVMTCwgeSA9IE5VTEwsIA0KICAgICAgIHRpdGxlID0gIkZpZ3VyZSAyOiBVUyBGYXRhbCBEZWF0aHMgYnkgTG9jYXRpb24iLCANCiAgICAgICBzdWJ0aXRsZSA9ICJOb3RlOiBVbnZlcmlmaWVkIExvY2F0aW9ucyBhcmUgbGFiZWxsZWQgYXMgVW5rbm93bi4iLCANCiAgICAgICBjYXB0aW9uID0gIkRhdGEgU291cmNlOiBodHRwOi8vd3d3LnZpcnR1YWx3YWxsLm9yZyIpDQoNCg0KYGBgDQoNCiMgUmVmbGVjdGlvbnMgT2YgTXkgTGlmZQ0KDQpgYGB7ciwgZWNobz1GQUxTRX0NCmxpYnJhcnkodmVtYmVkcikNCmVtYmVkX3VybCgiaHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj1fMWxJQU5SSk5iQSIpDQpgYGANCg0KVGhlIGNoYW5naW5nDQoNCk9mIHN1bmxpZ2h0IHRvIG1vb25saWdodA0KDQpSZWZsZWN0aW9ucyBvZiBteSBsaWZlDQoNCk9oIGhvdyB0aGV5IGZpbGwgbXkgZXllcw0KDQpUaGUgZ3JlZXRpbmdzDQoNCk9mIHBlb3BsZSBpbiB0cm91YmxlDQoNClJlZmxlY3Rpb25zIG9mIG15IGxpZmUNCg0KT2ggaG93IHRoZXkgZmlsbCBteSBleWVzDQoNCkFsbCBteSBzb3Jyb3dzDQoNClNhZCB0b21vcnJvd3MNCg0KVGFrZSBtZSBiYWNrIHRvIG15IG93biBob21lDQoNCkFsbCBteSBjcnlpbmdzDQoNCkZlZWwgSSdtIGR5aW5nLCBkeWluZw0KDQpUYWtlIG1lIGJhY2sgdG8gbXkgb3duIGhvbWUNCg0KSSdtIGNoYW5naW5nLCBhcnJhbmdpbmcNCg0KSSdtIGNoYW5naW5nLCBJJ20gY2hhbmdpbmcgZXZlcnl0aGluZw0KDQpPaCwgZXZlcnl0aGluZyBhcm91bmQgbWUNCg0KVGhlIHdvcmxkIGlzIGEgYmFkIHBsYWNlDQoNCkEgYmFkIHBsYWNlLCBhIHRlcnJpYmxlIHBsYWNlIHRvIGxpdmUNCg0KT2gsIGJ1dCBJIGRvbid0IHdhbm5hIGRpZQ0KDQpBbGwgbXkgc29ycm93cw0KDQpTYWQgdG9tb3Jyb3dzDQoNClRha2UgbWUgYmFjayB0byBteSBvd24gaG9tZQ0KDQpBbGwgbXkgY3J5aW5ncw0KDQpGZWVsIEknbSBkeWluZywgZHlpbmcNCg0KVGFrZSBtZSBiYWNrIHRvIG15IG93biBob21lDQoNCkFsbCBteSBzb3Jyb3dzDQoNClNhZCB0b21vcnJvd3MNCg0KVGFrZSBtZSBiYWNrIHRvIG15IG93biBob21lDQoNCkFsbCBteSBjcnlpbmdzLi4uDQoNCiMgVG8gQmUgQ29udGludWVkDQoNCg0K