This is an R Markdown
Notebook with some plots and analysis of Bishop, California Police
Department Flock Data. This format is intended to allow others to
reproduce and modify. It walks through all the steps. Code and plots are
included.
Obviously, R is required.
First, load some prerequisite libraries.
# Required libraries
library(tidyverse)
library(forcats)
library(lubridate)
library(scales)
Data import
Now import data files. This uses the public record request data
obtained by Robert on June 2 2026. These records cover 2025-03-21
through 2026-05-13. For this code to run, it is assumed that they are
unzipped to the same directory as this file.
The data is in csv format, and there are 3 kinds of files:
- Shared Networks file: This contains info on the
organizations that Bishop PD has data sharing agreements with.
- Audit files: These contain records of searches performed by
Bishop PD.
- Network Audit files: These contain records of searches
performed by other organizations that included Bishop’s Flock
cameras.
The Audit and Network Audit files will be read in
together and combined into a single dataframe. Bishop PD and external
organizations are distinguished by the Org Name field. This
will produce the flock_audit dataframe. Dates and names are
cleaned for easier processing.
The Shared Networks file is read into a separate dataframe.
There are external networks represented in the Network Audit
files that are not in this file, so that information is joined into this
dataframe, called shared_networks.
# Read/combine audit files
list.files(path = "./Flock Audit FOIA data-20260602T021221Z-3-001/Flock Audit FOIA data/",
pattern = "\\-Audit.csv",
full.names = TRUE) |>
map_df(~read_csv(., col_types = cols(.default = "c"))) ->
flock_audit
# Data Cleaning
flock_audit |>
mutate(Reason = stringr::str_to_title(Reason)) |>
mutate(Name = stringr::str_to_title(Name)) |>
mutate(dt = str_remove(`Search Time`, " UTC")) |>
mutate(dt = parse_date_time(dt, "%m/%d/%Y, %I:%M:%S %p", tz = "UTC")) |>
mutate(Date = as_date(dt)) ->
flock_audit
# Read network files
list.files(path = "./Flock Audit FOIA data-20260602T021221Z-3-001/Flock Audit FOIA data/",
pattern = "\\SharedNetworks.*csv",
full.names = TRUE) |>
map_df(~read_csv(., col_types = cols(.default = "c"))) |>
mutate(`Org Name` = `Organization Name`)->
shared_networks
# Combine network info from audit and network files
flock_audit |>
group_by(`Org Name`) |>
summarize(n = n()) |>
full_join(shared_networks, by = c("Org Name")) ->
shared_networks
Flock Audit Example data:
# Preview flock audit data:
flock_audit |> slice_sample(n =10)
Shared Networks Example data:
shared_networks |> slice_sample(n = 10)
Shared Network Stats:
Let’s take a look at which agencies are requesting data. Here are the
top 20:
ggplot(flock_audit,
aes(y=fct_rev(fct_lump_n(fct_infreq(`Org Name`), 20)))) +
geom_bar() +
ylab("Organization") +
xlab("Search Requests") +
ggtitle("Top Requesting Agencies for Bishop Flock Cameras")

Where does Bishop PD sit on this list? The 226th most frequent
user.
shared_networks |>
arrange(desc(n)) |>
mutate(rank = row_number()) |>
select(rank, everything()) |>
slice(220:230)
leaflet.extras::addFullscreenControl()What are the top Reasons given
for the searches? Note that this is messy, because the Reason
field is not standardized. One interesting thing to note is the
prevalance of very generic, uninformative reasons like
“Investigation”.
flock_audit |>
ggplot() +
geom_bar(aes(y = fct_rev(fct_lump_n(fct_infreq(Reason), 20)))) +
ylab("Request Reason") +
xlab("Search Requests") +
scale_x_continuous(limits = c(0,200000), oob = scales::oob_keep) +
ggtitle("Top 20 Search Reasons for Bishop Flock Cameras")

It is interesting to note that the use of some of the very generic
reasons like “Investigation” or “Inv” sharply dropped off in 2026. Was
there an change in policy?
flock_audit |>
mutate(Reason = fct_collapse(Reason,
Investigation = c("Investigation", "Inv", "Invest", "Other - Investigation"),
)) |>
mutate(Generic = str_equal(Reason, "Investigation")) |>
#slice_sample(n = 10000) |>
ggplot(aes(x = Date, after_stat(count), fill = Generic)) +
geom_density(position = "stack") +
ggtitle("Generic Investigation Searches")

