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

  1. 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))
  1. 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.

  2. 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=