Helper code for creating library.
Erik.Leppo@tetratech.com 2017-09-26
Copied from ContDataQC so some parts are not needed. 2017-12-04.
Package
Package related code.
Vignette
- Need to run code below to add data to “vignette” directory so it will work.
# 1. change wd to vignettes
setwd(file.path("C:","Users","Erik.Leppo","OneDrive - Tetra Tech, Inc"
,"MyDocs_OneDrive","GitHub","ContDataQC","vignettes"))
#
# 2. Add data for vignette examples
# Parameters
Selection.Operation <- c("GetGageData","QCRaw", "Aggregate", "SummaryStats")
Selection.Type <- c("Air","Water","AW","Gage","AWG","AG","WG")
Selection.SUB <- c("Data1_RAW","Data2_QC","Data3_Aggregated","Data4_Stats")
myDir.BASE <- getwd()
#
# Create data directories
myDir.create <- paste0("./",Selection.SUB[1])
ifelse(dir.exists(myDir.create)==FALSE,dir.create(myDir.create),"Directory already exists")
myDir.create <- paste0("./",Selection.SUB[2])
ifelse(dir.exists(myDir.create)==FALSE,dir.create(myDir.create),"Directory already exists")
myDir.create <- paste0("./",Selection.SUB[3])
ifelse(dir.exists(myDir.create)==FALSE,dir.create(myDir.create),"Directory already exists")
myDir.create <- paste0("./",Selection.SUB[4])
ifelse(dir.exists(myDir.create)==FALSE,dir.create(myDir.create),"Directory already exists")
#
# Save example data (assumes directory ./Data1_RAW/ exists)
myData <- data_raw_test2_AW_20130426_20130725
write.csv(myData,paste0("./",Selection.SUB[1],"/test2_AW_20130426_20130725.csv"))
myData <- data_raw_test2_AW_20130725_20131015
write.csv(myData,paste0("./",Selection.SUB[1],"/test2_AW_20130725_20131015.csv"))
myData <- data_raw_test2_AW_20140901_20140930
write.csv(myData,paste0("./",Selection.SUB[1],"/test2_AW_20140901_20140930.csv"))
myData <- data_raw_test4_AW_20160418_20160726
write.csv(myData,paste0("./",Selection.SUB[1],"/test4_AW_20160418_20160726.csv"))
myFile <- "config.TZ.Central.R"
file.copy(file.path(path.package("ContDataQC"),"extdata",myFile)
,file.path(getwd(),Selection.SUB[1],myFile))
Knit the vignette in the vignette folder to ensure all of the code works and is properly displayed. This can take 2 to 5 min.
Use the code below to “build” the vignette and then use it in the pkg.
# generate Vignette
library(baytrends)
library(devtools)
devtools::build_vignettes()
# create vignette folder and default file
#devtools::use_vignette("ContDataQC_Vignette")
devtools::build() more useful and build_vignettes()
Create Package
Use the code below to create the package. Assumes you are in the development package directory
Delete Namespace, Collate section of DESCRIPTION, and \man\*
Need to remove end of line after Collate. Need first entry on the same line as “Collate:”.
# NEWS
# Render then Copy NEWS so picked up in help
rmarkdown::render("NEWS.rmd", "all")
file.copy("NEWS.md", "NEWS", overwrite = TRUE)
file.remove("NEWS.html")
file.remove("NEWS.md")
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Library Name
myLibrary <- "baytrends"
# Load Library
library(devtools)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Create Package
# create(myLibrary)
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Document, Install, and Reload Library
## Generate Documentation
setwd(paste0("./", myLibrary))
devtools::document()
## Install New Package (locally)
setwd("..") # return to root directory first
devtools::install(myLibrary)
## Reload library
library(myLibrary, character.only = TRUE)
# change wd back to package
setwd(paste0("./", myLibrary))
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
After creating the package reload it after restarting R within RStudio (Ctrl + Shift + F10).
# Restart R within RStudio: Ctrl + Shift + F10
library("baytrends")
help(package="baytrends")
Check
# Check for errors (or press Cmd + Shift + E in RStudio)
#http://r-pkgs.had.co.nz/check.html
devtools::check()
If use RStudio, Build - Check Package, the output is easier to read.
Check failures (single vector so not very useful) but puts it all in one place. Have to run after using Check.
library(devtools)
dir.check <- "C:\\Users\\Erik.Leppo\\OneDrive - Tetra Tech, Inc\\MyDocs_OneDrive\\GitHub\\baytrends.Rcheck"
#
check_failures(dir.check)
Check functions and such
Index
Go straight to index.
help(package="baytrends")
Open Vignette
browseVignettes("baytrends")
Then click on “HTML” to open.
Run examples
example(analysisOrganizeData)
Including Data
All data should have already been created.
Test
Need to use testthat but not to that stage yet.
RStudio, Build - Test Package.
Other Stuff
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Upload to Github via GitHub Desktop utility
# 0. download from web via "clone or download" via "Open in Desktop" (GitHub Desktop) if not already in GitHub Desktop
# 1. Make changes in download/clone folder. (done above)
# 3. Open GH Desktop commit changes then sync.
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# install from GitHub (via devtools)
devtools::install_github(paste0("leppott/",myLibrary))
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# remove installed packages (if needed for troubleshooting)
search() # find
#detach(3) # remove by number
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# to build package
#https://thepoliticalmethodologist.com/2014/08/14/building-and-maintaining-r-packages-with-devtools-and-roxygen2/
# To build the package as a compressed file in your working directory, run build(current.code, path=getwd()).
# to save internal data for examples
# example
#http://r-pkgs.had.co.nz/data.html#data-sysdata
# have to be at root directory (above package)
#devtools::use_data(NV.predictors,NV.bugs,pkg="MMIcalcNV",internal=TRUE,overwrite=TRUE)
## verify with data()
# To save RMD files
# http://stackoverflow.com/questions/30377213/how-to-include-rmarkdown-file-in-r-package
# /pkg/inst/rmd/
# system.file("rmd/file.Rmd", package="packagename")
#
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#https://hilaryparker.com/2014/04/29/writing-an-r-package-from-scratch/
# Create Package
# create(myLibrary)
Test Stats only
# Parameters
Selection.Operation <- c("GetGageData","QCRaw", "Aggregate", "SummaryStats")
Selection.Type <- c("Air","Water","AW","Gage","AWG","AG","WG")
Selection.SUB <- c("Data1_RAW","Data2_QC","Data3_Aggregated","Data4_Stats")
myDir.BASE <- getwd()
#
# Summary Stats, File
## Have to use "file" version.
## Base version builds file name and expects "DATA" prefix
# Gage File + Other File
myData.Operation <- "SummaryStats" #Selection.Operation[4]
myFile <- c("Data4Stats_01187300_Gage_20130101_20141231.csv"
,"Data4Stats_test2_Aw_20130101_20141231.csv")
myDir.import <- file.path(".","data-raw")
myDir.export <- file.path(".","Data4_Stats")
#Leave off myReport.format and get default (docx).
ContDataQC(myData.Operation
, fun.myDir.import=myDir.import
, fun.myDir.export=myDir.export
, fun.myFile=myFile)
SiteID, Date, Time, Date.Time, Parameters, Flag.Parameters
Only one flag per parameter. Do not need individual test flags.
“F” (fail) flags are changed to NA so they are dropped from the statistics that calculated.
Mocked up 2 files.
LS0tDQp0aXRsZTogImJheXRyZW5kcyBMaWJyYXJ5IENyZWF0aW9uIg0KYXV0aG9yOiAiRXJpayBXLiBMZXBwbyINCmRhdGU6ICJgciBTeXMudGltZSgpYCINCm91dHB1dDogDQogIGh0bWxfbm90ZWJvb2s6DQogICAgdG9jOiB5ZXMNCiAgICBkZXB0aDogMw0KICAgIHRvY19mbG9hdDogeWVzDQotLS0NCg0KSGVscGVyIGNvZGUgZm9yIGNyZWF0aW5nIGxpYnJhcnkuDQoNCkVyaWsuTGVwcG9AdGV0cmF0ZWNoLmNvbQ0KMjAxNy0wOS0yNg0KDQpDb3BpZWQgZnJvbSBDb250RGF0YVFDIHNvIHNvbWUgcGFydHMgYXJlIG5vdCBuZWVkZWQuICAyMDE3LTEyLTA0Lg0KDQojIFBhY2thZ2UNCg0KUGFja2FnZSByZWxhdGVkIGNvZGUuDQoNCiMjIFZpZ25ldHRlDQoNCjEuIE5lZWQgdG8gcnVuIGNvZGUgYmVsb3cgdG8gYWRkIGRhdGEgdG8gInZpZ25ldHRlIiBkaXJlY3Rvcnkgc28gaXQgd2lsbCB3b3JrLg0KDQpgYGB7ciBWaWduZXR0ZV9EYXRhLCBldmFsPUZBTFNFfQ0KIyAxLiBjaGFuZ2Ugd2QgdG8gdmlnbmV0dGVzDQpzZXR3ZChmaWxlLnBhdGgoIkM6IiwiVXNlcnMiLCJFcmlrLkxlcHBvIiwiT25lRHJpdmUgLSBUZXRyYSBUZWNoLCBJbmMiDQogICAgICAgICAgICAgICAgLCJNeURvY3NfT25lRHJpdmUiLCJHaXRIdWIiLCJDb250RGF0YVFDIiwidmlnbmV0dGVzIikpDQojDQojIDIuIEFkZCBkYXRhIGZvciB2aWduZXR0ZSBleGFtcGxlcw0KIyBQYXJhbWV0ZXJzDQpTZWxlY3Rpb24uT3BlcmF0aW9uIDwtIGMoIkdldEdhZ2VEYXRhIiwiUUNSYXciLCAiQWdncmVnYXRlIiwgIlN1bW1hcnlTdGF0cyIpDQpTZWxlY3Rpb24uVHlwZSAgICAgIDwtIGMoIkFpciIsIldhdGVyIiwiQVciLCJHYWdlIiwiQVdHIiwiQUciLCJXRyIpDQpTZWxlY3Rpb24uU1VCIDwtIGMoIkRhdGExX1JBVyIsIkRhdGEyX1FDIiwiRGF0YTNfQWdncmVnYXRlZCIsIkRhdGE0X1N0YXRzIikNCm15RGlyLkJBU0UgPC0gZ2V0d2QoKQ0KIw0KIyBDcmVhdGUgZGF0YSBkaXJlY3Rvcmllcw0KbXlEaXIuY3JlYXRlIDwtIHBhc3RlMCgiLi8iLFNlbGVjdGlvbi5TVUJbMV0pDQogIGlmZWxzZShkaXIuZXhpc3RzKG15RGlyLmNyZWF0ZSk9PUZBTFNFLGRpci5jcmVhdGUobXlEaXIuY3JlYXRlKSwiRGlyZWN0b3J5IGFscmVhZHkgZXhpc3RzIikNCm15RGlyLmNyZWF0ZSA8LSBwYXN0ZTAoIi4vIixTZWxlY3Rpb24uU1VCWzJdKQ0KICBpZmVsc2UoZGlyLmV4aXN0cyhteURpci5jcmVhdGUpPT1GQUxTRSxkaXIuY3JlYXRlKG15RGlyLmNyZWF0ZSksIkRpcmVjdG9yeSBhbHJlYWR5IGV4aXN0cyIpDQpteURpci5jcmVhdGUgPC0gcGFzdGUwKCIuLyIsU2VsZWN0aW9uLlNVQlszXSkNCiAgaWZlbHNlKGRpci5leGlzdHMobXlEaXIuY3JlYXRlKT09RkFMU0UsZGlyLmNyZWF0ZShteURpci5jcmVhdGUpLCJEaXJlY3RvcnkgYWxyZWFkeSBleGlzdHMiKQ0KbXlEaXIuY3JlYXRlIDwtIHBhc3RlMCgiLi8iLFNlbGVjdGlvbi5TVUJbNF0pDQogIGlmZWxzZShkaXIuZXhpc3RzKG15RGlyLmNyZWF0ZSk9PUZBTFNFLGRpci5jcmVhdGUobXlEaXIuY3JlYXRlKSwiRGlyZWN0b3J5IGFscmVhZHkgZXhpc3RzIikNCiMNCiMgU2F2ZSBleGFtcGxlIGRhdGEgKGFzc3VtZXMgZGlyZWN0b3J5IC4vRGF0YTFfUkFXLyBleGlzdHMpDQpteURhdGEgPC0gZGF0YV9yYXdfdGVzdDJfQVdfMjAxMzA0MjZfMjAxMzA3MjUNCiAgd3JpdGUuY3N2KG15RGF0YSxwYXN0ZTAoIi4vIixTZWxlY3Rpb24uU1VCWzFdLCIvdGVzdDJfQVdfMjAxMzA0MjZfMjAxMzA3MjUuY3N2IikpDQpteURhdGEgPC0gZGF0YV9yYXdfdGVzdDJfQVdfMjAxMzA3MjVfMjAxMzEwMTUNCiAgd3JpdGUuY3N2KG15RGF0YSxwYXN0ZTAoIi4vIixTZWxlY3Rpb24uU1VCWzFdLCIvdGVzdDJfQVdfMjAxMzA3MjVfMjAxMzEwMTUuY3N2IikpDQpteURhdGEgPC0gZGF0YV9yYXdfdGVzdDJfQVdfMjAxNDA5MDFfMjAxNDA5MzANCiAgd3JpdGUuY3N2KG15RGF0YSxwYXN0ZTAoIi4vIixTZWxlY3Rpb24uU1VCWzFdLCIvdGVzdDJfQVdfMjAxNDA5MDFfMjAxNDA5MzAuY3N2IikpDQpteURhdGEgPC0gZGF0YV9yYXdfdGVzdDRfQVdfMjAxNjA0MThfMjAxNjA3MjYNCiAgd3JpdGUuY3N2KG15RGF0YSxwYXN0ZTAoIi4vIixTZWxlY3Rpb24uU1VCWzFdLCIvdGVzdDRfQVdfMjAxNjA0MThfMjAxNjA3MjYuY3N2IikpDQpteUZpbGUgPC0gImNvbmZpZy5UWi5DZW50cmFsLlIiDQogIGZpbGUuY29weShmaWxlLnBhdGgocGF0aC5wYWNrYWdlKCJDb250RGF0YVFDIiksImV4dGRhdGEiLG15RmlsZSkNCiAgICAgICAgICAgICxmaWxlLnBhdGgoZ2V0d2QoKSxTZWxlY3Rpb24uU1VCWzFdLG15RmlsZSkpDQpgYGANCg0KMi4gS25pdCB0aGUgdmlnbmV0dGUgaW4gdGhlIHZpZ25ldHRlIGZvbGRlciB0byBlbnN1cmUgYWxsIG9mIHRoZSBjb2RlIHdvcmtzIGFuZCANCmlzIHByb3Blcmx5IGRpc3BsYXllZC4gIFRoaXMgY2FuIHRha2UgMiB0byA1IG1pbi4NCg0KMy4gVXNlIHRoZSBjb2RlIGJlbG93IHRvICJidWlsZCIgdGhlIHZpZ25ldHRlIGFuZCB0aGVuIHVzZSBpdCBpbiB0aGUgcGtnLg0KDQpgYGB7ciBWaWduZXR0ZV9CdWlsZCwgZXZhbD1GQUxTRX0NCiMgZ2VuZXJhdGUgVmlnbmV0dGUNCmxpYnJhcnkoYmF5dHJlbmRzKQ0KbGlicmFyeShkZXZ0b29scykNCmRldnRvb2xzOjpidWlsZF92aWduZXR0ZXMoKQ0KDQojIGNyZWF0ZSB2aWduZXR0ZSBmb2xkZXIgYW5kIGRlZmF1bHQgZmlsZQ0KI2RldnRvb2xzOjp1c2VfdmlnbmV0dGUoIkNvbnREYXRhUUNfVmlnbmV0dGUiKQ0KYGBgDQpkZXZ0b29sczo6YnVpbGQoKSBtb3JlIHVzZWZ1bCBhbmQgYnVpbGRfdmlnbmV0dGVzKCkNCg0KIyMgQ3JlYXRlIFBhY2thZ2UNClVzZSB0aGUgY29kZSBiZWxvdyB0byBjcmVhdGUgdGhlIHBhY2thZ2UuICBBc3N1bWVzIHlvdSBhcmUgaW4gdGhlIGRldmVsb3BtZW50IHBhY2thZ2UgZGlyZWN0b3J5DQoNCkRlbGV0ZSBOYW1lc3BhY2UsIENvbGxhdGUgc2VjdGlvbiBvZiBERVNDUklQVElPTiwgYW5kIFxcbWFuXFwqDQoNCk5lZWQgdG8gcmVtb3ZlIGVuZCBvZiBsaW5lIGFmdGVyIENvbGxhdGUuDQpOZWVkIGZpcnN0IGVudHJ5IG9uIHRoZSBzYW1lIGxpbmUgYXMgIkNvbGxhdGU6Ii4NCg0KYGBge3IgUEtHX0JVSUxELCBldmFsPUZBTFNFfQ0KIyBORVdTDQojIFJlbmRlciB0aGVuIENvcHkgTkVXUyBzbyBwaWNrZWQgdXAgaW4gaGVscA0Kcm1hcmtkb3duOjpyZW5kZXIoIk5FV1Mucm1kIiwgImFsbCIpDQpmaWxlLmNvcHkoIk5FV1MubWQiLCAiTkVXUyIsIG92ZXJ3cml0ZSA9IFRSVUUpDQpmaWxlLnJlbW92ZSgiTkVXUy5odG1sIikNCmZpbGUucmVtb3ZlKCJORVdTLm1kIikNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIExpYnJhcnkgTmFtZQ0KbXlMaWJyYXJ5IDwtICJiYXl0cmVuZHMiDQojIExvYWQgTGlicmFyeQ0KbGlicmFyeShkZXZ0b29scykNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIENyZWF0ZSBQYWNrYWdlDQojIGNyZWF0ZShteUxpYnJhcnkpDQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIw0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiMgRG9jdW1lbnQsIEluc3RhbGwsIGFuZCBSZWxvYWQgTGlicmFyeQ0KIyMgR2VuZXJhdGUgRG9jdW1lbnRhdGlvbg0Kc2V0d2QocGFzdGUwKCIuLyIsIG15TGlicmFyeSkpDQpkZXZ0b29sczo6ZG9jdW1lbnQoKQ0KIyMgSW5zdGFsbCBOZXcgUGFja2FnZSAobG9jYWxseSkNCnNldHdkKCIuLiIpICMgcmV0dXJuIHRvIHJvb3QgZGlyZWN0b3J5IGZpcnN0DQpkZXZ0b29sczo6aW5zdGFsbChteUxpYnJhcnkpDQojIyBSZWxvYWQgbGlicmFyeQ0KbGlicmFyeShteUxpYnJhcnksIGNoYXJhY3Rlci5vbmx5ID0gVFJVRSkNCiMgY2hhbmdlIHdkIGJhY2sgdG8gcGFja2FnZQ0Kc2V0d2QocGFzdGUwKCIuLyIsIG15TGlicmFyeSkpDQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KYGBgDQoNCkFmdGVyIGNyZWF0aW5nIHRoZSBwYWNrYWdlIHJlbG9hZCBpdCBhZnRlciByZXN0YXJ0aW5nIFIgd2l0aGluIFJTdHVkaW8gKEN0cmwgKyBTaGlmdCArIEYxMCkuDQoNCmBgYHtyLCBldmFsPUZBTFNFfQ0KIyBSZXN0YXJ0IFIgd2l0aGluIFJTdHVkaW86ICBDdHJsICsgU2hpZnQgKyBGMTANCmxpYnJhcnkoImJheXRyZW5kcyIpDQpoZWxwKHBhY2thZ2U9ImJheXRyZW5kcyIpDQpgYGANCg0KIyMgQ2hlY2sNCg0KYGBge3IsIGV2YWw9RkFMU0V9DQojIENoZWNrIGZvciBlcnJvcnMgKG9yIHByZXNzIENtZCArIFNoaWZ0ICsgRSBpbiBSU3R1ZGlvKQ0KI2h0dHA6Ly9yLXBrZ3MuaGFkLmNvLm56L2NoZWNrLmh0bWwNCmRldnRvb2xzOjpjaGVjaygpDQpgYGANCg0KSWYgdXNlIFJTdHVkaW8sIEJ1aWxkIC0gQ2hlY2sgUGFja2FnZSwgdGhlIG91dHB1dCBpcyBlYXNpZXIgdG8gcmVhZC4gDQoNCkNoZWNrIGZhaWx1cmVzDQooc2luZ2xlIHZlY3RvciBzbyBub3QgdmVyeSB1c2VmdWwpDQpidXQgcHV0cyBpdCBhbGwgaW4gb25lIHBsYWNlLiAgSGF2ZSB0byBydW4gKmFmdGVyKiB1c2luZyBDaGVjay4NCmBgYHtyIENoZWNrRmFpbHVyZXMsIGV2YWw9RkFMU0V9DQpsaWJyYXJ5KGRldnRvb2xzKQ0KZGlyLmNoZWNrIDwtICJDOlxcVXNlcnNcXEVyaWsuTGVwcG9cXE9uZURyaXZlIC0gVGV0cmEgVGVjaCwgSW5jXFxNeURvY3NfT25lRHJpdmVcXEdpdEh1YlxcYmF5dHJlbmRzLlJjaGVjayINCiMNCmNoZWNrX2ZhaWx1cmVzKGRpci5jaGVjaykNCg0KDQpgYGANCg0KDQoNCiMjIENoZWNrIGZ1bmN0aW9ucyBhbmQgc3VjaA0KIyMjIEluZGV4DQpHbyBzdHJhaWdodCB0byBpbmRleC4NCg0KYGBge3IsIGV2YWw9RkFMU0V9DQpoZWxwKHBhY2thZ2U9ImJheXRyZW5kcyIpDQpgYGANCg0KDQojIyMgT3BlbiBWaWduZXR0ZQ0KYGBge3IsIGV2YWw9RkFMU0V9DQpicm93c2VWaWduZXR0ZXMoImJheXRyZW5kcyIpDQpgYGANCg0KDQpUaGVuIGNsaWNrIG9uICJIVE1MIiB0byBvcGVuLg0KDQojIyMgUnVuIGV4YW1wbGVzDQpgYGB7ciwgZXZhbD1GQUxTRX0NCmV4YW1wbGUoYW5hbHlzaXNPcmdhbml6ZURhdGEpDQpgYGANCg0KDQoNCg0KIyMgSW5jbHVkaW5nIERhdGENCkFsbCBkYXRhIHNob3VsZCBoYXZlIGFscmVhZHkgYmVlbiBjcmVhdGVkLg0KDQoNCg0KIyMgVGVzdA0KTmVlZCB0byB1c2UgdGVzdHRoYXQgYnV0IG5vdCB0byB0aGF0IHN0YWdlIHlldC4NCg0KUlN0dWRpbywgQnVpbGQgLSBUZXN0IFBhY2thZ2UuDQoNCg0KIyBPdGhlciBTdHVmZg0KDQpgYGB7ciwgZXZhbD1GQUxTRX0NCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIFVwbG9hZCB0byBHaXRodWIgdmlhIEdpdEh1YiBEZXNrdG9wIHV0aWxpdHkNCiMgMC4gZG93bmxvYWQgZnJvbSB3ZWIgdmlhICJjbG9uZSBvciBkb3dubG9hZCIgdmlhICJPcGVuIGluIERlc2t0b3AiIChHaXRIdWIgRGVza3RvcCkgaWYgbm90IGFscmVhZHkgaW4gR2l0SHViIERlc2t0b3ANCiMgMS4gTWFrZSBjaGFuZ2VzIGluIGRvd25sb2FkL2Nsb25lIGZvbGRlci4gKGRvbmUgYWJvdmUpDQojIDMuIE9wZW4gR0ggRGVza3RvcCBjb21taXQgY2hhbmdlcyB0aGVuIHN5bmMuDQojfn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fg0KIyBpbnN0YWxsIGZyb20gR2l0SHViICh2aWEgZGV2dG9vbHMpDQpkZXZ0b29sczo6aW5zdGFsbF9naXRodWIocGFzdGUwKCJsZXBwb3R0LyIsbXlMaWJyYXJ5KSkNCiMNCg0KDQoNCiN+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+DQojIHJlbW92ZSBpbnN0YWxsZWQgcGFja2FnZXMgKGlmIG5lZWRlZCBmb3IgdHJvdWJsZXNob290aW5nKQ0Kc2VhcmNoKCkgIyBmaW5kDQojZGV0YWNoKDMpICMgcmVtb3ZlIGJ5IG51bWJlcg0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCg0KDQojIHRvIGJ1aWxkIHBhY2thZ2UNCiNodHRwczovL3RoZXBvbGl0aWNhbG1ldGhvZG9sb2dpc3QuY29tLzIwMTQvMDgvMTQvYnVpbGRpbmctYW5kLW1haW50YWluaW5nLXItcGFja2FnZXMtd2l0aC1kZXZ0b29scy1hbmQtcm94eWdlbjIvDQojIFRvIGJ1aWxkIHRoZSBwYWNrYWdlIGFzIGEgY29tcHJlc3NlZCBmaWxlIGluIHlvdXIgd29ya2luZyBkaXJlY3RvcnksIHJ1biBidWlsZChjdXJyZW50LmNvZGUsIHBhdGg9Z2V0d2QoKSkuDQoNCiMgdG8gc2F2ZSBpbnRlcm5hbCBkYXRhIGZvciBleGFtcGxlcw0KIyBleGFtcGxlDQojaHR0cDovL3ItcGtncy5oYWQuY28ubnovZGF0YS5odG1sI2RhdGEtc3lzZGF0YQ0KIyBoYXZlIHRvIGJlIGF0IHJvb3QgZGlyZWN0b3J5IChhYm92ZSBwYWNrYWdlKQ0KI2RldnRvb2xzOjp1c2VfZGF0YShOVi5wcmVkaWN0b3JzLE5WLmJ1Z3MscGtnPSJNTUljYWxjTlYiLGludGVybmFsPVRSVUUsb3ZlcndyaXRlPVRSVUUpDQojIyB2ZXJpZnkgd2l0aCBkYXRhKCkNCg0KIyBUbyBzYXZlIFJNRCBmaWxlcw0KIyBodHRwOi8vc3RhY2tvdmVyZmxvdy5jb20vcXVlc3Rpb25zLzMwMzc3MjEzL2hvdy10by1pbmNsdWRlLXJtYXJrZG93bi1maWxlLWluLXItcGFja2FnZQ0KIyAvcGtnL2luc3Qvcm1kLw0KIyBzeXN0ZW0uZmlsZSgicm1kL2ZpbGUuUm1kIiwgcGFja2FnZT0icGFja2FnZW5hbWUiKQ0KIw0KI35+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn5+fn4NCiNodHRwczovL2hpbGFyeXBhcmtlci5jb20vMjAxNC8wNC8yOS93cml0aW5nLWFuLXItcGFja2FnZS1mcm9tLXNjcmF0Y2gvDQojIENyZWF0ZSBQYWNrYWdlDQojIGNyZWF0ZShteUxpYnJhcnkpDQoNCmBgYA0KDQojIFRlc3QgU3RhdHMgb25seQ0KDQoNCmBgYHtyIFN0YXRzX0dhZ2UsIGV2YWw9RkFMU0V9DQojIFBhcmFtZXRlcnMNClNlbGVjdGlvbi5PcGVyYXRpb24gPC0gYygiR2V0R2FnZURhdGEiLCJRQ1JhdyIsICJBZ2dyZWdhdGUiLCAiU3VtbWFyeVN0YXRzIikNClNlbGVjdGlvbi5UeXBlICAgICAgPC0gYygiQWlyIiwiV2F0ZXIiLCJBVyIsIkdhZ2UiLCJBV0ciLCJBRyIsIldHIikNClNlbGVjdGlvbi5TVUIgPC0gYygiRGF0YTFfUkFXIiwiRGF0YTJfUUMiLCJEYXRhM19BZ2dyZWdhdGVkIiwiRGF0YTRfU3RhdHMiKQ0KbXlEaXIuQkFTRSA8LSBnZXR3ZCgpDQojDQojIFN1bW1hcnkgU3RhdHMsIEZpbGUNCiMjIEhhdmUgdG8gdXNlICJmaWxlIiB2ZXJzaW9uLiAgDQojIyBCYXNlIHZlcnNpb24gYnVpbGRzIGZpbGUgbmFtZSBhbmQgZXhwZWN0cyAiREFUQSIgcHJlZml4DQoNCiMgR2FnZSBGaWxlICsgT3RoZXIgRmlsZQ0KbXlEYXRhLk9wZXJhdGlvbiA8LSAiU3VtbWFyeVN0YXRzIiAjU2VsZWN0aW9uLk9wZXJhdGlvbls0XQ0KbXlGaWxlIDwtIGMoIkRhdGE0U3RhdHNfMDExODczMDBfR2FnZV8yMDEzMDEwMV8yMDE0MTIzMS5jc3YiDQogICAgICAgICAgICAsIkRhdGE0U3RhdHNfdGVzdDJfQXdfMjAxMzAxMDFfMjAxNDEyMzEuY3N2IikNCm15RGlyLmltcG9ydCA8LSBmaWxlLnBhdGgoIi4iLCJkYXRhLXJhdyIpDQpteURpci5leHBvcnQgPC0gZmlsZS5wYXRoKCIuIiwiRGF0YTRfU3RhdHMiKQ0KDQojTGVhdmUgb2ZmIG15UmVwb3J0LmZvcm1hdCBhbmQgZ2V0IGRlZmF1bHQgKGRvY3gpLg0KQ29udERhdGFRQyhteURhdGEuT3BlcmF0aW9uDQogICAgICAgICAgICwgZnVuLm15RGlyLmltcG9ydD1teURpci5pbXBvcnQNCiAgICAgICAgICAgLCBmdW4ubXlEaXIuZXhwb3J0PW15RGlyLmV4cG9ydA0KICAgICAgICAgICAsIGZ1bi5teUZpbGU9bXlGaWxlKQ0KDQoNCmBgYA0KDQpTaXRlSUQsIERhdGUsIFRpbWUsIERhdGUuVGltZSwgUGFyYW1ldGVycywgRmxhZy5QYXJhbWV0ZXJzDQoNCk9ubHkgb25lIGZsYWcgcGVyIHBhcmFtZXRlci4gIERvIG5vdCBuZWVkIGluZGl2aWR1YWwgdGVzdCBmbGFncy4NCg0KIkYiIChmYWlsKSBmbGFncyBhcmUgY2hhbmdlZCB0byBOQSBzbyB0aGV5IGFyZSBkcm9wcGVkIGZyb20gdGhlIHN0YXRpc3RpY3MgdGhhdCBjYWxjdWxhdGVkLg0KDQpNb2NrZWQgdXAgMiBmaWxlcy4=