If we look at only Bishop PD searches, we can manually collapse this
messy Reason field and get a better sense of the types of
Reasons these cameras are used. Note that Bishop PD’s use differs from
that of external organizations.
flock_audit |>
mutate(Date = as_date(dt)) |>
filter(`Org Name` == "Bishop CA PD") |>
mutate(`Reason Type` = fct_collapse(Reason,
`Vehicle Theft` = c(str_subset(Reason, "Vehicle Theft"),
str_subset(Reason, "Stolen Vehicle"),
str_subset(Reason, "10851")),
`Hit and Run` = c(str_subset(Reason, "Hit")),
`Assault` = c(str_subset(Reason, "Assault"),
str_subset(Reason, "Battery")),
`Wanted Person` = c(str_subset(Reason, "Wanted Person"),
str_subset(Reason, "Warrant")),
`Welfare Check` = c(str_subset(Reason, "Welfare")),
Drugs = c(str_subset(Reason, "Drug"),
str_subset(Reason, "Narco")),
Theft = c("Theft",
str_subset(Reason, "Burglar"),
str_subset(Reason, "Stolen Prop"),
"Stolen"),
DUI = c(str_subset(Reason, "Influence"),
str_subset(Reason, "Dui")),
`Missing/Endangered/Runaway` = c(str_subset(Reason, "Missing"),
str_subset(Reason, "Kidnap"),
str_subset(Reason, "Runaway")),
Tests = c(str_subset(Reason, "Test")),
`H & S` = c(str_subset(Reason, "Hs Inv"),
str_subset(Reason, "H&S"),
str_subset(Reason, "Health")),
`Investigation` = c("Investigations",
"Investigation",
"Criminal Inv")
)) |>
mutate(`Reason Type` = fct_rev(fct_lump_min(fct_infreq(`Reason Type`), 6))) |>
ggplot(aes(y = `Reason Type`)) +
geom_bar() +
ggtitle("BPD Searches Reason Categories")

Looking at search type:
flock_audit |>
mutate(`Search Type` = fct_collapse(`Search Type`,
Lookup = c("lookup", "lookup - Mobile"),
Search = c("search", "search - Mobile", "searchSummary - Mobile")
)) |>
mutate(`Search Type` = fct_infreq(`Search Type`)) |>
mutate(Date = as_date(dt)) |>
ggplot(aes(y = `Search Type`)) +
geom_bar() +
ggtitle("Search Type Frequencies") +
scale_x_log10() +
xlab("Search Counts (log)")

There are a few instances of “freeform” searches. These have text
prompts.
flock_audit |> filter(`Search Type` == "freeform") |> select(`Text Prompt`,`Org Name`, everything())
LS0tDQp0aXRsZTogIkJpc2hvcCBGbG9jayBBdWRpdCINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgY29kZV9mb2xkaW5nOiBoaWRlDQotLS0NCg0KVGhpcyBpcyBhbiBbUiBNYXJrZG93bl0oaHR0cDovL3JtYXJrZG93bi5yc3R1ZGlvLmNvbSkgTm90ZWJvb2sgd2l0aCBzb21lIHBsb3RzIGFuZCANCmFuYWx5c2lzIG9mIEJpc2hvcCwgQ2FsaWZvcm5pYSBQb2xpY2UgRGVwYXJ0bWVudCBGbG9jayBEYXRhLiBUaGlzIGZvcm1hdCBpcyBpbnRlbmRlZA0KdG8gYWxsb3cgb3RoZXJzIHRvIHJlcHJvZHVjZSBhbmQgbW9kaWZ5LiBJdCB3YWxrcyB0aHJvdWdoIGFsbCB0aGUgc3RlcHMuIENvZGUgYW5kIA0KcGxvdHMgYXJlIGluY2x1ZGVkLiANCg0KT2J2aW91c2x5LCBSIGlzIHJlcXVpcmVkLg0KDQpGaXJzdCwgbG9hZCBzb21lIHByZXJlcXVpc2l0ZSBsaWJyYXJpZXMuDQpgYGB7ciBtZXNzYWdlPUZBTFNFLCB3YXJuaW5nPUZBTFNFLCBpbmNsdWRlPVRSVUV9DQojIFJlcXVpcmVkIGxpYnJhcmllcw0KbGlicmFyeSh0aWR5dmVyc2UpDQpsaWJyYXJ5KGZvcmNhdHMpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmxpYnJhcnkoc2NhbGVzKQ0KYGBgDQoNCg0KIyMjIERhdGEgaW1wb3J0DQoNCk5vdyBpbXBvcnQgZGF0YSBmaWxlcy4gVGhpcyB1c2VzIHRoZSBwdWJsaWMgcmVjb3JkIHJlcXVlc3QgZGF0YSBvYnRhaW5lZCBieSBSb2JlcnQgb24gSnVuZSAyIDIwMjYuDQpUaGVzZSByZWNvcmRzIGNvdmVyIDIwMjUtMDMtMjEgdGhyb3VnaCAyMDI2LTA1LTEzLiBGb3IgdGhpcyBjb2RlIHRvIHJ1biwgaXQgaXMgYXNzdW1lZCB0aGF0IHRoZXkgYXJlIHVuemlwcGVkIHRvIHRoZSBzYW1lIGRpcmVjdG9yeSBhcyB0aGlzIGZpbGUuIA0KDQpUaGUgZGF0YSBpcyBpbiBjc3YgZm9ybWF0LCBhbmQgdGhlcmUgYXJlIDMga2luZHMgb2YgZmlsZXM6ICAgDQoNCi0gKlNoYXJlZCBOZXR3b3JrcyogZmlsZTogVGhpcyBjb250YWlucyBpbmZvIG9uIHRoZSBvcmdhbml6YXRpb25zIHRoYXQgQmlzaG9wIFBEIGhhcyBkYXRhIHNoYXJpbmcgYWdyZWVtZW50cyB3aXRoLg0KLSAqQXVkaXQqIGZpbGVzOiBUaGVzZSBjb250YWluIHJlY29yZHMgb2Ygc2VhcmNoZXMgcGVyZm9ybWVkIGJ5IEJpc2hvcCBQRC4gDQotICpOZXR3b3JrIEF1ZGl0KiBmaWxlczogVGhlc2UgY29udGFpbiByZWNvcmRzIG9mIHNlYXJjaGVzIHBlcmZvcm1lZCBieSBvdGhlciBvcmdhbml6YXRpb25zIHRoYXQgaW5jbHVkZWQgQmlzaG9wJ3MgRmxvY2sgY2FtZXJhcy4gDQoNClRoZSAqQXVkaXQqIGFuZCAqTmV0d29yayBBdWRpdCogZmlsZXMgd2lsbCBiZSByZWFkIGluIHRvZ2V0aGVyIGFuZCBjb21iaW5lZCBpbnRvIA0KYSBzaW5nbGUgZGF0YWZyYW1lLiBCaXNob3AgUEQgYW5kIGV4dGVybmFsIG9yZ2FuaXphdGlvbnMgYXJlIGRpc3Rpbmd1aXNoZWQgYnkgdGhlIA0KKk9yZyBOYW1lKiBmaWVsZC4gVGhpcyB3aWxsIHByb2R1Y2UgdGhlICpmbG9ja19hdWRpdCogZGF0YWZyYW1lLiBEYXRlcw0KYW5kIG5hbWVzIGFyZSBjbGVhbmVkIGZvciBlYXNpZXIgcHJvY2Vzc2luZy4NCg0KVGhlICpTaGFyZWQgTmV0d29ya3MqIGZpbGUgaXMgcmVhZCBpbnRvIGEgc2VwYXJhdGUgZGF0YWZyYW1lLiBUaGVyZSBhcmUgZXh0ZXJuYWwNCm5ldHdvcmtzIHJlcHJlc2VudGVkIGluIHRoZSAqTmV0d29yayBBdWRpdCogZmlsZXMgdGhhdCBhcmUgbm90IGluIHRoaXMgZmlsZSwgc28gDQp0aGF0IGluZm9ybWF0aW9uIGlzIGpvaW5lZCBpbnRvIHRoaXMgZGF0YWZyYW1lLCBjYWxsZWQgKnNoYXJlZF9uZXR3b3JrcyouDQoNCg0KYGBge3J9DQojIFJlYWQvY29tYmluZSBhdWRpdCBmaWxlcw0KbGlzdC5maWxlcyhwYXRoID0gIi4vRmxvY2sgQXVkaXQgRk9JQSBkYXRhLTIwMjYwNjAyVDAyMTIyMVotMy0wMDEvRmxvY2sgQXVkaXQgRk9JQSBkYXRhLyIsIA0KICAgICAgICAgICBwYXR0ZXJuID0gIlxcLUF1ZGl0LmNzdiIsDQogICAgICAgICAgIGZ1bGwubmFtZXMgPSBUUlVFKSB8PiANCiAgbWFwX2RmKH5yZWFkX2NzdiguLCBjb2xfdHlwZXMgPSBjb2xzKC5kZWZhdWx0ID0gImMiKSkpIC0+DQogIGZsb2NrX2F1ZGl0DQoNCiMgRGF0YSBDbGVhbmluZw0KZmxvY2tfYXVkaXQgfD4gDQogIG11dGF0ZShSZWFzb24gPSBzdHJpbmdyOjpzdHJfdG9fdGl0bGUoUmVhc29uKSkgfD4gDQogIG11dGF0ZShOYW1lID0gc3RyaW5ncjo6c3RyX3RvX3RpdGxlKE5hbWUpKSB8PiANCiAgbXV0YXRlKGR0ID0gc3RyX3JlbW92ZShgU2VhcmNoIFRpbWVgLCAiIFVUQyIpKSB8Pg0KICBtdXRhdGUoZHQgPSBwYXJzZV9kYXRlX3RpbWUoZHQsICIlbS8lZC8lWSwgJUk6JU06JVMgJXAiLCB0eiA9ICJVVEMiKSkgfD4gDQogIG11dGF0ZShEYXRlID0gYXNfZGF0ZShkdCkpIC0+DQogIGZsb2NrX2F1ZGl0DQoNCiMgUmVhZCBuZXR3b3JrIGZpbGVzDQpsaXN0LmZpbGVzKHBhdGggPSAiLi9GbG9jayBBdWRpdCBGT0lBIGRhdGEtMjAyNjA2MDJUMDIxMjIxWi0zLTAwMS9GbG9jayBBdWRpdCBGT0lBIGRhdGEvIiwNCiAgICAgICAgICAgcGF0dGVybiA9ICJcXFNoYXJlZE5ldHdvcmtzLipjc3YiLA0KICAgICAgICAgICBmdWxsLm5hbWVzID0gVFJVRSkgfD4gDQogIG1hcF9kZih+cmVhZF9jc3YoLiwgY29sX3R5cGVzID0gY29scyguZGVmYXVsdCA9ICJjIikpKSB8PiANCiAgbXV0YXRlKGBPcmcgTmFtZWAgPSBgT3JnYW5pemF0aW9uIE5hbWVgKS0+DQogIHNoYXJlZF9uZXR3b3Jrcw0KDQojIENvbWJpbmUgbmV0d29yayBpbmZvIGZyb20gYXVkaXQgYW5kIG5ldHdvcmsgZmlsZXMNCmZsb2NrX2F1ZGl0IHw+IA0KICBncm91cF9ieShgT3JnIE5hbWVgKSB8PiANCiAgc3VtbWFyaXplKG4gPSBuKCkpIHw+IA0KICBmdWxsX2pvaW4oc2hhcmVkX25ldHdvcmtzLCBieSA9IGMoIk9yZyBOYW1lIikpIC0+DQogIHNoYXJlZF9uZXR3b3Jrcw0KDQpgYGANCg0KDQojIyMgRmxvY2sgQXVkaXQgRXhhbXBsZSBkYXRhOiANCmBgYHtyfQ0KIyBQcmV2aWV3IGZsb2NrIGF1ZGl0IGRhdGE6DQpmbG9ja19hdWRpdCB8PiBzbGljZV9zYW1wbGUobiA9MTApDQpgYGANCg0KIyMjIFNoYXJlZCBOZXR3b3JrcyBFeGFtcGxlIGRhdGE6DQpgYGB7cn0NCnNoYXJlZF9uZXR3b3JrcyB8PiBzbGljZV9zYW1wbGUobiA9IDEwKQ0KYGBgDQoNCmBgYHtyfQ0KDQogIA0KDQpgYGANCg0KDQoNCg0KIyMjIFNoYXJlZCBOZXR3b3JrIFN0YXRzOg0KDQpMZXQncyB0YWtlIGEgbG9vayBhdCB3aGljaCBhZ2VuY2llcyBhcmUgcmVxdWVzdGluZyBkYXRhLiBIZXJlIGFyZSB0aGUgdG9wIDIwOg0KDQpgYGB7cn0NCmdncGxvdChmbG9ja19hdWRpdCwgDQogICAgICAgYWVzKHk9ZmN0X3JldihmY3RfbHVtcF9uKGZjdF9pbmZyZXEoYE9yZyBOYW1lYCksIDIwKSkpKSArDQogIGdlb21fYmFyKCkgKyANCiAgeWxhYigiT3JnYW5pemF0aW9uIikgKw0KICB4bGFiKCJTZWFyY2ggUmVxdWVzdHMiKSArIA0KICBnZ3RpdGxlKCJUb3AgUmVxdWVzdGluZyBBZ2VuY2llcyBmb3IgQmlzaG9wIEZsb2NrIENhbWVyYXMiKQ0KYGBgDQpXaGVyZSBkb2VzIEJpc2hvcCBQRCBzaXQgb24gdGhpcyBsaXN0PyBUaGUgMjI2dGggbW9zdCBmcmVxdWVudCB1c2VyLiANCg0KYGBge3J9DQpzaGFyZWRfbmV0d29ya3MgfD4NCiAgYXJyYW5nZShkZXNjKG4pKSB8Pg0KICBtdXRhdGUocmFuayA9IHJvd19udW1iZXIoKSkgfD4gDQogIHNlbGVjdChyYW5rLCBldmVyeXRoaW5nKCkpIHw+IA0KICBzbGljZSgyMjA6MjMwKSANCmBgYA0KDQo8IS0tIFdoZXJlIGFyZSB0aGVzZSBvcmdhbml6YXRpb25zPyBGb3Igc29tZSAobm90IGFsbCkgb3JnYW5pemF0aW9ucywgSSBjYW4gZWFzaWx5IGFkZCAtLT4NCjwhLS0gY29vcmRpbmF0ZXMgYW5kIHB1dCB0aGVtIG9uIGEgbWFwLiBIZXJlLCBJIHB1dCB0aG9zZSBvcmdhbml6YXRpb25zIG9uIGEgbWFwLCBzY2FsZSAtLT4NCjwhLS0gdGhlIHNpemUgb2YgdGhlaXIgY2lyY2xlcyBieSB0aGUgKGxvZykgbnVtYmVyIG9mIHRpbWVzIHRoZXkgYWNjZXNzZWQgQlBEIG5ldHdvcmtzLCAgLS0+DQo8IS0tIGFuZCBjb2xvciBjb2RlIHRoZW0gYnkgd2hhdCB0eXBlIG9mIG5ldHdvcmtzIEJpc2hvcCBQRCBzaGFyZXMgd2l0aCB0aGVtLiBTb21lIG9yZ2FuaXphdGlvbnMgLS0+DQo8IS0tIGhhdmUgc2hhcmluZyB0dXJuZWQgb24gZm9yIGJvdGggQUxQUiBhbmQgQ29uZG9yIGNhbWVyYXMsIHNvbWUganVzdCBmb3IgQUxQUiwgYW5kIHNvbWUgKE5BKSwgZG9uJ3QgaGF2ZSBhIHJlY29yZCAgLS0+DQo8IS0tIG9mIHNoYXJlZCBuZXR3b3JrcywgYnV0IHRoZWlyIHNlYXJjaGVzIHN0aWxsIHNob3cgdXAgaW4gdGhlIGF1ZGl0IGxvZ3MuICAtLT4NCg0KPCEtLSBgYGB7cn0gLS0+DQo8IS0tIHNoYXJlZF9uZXR3b3JrcyB8PiAgIC0tPg0KPCEtLSAgIG11dGF0ZShQbGFjZSA9IHN0cl9yZW1vdmUoYE9yZyBOYW1lYCwgIiBQRCIpKSB8PiAgLS0+DQo8IS0tICAgbXV0YXRlKFBsYWNlID0gc3RyX3JlcGxhY2UoUGxhY2UsICIoLiopKCBDQSkuKiIsICJcXDEsIENhbGlmb3JuaWEiKSkgfD4gLS0+DQo8IS0tICAgdGlkeWdlb2NvZGVyOjpnZW9jb2RlKFBsYWNlLCBtZXRob2QgPSAnb3NtJykgLT4gLS0+DQo8IS0tICAgc2hhcmVkX25ldHdvcmtzX2xhdGxvbiAtLT4NCg0KPCEtLSBzaGFyZWRfbmV0d29ya3NfbGF0bG9uIHw+ICAtLT4NCjwhLS0gICBzdF9hc19zZihjb29yZHMgPSBjKCJsb25nIiwgImxhdCIpLCAtLT4NCjwhLS0gICAgICAgICAgICBjcnMgPSAiK3Byb2o9bG9uZ2xhdCArZGF0dW09V0dTODQgK2VsbHBzPVdHUzg0ICt0b3dnczg0PTAsMCwwIiwgLS0+DQo8IS0tICAgICAgICAgICAgbmEuZmFpbCA9IEZBTFNFKSAtPiAtLT4NCjwhLS0gICBzaGFyZWRfbmV0d29ya3Nfc2YgLS0+DQoNCjwhLS0gYGBgIC0tPg0KPCEtLSBgYGB7cn0gLS0+DQo8IS0tIHNoYXJlZF9uZXR3b3Jrc19zZiB8PiAgLS0+DQo8IS0tICAgbXV0YXRlKFNoYXJpbmcgPSBpZmVsc2Uoc3RyX2RldGVjdChgTmV0d29ya3MgSSdtIFNoYXJpbmdgLCAibmRvciIpLCJDb25kb3IgYW5kIEFMUFIiLCAiQUxQUiIpKSB8PiAgLS0+DQo8IS0tICAgbXV0YXRlKHNpemUgPSByb3VuZChsb2cobikpKSAtPiAtLT4NCjwhLS0gICBCaXNob3BQRF9GbG9ja19OZXR3b3JrcyAtLT4NCg0KPCEtLSAgIEJpc2hvcFBEX0Zsb2NrX05ldHdvcmtzIHw+ICAtLT4NCjwhLS0gICBtYXB2aWV3OjptYXB2aWV3KHpjb2wgPSAiU2hhcmluZyIsIGNleCA9InNpemUiKSAtPiAtLT4NCjwhLS0gICAgIGZsb2NrX21hcCAtLT4NCg0KPCEtLSAgIGZsb2NrX21hcEBtYXAgfD4gbGVhZmxldC5leHRyYXM6OmFkZEZ1bGxzY3JlZW5Db250cm9sKCkgLS0+DQo8IS0tIGBgYCAtLT4NCiAgICAgDQogICAgIA0KICAgICANCg0KDQoNCmxlYWZsZXQuZXh0cmFzOjphZGRGdWxsc2NyZWVuQ29udHJvbCgpV2hhdCBhcmUgdGhlIHRvcCBSZWFzb25zIGdpdmVuIGZvciB0aGUgc2VhcmNoZXM/IE5vdGUgdGhhdCB0aGlzIGlzIG1lc3N5LCBiZWNhdXNlDQp0aGUgKlJlYXNvbiogZmllbGQgaXMgbm90IHN0YW5kYXJkaXplZC4gT25lIGludGVyZXN0aW5nIHRoaW5nIHRvIG5vdGUgaXMgdGhlIA0KcHJldmFsYW5jZSBvZiB2ZXJ5IGdlbmVyaWMsIHVuaW5mb3JtYXRpdmUgcmVhc29ucyBsaWtlICJJbnZlc3RpZ2F0aW9uIi4NCg0KYGBge3J9DQpmbG9ja19hdWRpdCB8PiANCiAgZ2dwbG90KCkgKyANCiAgZ2VvbV9iYXIoYWVzKHkgPSBmY3RfcmV2KGZjdF9sdW1wX24oZmN0X2luZnJlcShSZWFzb24pLCAyMCkpKSkgKw0KICB5bGFiKCJSZXF1ZXN0IFJlYXNvbiIpICsNCiAgeGxhYigiU2VhcmNoIFJlcXVlc3RzIikgKw0KICBzY2FsZV94X2NvbnRpbnVvdXMobGltaXRzID0gYygwLDIwMDAwMCksIG9vYiA9IHNjYWxlczo6b29iX2tlZXApICsNCiAgZ2d0aXRsZSgiVG9wIDIwIFNlYXJjaCBSZWFzb25zIGZvciBCaXNob3AgRmxvY2sgQ2FtZXJhcyIpIA0KDQpgYGANCkl0IGlzIGludGVyZXN0aW5nIHRvIG5vdGUgdGhhdCB0aGUgdXNlIG9mIHNvbWUgb2YgdGhlIHZlcnkgZ2VuZXJpYyByZWFzb25zIGxpa2UgIkludmVzdGlnYXRpb24iIG9yICJJbnYiIHNoYXJwbHkgZHJvcHBlZCBvZmYgaW4gMjAyNi4gV2FzIHRoZXJlIGFuIGNoYW5nZSBpbiBwb2xpY3k/DQoNCmBgYHtyfQ0KZmxvY2tfYXVkaXQgfD4gDQogIG11dGF0ZShSZWFzb24gPSBmY3RfY29sbGFwc2UoUmVhc29uLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBJbnZlc3RpZ2F0aW9uID0gYygiSW52ZXN0aWdhdGlvbiIsICJJbnYiLCAiSW52ZXN0IiwgIk90aGVyIC0gSW52ZXN0aWdhdGlvbiIpLA0KICApKSB8PiANCiAgbXV0YXRlKEdlbmVyaWMgPSBzdHJfZXF1YWwoUmVhc29uLCAiSW52ZXN0aWdhdGlvbiIpKSB8PiANCiAgI3NsaWNlX3NhbXBsZShuID0gMTAwMDApIHw+IA0KICBnZ3Bsb3QoYWVzKHggPSBEYXRlLCBhZnRlcl9zdGF0KGNvdW50KSwgZmlsbCA9IEdlbmVyaWMpKSArDQogIGdlb21fZGVuc2l0eShwb3NpdGlvbiA9ICJzdGFjayIpICsNCiAgZ2d0aXRsZSgiR2VuZXJpYyBJbnZlc3RpZ2F0aW9uIFNlYXJjaGVzIikNCmBgYA0KDQpJZiB3ZSBsb29rIGF0IG9ubHkgQmlzaG9wIFBEIHNlYXJjaGVzLCB3ZSBjYW4gbWFudWFsbHkgY29sbGFwc2UgdGhpcyBtZXNzeSAqUmVhc29uKg0KZmllbGQgYW5kIGdldCBhIGJldHRlciBzZW5zZSBvZiB0aGUgdHlwZXMgb2YgUmVhc29ucyB0aGVzZSBjYW1lcmFzIGFyZSB1c2VkLiBOb3RlIA0KdGhhdCBCaXNob3AgUEQncyB1c2UgZGlmZmVycyBmcm9tIHRoYXQgb2YgZXh0ZXJuYWwgb3JnYW5pemF0aW9ucy4NCg0KYGBge3J9DQpmbG9ja19hdWRpdCB8PiANCiAgbXV0YXRlKERhdGUgPSBhc19kYXRlKGR0KSkgfD4NCiAgZmlsdGVyKGBPcmcgTmFtZWAgPT0gIkJpc2hvcCBDQSBQRCIpIHw+IA0KICBtdXRhdGUoYFJlYXNvbiBUeXBlYCA9IGZjdF9jb2xsYXBzZShSZWFzb24sIA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgVmVoaWNsZSBUaGVmdGAgPSBjKHN0cl9zdWJzZXQoUmVhc29uLCAiVmVoaWNsZSBUaGVmdCIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zdWJzZXQoUmVhc29uLCAiU3RvbGVuIFZlaGljbGUiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfc3Vic2V0KFJlYXNvbiwgIjEwODUxIikpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgSGl0IGFuZCBSdW5gID0gYyhzdHJfc3Vic2V0KFJlYXNvbiwgIkhpdCIpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEFzc2F1bHRgID0gYyhzdHJfc3Vic2V0KFJlYXNvbiwgIkFzc2F1bHQiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfc3Vic2V0KFJlYXNvbiwgIkJhdHRlcnkiKSksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGBXYW50ZWQgUGVyc29uYCA9IGMoc3RyX3N1YnNldChSZWFzb24sICJXYW50ZWQgUGVyc29uIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3N1YnNldChSZWFzb24sICJXYXJyYW50IikpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgV2VsZmFyZSBDaGVja2AgPSBjKHN0cl9zdWJzZXQoUmVhc29uLCAiV2VsZmFyZSIpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRHJ1Z3MgPSBjKHN0cl9zdWJzZXQoUmVhc29uLCAiRHJ1ZyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3N1YnNldChSZWFzb24sICJOYXJjbyIpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgVGhlZnQgPSBjKCJUaGVmdCIsDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfc3Vic2V0KFJlYXNvbiwgIkJ1cmdsYXIiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zdWJzZXQoUmVhc29uLCAiU3RvbGVuIFByb3AiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJTdG9sZW4iKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgRFVJID0gYyhzdHJfc3Vic2V0KFJlYXNvbiwgIkluZmx1ZW5jZSIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHN0cl9zdWJzZXQoUmVhc29uLCAiRHVpIikpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgTWlzc2luZy9FbmRhbmdlcmVkL1J1bmF3YXlgID0gYyhzdHJfc3Vic2V0KFJlYXNvbiwgIk1pc3NpbmciKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3N1YnNldChSZWFzb24sICJLaWRuYXAiKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgc3RyX3N1YnNldChSZWFzb24sICJSdW5hd2F5IikpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBUZXN0cyA9IGMoc3RyX3N1YnNldChSZWFzb24sICJUZXN0IikpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBgSCAmIFNgID0gYyhzdHJfc3Vic2V0KFJlYXNvbiwgIkhzIEludiIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfc3Vic2V0KFJlYXNvbiwgIkgmUyIpLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBzdHJfc3Vic2V0KFJlYXNvbiwgIkhlYWx0aCIpKSwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYEludmVzdGlnYXRpb25gID0gYygiSW52ZXN0aWdhdGlvbnMiLA0KICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICJJbnZlc3RpZ2F0aW9uIiwNCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAiQ3JpbWluYWwgSW52IikNCiAgKSkgfD4NCiAgbXV0YXRlKGBSZWFzb24gVHlwZWAgPSBmY3RfcmV2KGZjdF9sdW1wX21pbihmY3RfaW5mcmVxKGBSZWFzb24gVHlwZWApLCA2KSkpIHw+IA0KICBnZ3Bsb3QoYWVzKHkgPSBgUmVhc29uIFR5cGVgKSkgKw0KICBnZW9tX2JhcigpICsgDQogIGdndGl0bGUoIkJQRCBTZWFyY2hlcyBSZWFzb24gQ2F0ZWdvcmllcyIpDQpgYGANCkxvb2tpbmcgYXQgc2VhcmNoIHR5cGU6DQpgYGB7cn0NCmZsb2NrX2F1ZGl0IHw+IA0KICBtdXRhdGUoYFNlYXJjaCBUeXBlYCA9IGZjdF9jb2xsYXBzZShgU2VhcmNoIFR5cGVgLCANCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBMb29rdXAgPSBjKCJsb29rdXAiLCAibG9va3VwIC0gTW9iaWxlIiksDQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU2VhcmNoID0gYygic2VhcmNoIiwgInNlYXJjaCAtIE1vYmlsZSIsICJzZWFyY2hTdW1tYXJ5IC0gTW9iaWxlIikNCiAgKSkgfD4gDQogIG11dGF0ZShgU2VhcmNoIFR5cGVgID0gZmN0X2luZnJlcShgU2VhcmNoIFR5cGVgKSkgfD4gDQogIG11dGF0ZShEYXRlID0gYXNfZGF0ZShkdCkpIHw+IA0KICBnZ3Bsb3QoYWVzKHkgPSBgU2VhcmNoIFR5cGVgKSkgKw0KICBnZW9tX2JhcigpICsgDQogIGdndGl0bGUoIlNlYXJjaCBUeXBlIEZyZXF1ZW5jaWVzIikgKw0KICBzY2FsZV94X2xvZzEwKCkgKw0KICB4bGFiKCJTZWFyY2ggQ291bnRzIChsb2cpIikNCmBgYA0KVGhlcmUgYXJlIGEgZmV3IGluc3RhbmNlcyBvZiAiZnJlZWZvcm0iIHNlYXJjaGVzLiBUaGVzZSBoYXZlIHRleHQgcHJvbXB0cy4gDQoNCmBgYHtyfQ0KZmxvY2tfYXVkaXQgfD4gZmlsdGVyKGBTZWFyY2ggVHlwZWAgPT0gImZyZWVmb3JtIikgfD4gc2VsZWN0KGBUZXh0IFByb21wdGAsYE9yZyBOYW1lYCwgIGV2ZXJ5dGhpbmcoKSkNCmBgYA0KDQoNCg0K