Installing Packages
COMPAS
Description: Conformational Manipulations of Protein Atomic Structures
install.packages(“compas”)
compas
library(“readr”)
library(“tidyverse”)
library(“dplyr”)
library(“magrittr”)
library(“lubridate”)
library(readr)
install.packages(readr)
library(“readr”)

The goal of readr is to provide a fast and friendly way to read rectangular data from delimited files, such as comma-separated values (CSV) and tab-separated values (TSV). It is designed to parse many types of data found in the wild, while providing an informative problem report when parsing leads to unexpected results.
library(tidyverse)
install.packages(tidyverse)
library(“tidyverse”)

The tidyverse is a collection of open source packages for the R programming language introduced by Hadley Wickham and his team that “share an underlying design philosophy, grammar, and data structures” of tidy data.
dplyr
install.packages(dplyr)
library(“dplyr”)

One of the core packages of the tidyverse in the R programming language, dplyr is primarily a set of functions designed to enable dataframe manipulation in an intuitive, user-friendly way
magrittr
install.packages(magrittr)
library(“magrittr”)

Provides a mechanism for chaining commands with a new forward-pipe operator, %>%. This operator will forward a value, or the result of an expression, into the next function call/expression. There is flexible support for the type of right-hand side expressions. For more information, see package vignette. To quote Rene Magritte, “Ceci n’est pas un pipe.”
lubridate
install.packages(lubridate)
library(“lubridate”)

R commands for date-times are generally unintuitive and change depending on the type of date-time object being used. Moreover, the methods we use with date-times must be robust to time zones, leap days, daylight savings times, and other time related quirks, and R lacks these capabilities in some situations. Lubridate makes it easier to do the things R does with date-times and possible to do the things R does not.
File Import
Read in .csv file
recid.dat = read.csv("compas.violent.csv")
Data Summary
amount1 <- length(recid.dat)
print(paste("there are", amount1, "columns in the recid.dat file"))
[1] "there are 20 columns in the recid.dat file"
amount2 <- nrow(recid.dat)
print(paste('there are', amount2, 'rows in the recid.dat file'))
[1] "there are 4743 rows in the recid.dat file"
take0 <- recid.dat[1:3,1:6]
Make a Copy of recid.dat
external.dat <- recid.dat
Number of Distinct Values
individuals <- length(unique(recid.dat$name))
print(paste('there are' , individuals,'unique individuals'))
[1] "there are 4721 unique individuals"
Assigning Unique Identifier
new_recid.dat <- cbind(recid.dat,
DEFID = c(5000:9742))
new_recid.dat <- new_recid.dat[, c(21, 1:20)] # assigning DEFID to 1st column
print(head(new_recid.dat[1:3,1:6]))
external.dat <- cbind(external.dat,
DEFID = new_recid.dat$DEFID)
external.dat <- external.dat[, c(21, 1:20)] # assigning DEFID to 1st column
take1 <- print(head(external.dat[1:3,1:6]))
ADD DELETE COLUMN(S)
Add AGECAT Variable
oldest <- min(external.dat$dob)
print(paste(oldest,"is the oldest date of birth"))
[1] "1932-09-24 is the oldest date of birth"
youngest <- max(external.dat$dob)
print(paste(youngest,"is the most recent date of birth"))
[1] "1998-01-20 is the most recent date of birth"
external.dat$AGECAT <- ifelse(external.dat$dob < "1924-12-31", "Greatest Gen",
ifelse(external.dat$dob < "1945-12-31", "Silent Gen",
ifelse(external.dat$dob < "1964-12-31", "Baby Boomer",
ifelse(external.dat$dob < "1979-12-31", "Gen X",
ifelse(external.dat$dob < "1994-12-31", "Millenials",
ifelse(external.dat$dob < "2012-12-31", "Gen Z",
ifelse(external.dat$dob < "2025-12-31", "Gen Alpha")))))))
Remove age & dob
external.dat <- external.dat[, c(19, 1:18)] #reassign new column as first column
external.dat <- external.dat[,-c(5,6)]
#length(external.dat) #check data frame dimension is correct
take3 <- print(head(external.dat[1:3.,1:10]))
RECODE VALUES OF A VARIABLE
REPLACE DATETIME COLUMNS
Create Jail Days Column
external.dat$jail_days <- ifelse(external.dat$jail_hours < 23.9, 1,
ifelse(external.dat$jail_hours >= 24, 2,
ifelse(external.dat$jail_hours < 48, 3,
ifelse(external.dat$jail_hours <= 72, 4
))))
external.dat <- external.dat[, c(19, 1:18)]
tail_ <- view(tail(external.dat[4741:4743,1:6]))
head_ <- view(head(external.dat[1:3,1:6]))
Bibliography
This assignment about replicating the COMPAS software, which uses an algorithm to assess potential recidivism risk R-4.2.2 for Windows.
R is ‘GNU S,’ a freely available language and environment for statistical computing and graphics which provides a wide variety of statistical and graphical techniques such as linear and nonlinear modelling, statistical tests, time series analysis, classification, clustering, and in our case: in modeling the risk assessment software.
COMPAS - Correctional Offender Management Profiling for Alternative Sanctions (COMPAS) is a case management and decision support tool developed and owned by Northpointe (now Equivant) used by U.S. courts to assess the likelihood of a defendant becoming a recidivist.
For an in depth understanding of the methodology used in COMPAS risk assessment, I recommend the Practitioner-s-Guide-to-COMPAS-Core handbook.
LS0tDQp0aXRsZTogJ0RhdGEgQ29uZmlkZW50aWFsaXR5ICcNCmF1dGhvcjogImJ5IE5kdWJ1aXNpIENoaWJ1b2d3dSINCm91dHB1dDoNCiAgaHRtbF9ub3RlYm9vazoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogNA0KICAgIG51bWJlcl9zZWN0aW9uczogeWVzDQogIHBkZl9kb2N1bWVudDoNCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogJzQnDQogICAgbnVtYmVyX3NlY3Rpb25zOiB5ZXMNCiAgaHRtbF9kb2N1bWVudDoNCiAgICANCiAgICB0b2M6IHllcw0KICAgIHRvY19kZXB0aDogJzQnDQogICAgZGZfcHJpbnQ6IHBhZ2VkDQpiaWJsaW9ncmFwaHk6IHJlZmVyZW5jZXMuYmliDQotLS0NCg0KIyBJbnN0YWxsaW5nIFBhY2thZ2VzDQoNCiMjIENPTVBBUw0KRGVzY3JpcHRpb246IENvbmZvcm1hdGlvbmFsIE1hbmlwdWxhdGlvbnMgb2YgUHJvdGVpbiBBdG9taWMgU3RydWN0dXJlcyBcDQppbnN0YWxsLnBhY2thZ2VzKCJjb21wYXMiKSBcDQpbY29tcGFzXSgiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ09NUEFTXyhzb2Z0d2FyZSkpDQoNCiANCmxpYnJhcnkoInJlYWRyIikgXA0KbGlicmFyeSgidGlkeXZlcnNlIikgXA0KbGlicmFyeSgiZHBseXIiKSBcDQpsaWJyYXJ5KCJtYWdyaXR0ciIpIFwNCmxpYnJhcnkoImx1YnJpZGF0ZSIpIFwNCg0KDQoNCiMjIGxpYnJhcnkocmVhZHIpIA0KDQppbnN0YWxsLnBhY2thZ2VzKHJlYWRyKSBcDQpsaWJyYXJ5KCJyZWFkciIpIFwNCg0KPGltZyBhbGlnbj0icmlnaHQiIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCJzcmM9Imh0dHBzOi8vcmVhZHIudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyI+DQoNClRoZSBnb2FsIG9mIHJlYWRyIGlzIHRvIHByb3ZpZGUgYSBmYXN0IGFuZCBmcmllbmRseSB3YXkgdG8gcmVhZCByZWN0YW5ndWxhciBkYXRhIGZyb20gZGVsaW1pdGVkIGZpbGVzLCBzdWNoIGFzIGNvbW1hLXNlcGFyYXRlZCB2YWx1ZXMgKENTVikgYW5kIHRhYi1zZXBhcmF0ZWQgdmFsdWVzIChUU1YpLiBJdCBpcyBkZXNpZ25lZCB0byBwYXJzZSBtYW55IHR5cGVzIG9mIGRhdGEgZm91bmQgaW4gdGhlIHdpbGQsIHdoaWxlIHByb3ZpZGluZyBhbiBpbmZvcm1hdGl2ZSBwcm9ibGVtIHJlcG9ydCB3aGVuIHBhcnNpbmcgbGVhZHMgdG8gdW5leHBlY3RlZCByZXN1bHRzLg0KDQojIyBsaWJyYXJ5KHRpZHl2ZXJzZSkNCg0KaW5zdGFsbC5wYWNrYWdlcyh0aWR5dmVyc2UpIFwNCmxpYnJhcnkoInRpZHl2ZXJzZSIpIFwNCg0KPGltZyBhbGlnbj0icmlnaHQiIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCJzcmM9Imh0dHBzOi8vd3d3LnRpZHl2ZXJzZS5vcmcvaW1hZ2VzL2hleC10aWR5dmVyc2UucG5nIj4NCg0KVGhlIHRpZHl2ZXJzZSBpcyBhIGNvbGxlY3Rpb24gb2Ygb3BlbiBzb3VyY2UgcGFja2FnZXMgZm9yIHRoZSBSIHByb2dyYW1taW5nIGxhbmd1YWdlIGludHJvZHVjZWQgYnkgSGFkbGV5IFdpY2toYW0gYW5kIGhpcyB0ZWFtIHRoYXQgInNoYXJlIGFuIHVuZGVybHlpbmcgZGVzaWduIHBoaWxvc29waHksIGdyYW1tYXIsIGFuZCBkYXRhIHN0cnVjdHVyZXMiIG9mIHRpZHkgZGF0YS4NCg0KDQojIyBkcGx5cg0KDQppbnN0YWxsLnBhY2thZ2VzKGRwbHlyKSBcDQpsaWJyYXJ5KCJkcGx5ciIpIFwNCg0KPGltZyBhbGlnbj0icmlnaHQiIHdpZHRoPSI1MCIgaGVpZ2h0PSI1MCJzcmM9Imh0dHBzOi8vZHBseXIudGlkeXZlcnNlLm9yZy9sb2dvLnBuZyI+DQoNCk9uZSBvZiB0aGUgY29yZSBwYWNrYWdlcyBvZiB0aGUgdGlkeXZlcnNlIGluIHRoZSBSIHByb2dyYW1taW5nIGxhbmd1YWdlLCBkcGx5ciBpcyBwcmltYXJpbHkgYSBzZXQgb2YgZnVuY3Rpb25zIGRlc2lnbmVkIHRvIGVuYWJsZSBkYXRhZnJhbWUgbWFuaXB1bGF0aW9uIGluIGFuIGludHVpdGl2ZSwgdXNlci1mcmllbmRseSB3YXkNCg0KDQojIyBtYWdyaXR0cg0KDQppbnN0YWxsLnBhY2thZ2VzKG1hZ3JpdHRyKSAgXA0KbGlicmFyeSgibWFncml0dHIiKSAgXA0KDQo8aW1nIGFsaWduPSJyaWdodCIgd2lkdGg9IjUwIiBoZWlnaHQ9IjUwInNyYz0iaHR0cHM6Ly9tYWdyaXR0ci50aWR5dmVyc2Uub3JnL2xvZ28ucG5nIj4NCg0KUHJvdmlkZXMgYSBtZWNoYW5pc20gZm9yIGNoYWluaW5nIGNvbW1hbmRzIHdpdGggYSBuZXcgZm9yd2FyZC1waXBlIG9wZXJhdG9yLCAlPiUuIFRoaXMgb3BlcmF0b3Igd2lsbCBmb3J3YXJkIGEgdmFsdWUsIG9yIHRoZSByZXN1bHQgb2YgYW4gZXhwcmVzc2lvbiwgaW50byB0aGUgbmV4dCBmdW5jdGlvbiBjYWxsL2V4cHJlc3Npb24uIFRoZXJlIGlzIGZsZXhpYmxlIHN1cHBvcnQgZm9yIHRoZSB0eXBlIG9mIHJpZ2h0LWhhbmQgc2lkZSBleHByZXNzaW9ucy4gRm9yIG1vcmUgaW5mb3JtYXRpb24sIHNlZSBwYWNrYWdlIHZpZ25ldHRlLiBUbyBxdW90ZSBSZW5lIE1hZ3JpdHRlLCAiQ2VjaSBuJ2VzdCBwYXMgdW4gcGlwZS4iIFwNCg0KDQojIyBsdWJyaWRhdGUNCg0KaW5zdGFsbC5wYWNrYWdlcyhsdWJyaWRhdGUpIFwNCmxpYnJhcnkoImx1YnJpZGF0ZSIpDQoNCjxpbWcgYWxpZ249InJpZ2h0IiB3aWR0aD0iNTAiIGhlaWdodD0iNTAic3JjPSJodHRwczovL2x1YnJpZGF0ZS50aWR5dmVyc2Uub3JnL2xvZ28ucG5nIj4NCg0KUiBjb21tYW5kcyBmb3IgZGF0ZS10aW1lcyBhcmUgZ2VuZXJhbGx5IHVuaW50dWl0aXZlIGFuZCBjaGFuZ2UgZGVwZW5kaW5nIG9uIHRoZSB0eXBlIG9mIGRhdGUtdGltZSBvYmplY3QgYmVpbmcgdXNlZC4gTW9yZW92ZXIsIHRoZSBtZXRob2RzIHdlIHVzZSB3aXRoIGRhdGUtdGltZXMgbXVzdCBiZSByb2J1c3QgdG8gdGltZSB6b25lcywgbGVhcCBkYXlzLCBkYXlsaWdodCBzYXZpbmdzIHRpbWVzLCBhbmQgb3RoZXIgdGltZSByZWxhdGVkIHF1aXJrcywgYW5kIFIgbGFja3MgdGhlc2UgY2FwYWJpbGl0aWVzIGluIHNvbWUgc2l0dWF0aW9ucy4gTHVicmlkYXRlIG1ha2VzIGl0IGVhc2llciB0byBkbyB0aGUgdGhpbmdzIFIgZG9lcyB3aXRoIGRhdGUtdGltZXMgYW5kIHBvc3NpYmxlIHRvIGRvIHRoZSB0aGluZ3MgUiBkb2VzIG5vdC4gXA0KDQoNCg0KIyBGaWxlIEltcG9ydA0KDQojIyBSZWFkIGluIC5jc3YgZmlsZQ0KDQpgYGB7cn0NCnJlY2lkLmRhdCA9IHJlYWQuY3N2KCJjb21wYXMudmlvbGVudC5jc3YiKSANCmBgYA0KDQoNCiMgRGF0YSBTdW1tYXJ5DQoNCg0KYGBge3J9DQphbW91bnQxIDwtIGxlbmd0aChyZWNpZC5kYXQpIA0KcHJpbnQocGFzdGUoInRoZXJlIGFyZSIsIGFtb3VudDEsICJjb2x1bW5zIGluIHRoZSByZWNpZC5kYXQgZmlsZSIpKQ0KYW1vdW50MiA8LSBucm93KHJlY2lkLmRhdCkNCnByaW50KHBhc3RlKCd0aGVyZSBhcmUnLCBhbW91bnQyLCAncm93cyBpbiB0aGUgcmVjaWQuZGF0IGZpbGUnKSkNCnRha2UwIDwtIHJlY2lkLmRhdFsxOjMsMTo2XQ0KYGBgDQoNCmByIHRha2UwYA0KDQoNCiMgTWFrZSBhIENvcHkgb2YgcmVjaWQuZGF0IA0KDQpgYGB7cn0NCmV4dGVybmFsLmRhdCA8LSByZWNpZC5kYXQNCmBgYA0KDQoNCiMgTnVtYmVyIG9mIERpc3RpbmN0IFZhbHVlcw0KDQpgYGB7cn0NCmluZGl2aWR1YWxzIDwtIGxlbmd0aCh1bmlxdWUocmVjaWQuZGF0JG5hbWUpKQ0KcHJpbnQocGFzdGUoJ3RoZXJlIGFyZScgLCBpbmRpdmlkdWFscywndW5pcXVlIGluZGl2aWR1YWxzJykpDQpgYGANCg0KDQojIEFzc2lnbmluZyBVbmlxdWUgSWRlbnRpZmllcg0KDQpgYGB7cn0NCm5ld19yZWNpZC5kYXQgPC0gY2JpbmQocmVjaWQuZGF0LCANCiAgICAgICAgICAgICAgICAgICAgICAgREVGSUQgPSBjKDUwMDA6OTc0MikpDQpuZXdfcmVjaWQuZGF0IDwtIG5ld19yZWNpZC5kYXRbLCBjKDIxLCAxOjIwKV0gIyBhc3NpZ25pbmcgREVGSUQgdG8gMXN0IGNvbHVtbg0KcHJpbnQoaGVhZChuZXdfcmVjaWQuZGF0WzE6MywxOjZdKSkNCg0KZXh0ZXJuYWwuZGF0IDwtIGNiaW5kKGV4dGVybmFsLmRhdCwgDQogICAgICAgICAgICAgICAgICAgICAgREVGSUQgPSBuZXdfcmVjaWQuZGF0JERFRklEKQ0KZXh0ZXJuYWwuZGF0IDwtIGV4dGVybmFsLmRhdFssIGMoMjEsIDE6MjApXSAgIyBhc3NpZ25pbmcgREVGSUQgdG8gMXN0IGNvbHVtbg0KdGFrZTEgPC0gcHJpbnQoaGVhZChleHRlcm5hbC5kYXRbMTozLDE6Nl0pKQ0KYGBgDQoNCg0KDQojIFJFTU9WRSBOQU1FIFJFTEFURUQgQ09MVU1OUw0KDQpgYGB7cn0NCmV4dGVybmFsLmRhdCA8LSBleHRlcm5hbC5kYXRbLC1jKDIsMyw0KV0NCnRha2UyIDwtIHByaW50KGhlYWQoZXh0ZXJuYWwuZGF0WzE6MywgMTo2XSkpDQpgYGANCg0KDQoNCiMgQUREIERFTEVURSBDT0xVTU4oUykNCg0KIyMgQWRkIEFHRUNBVCBWYXJpYWJsZSANCmBgYHtyfQ0Kb2xkZXN0IDwtIG1pbihleHRlcm5hbC5kYXQkZG9iKQ0KcHJpbnQocGFzdGUob2xkZXN0LCJpcyB0aGUgb2xkZXN0IGRhdGUgb2YgYmlydGgiKSkNCnlvdW5nZXN0IDwtIG1heChleHRlcm5hbC5kYXQkZG9iKQ0KcHJpbnQocGFzdGUoeW91bmdlc3QsImlzIHRoZSBtb3N0IHJlY2VudCBkYXRlIG9mIGJpcnRoIikpDQoNCg0KZXh0ZXJuYWwuZGF0JEFHRUNBVCA8LSBpZmVsc2UoZXh0ZXJuYWwuZGF0JGRvYiA8ICIxOTI0LTEyLTMxIiwgIkdyZWF0ZXN0IEdlbiIsDQogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShleHRlcm5hbC5kYXQkZG9iIDwgIjE5NDUtMTItMzEiLCAiU2lsZW50IEdlbiIsIA0KICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZXh0ZXJuYWwuZGF0JGRvYiA8ICIxOTY0LTEyLTMxIiwgIkJhYnkgQm9vbWVyIiwNCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGV4dGVybmFsLmRhdCRkb2IgPCAiMTk3OS0xMi0zMSIsICJHZW4gWCIsDQogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShleHRlcm5hbC5kYXQkZG9iIDwgIjE5OTQtMTItMzEiLCAiTWlsbGVuaWFscyIsDQogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShleHRlcm5hbC5kYXQkZG9iIDwgIjIwMTItMTItMzEiLCAiR2VuIFoiLA0KICAgICAgICAgICAgICAgICAgICAgICBpZmVsc2UoZXh0ZXJuYWwuZGF0JGRvYiA8ICIyMDI1LTEyLTMxIiwgIkdlbiBBbHBoYSIpKSkpKSkpDQpgYGAgICAgICAgICAgICAgICAgICAgICAgIA0KDQojIyBSZW1vdmUgYWdlICYgZG9iDQoNCmBgYHtyfQ0KZXh0ZXJuYWwuZGF0IDwtIGV4dGVybmFsLmRhdFssIGMoMTksIDE6MTgpXSAjcmVhc3NpZ24gbmV3IGNvbHVtbiBhcyBmaXJzdCBjb2x1bW4NCmV4dGVybmFsLmRhdCA8LSBleHRlcm5hbC5kYXRbLC1jKDUsNildDQojbGVuZ3RoKGV4dGVybmFsLmRhdCkgI2NoZWNrIGRhdGEgZnJhbWUgZGltZW5zaW9uIGlzIGNvcnJlY3QNCnRha2UzIDwtIHByaW50KGhlYWQoZXh0ZXJuYWwuZGF0WzE6My4sMToxMF0pKQ0KYGBgDQoNCg0KDQojIFJFQ09ERSBWQUxVRVMgT0YgQSBWQVJJQUJMRSANCg0KYGBge3IgcHJlc3N1cmUsIGVjaG89RkFMU0V9DQpleHRlcm5hbC5kYXQgPC0gZXh0ZXJuYWwuZGF0ICU+JQ0KICAgICAgICAgbXV0YXRlKGNfY2hhcmdlX2RlZ3JlZSA9IHJlY29kZShjX2NoYXJnZV9kZWdyZWUsIE0gPSAnTWlzZGVtZWFub3JzJywgRiA9ICdGZWxvbnknKSkNCg0KdGFrZTQgPC0gcHJpbnQoaGVhZChleHRlcm5hbC5kYXRbMTozLDE6N10pKSAjc2hvdyBjbGFzcyB2YXJpYWJsZSByZW5hbWVkDQoNCmBgYA0KDQoNCiMgUkVQTEFDRSBEQVRFVElNRSBDT0xVTU5TDQoNCiMjIFRyYW5zZm9ybSBEYXRlIHRvIERhdGUgT2JqZWN0DQoNCmBgYHtyfQ0KZXh0ZXJuYWwuZGF0JGNfamFpbF9vdXQgPC0geW1kX2htcyhleHRlcm5hbC5kYXQkY19qYWlsX291dCkgI2NvbnZlcnQgY2hhcmFjdGVyIHRvIHRpbWUgc3RhbXANCmV4dGVybmFsLmRhdCRjX2phaWxfaW4gPC0geW1kX2htcyhleHRlcm5hbC5kYXQkY19qYWlsX2luKSAgICNjb252ZXJ0IGNoYXJhY3RlciB0byB0aW1lIHN0YW1wDQpvdXRfb2ZfamFpbCA8LSBob3VyKGV4dGVybmFsLmRhdCRjX2phaWxfb3V0KSAgICAgICAgICAgICNjb252ZXJ0IHRpbWUgc3RhbXAgaW50byBob3VyIGZvcm1hdA0KaW5famFpbCA8LSBob3VyKGV4dGVybmFsLmRhdCRjX2phaWxfaW4pICAgICAgICAgICAgICAgICAjY29udmVydCB0aW1lIHN0YW1wIGludG8gaG91ciBmb3JtYXQNCmphaWxfaG91cnMgPC0gb3V0X29mX2phaWwgKyBpbl9qYWlsICAgICAgICAgICAgICNjYWxjdWxhdGUgdG90YWwgaG91cnMgYmV0d2VlbiBkYXRlIHZhcmlhYmxlDQoNCmxlbmd0aChleHRlcm5hbC5kYXQpDQpleHRlcm5hbC5kYXQgPC0gY2JpbmQoZXh0ZXJuYWwuZGF0LCBqYWlsX2hvdXJzID0gamFpbF9ob3VycykgI0FkZCBuZXcgY29sdW1uIHRvIGV4dGVybmFsLmRhdA0KZXh0ZXJuYWwuZGF0IDwtIGV4dGVybmFsLmRhdFssIGMoMTgsIDE6MTcpXSAgICAgICAgICAgICAgICNhc3NpZ24gbmV3IGNvbHVtbiB0byBmaXJzdCBjb2x1bW4NCnRha2U1IDwtIHByaW50KGhlYWQoZXh0ZXJuYWwuZGF0WzE6MywgMTo2XSkpDQpgYGANCg0KDQojIyBDcmVhdGUgSmFpbCBEYXlzIENvbHVtbg0KDQpgYGB7cn0NCmV4dGVybmFsLmRhdCRqYWlsX2RheXMgPC0gaWZlbHNlKGV4dGVybmFsLmRhdCRqYWlsX2hvdXJzIDwgMjMuOSwgMSwNCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGV4dGVybmFsLmRhdCRqYWlsX2hvdXJzID49IDI0LCAyLCANCiAgICAgICAgICAgICAgICAgICAgICAgaWZlbHNlKGV4dGVybmFsLmRhdCRqYWlsX2hvdXJzIDwgNDgsIDMsDQogICAgICAgICAgICAgICAgICAgICAgIGlmZWxzZShleHRlcm5hbC5kYXQkamFpbF9ob3VycyA8PSA3MiwgNA0KICAgICAgICAgICAgICAgICAgICAgICApKSkpDQoNCmV4dGVybmFsLmRhdCA8LSBleHRlcm5hbC5kYXRbLCBjKDE5LCAxOjE4KV0gIA0KdGFpbF8gPC0gdmlldyh0YWlsKGV4dGVybmFsLmRhdFs0NzQxOjQ3NDMsMTo2XSkpDQpoZWFkXyA8LSB2aWV3KGhlYWQoZXh0ZXJuYWwuZGF0WzE6MywxOjZdKSkNCmBgYA0KYHIgdGFpbF9gDQpgciBoZWFkX2ANCg0KDQojIEJpYmxpb2dyYXBoeQ0KDQpUaGlzIGFzc2lnbm1lbnQgYWJvdXQgcmVwbGljYXRpbmcgdGhlICoqQ09NUEFTKiogc29mdHdhcmUsIHdoaWNoIHVzZXMgYW4gYWxnb3JpdGhtIHRvIGFzc2VzcyBwb3RlbnRpYWwgcmVjaWRpdmlzbSByaXNrIFtSLTQuMi4yIGZvciBXaW5kb3dzXSgiaHR0cHM6Ly9jcmFuLnItcHJvamVjdC5vcmcvIikuICAgXA0KUiBpcyDigJhHTlUgU+KAmSwgYSBmcmVlbHkgYXZhaWxhYmxlIGxhbmd1YWdlIGFuZCBlbnZpcm9ubWVudCBmb3Igc3RhdGlzdGljYWwgY29tcHV0aW5nIGFuZCBncmFwaGljcyB3aGljaCBwcm92aWRlcyBhIHdpZGUgdmFyaWV0eSBvZiBzdGF0aXN0aWNhbCBhbmQgZ3JhcGhpY2FsIHRlY2huaXF1ZXMgc3VjaCBhcyBsaW5lYXIgYW5kIG5vbmxpbmVhciBtb2RlbGxpbmcsIHN0YXRpc3RpY2FsIHRlc3RzLCB0aW1lIHNlcmllcyBhbmFseXNpcywgY2xhc3NpZmljYXRpb24sIGNsdXN0ZXJpbmcsIGFuZCBpbiBvdXIgY2FzZTogaW4gbW9kZWxpbmcgdGhlIHJpc2sgYXNzZXNzbWVudCBzb2Z0d2FyZS4gXA0KDQpbQ09NUEFTXSgiaHR0cHM6Ly9lbi53aWtpcGVkaWEub3JnL3dpa2kvQ09NUEFTXyhzb2Z0d2FyZSkiKSAtIENvcnJlY3Rpb25hbCBPZmZlbmRlciBNYW5hZ2VtZW50IFByb2ZpbGluZyBmb3IgQWx0ZXJuYXRpdmUgU2FuY3Rpb25zIChDT01QQVMpIGlzIGEgY2FzZSBtYW5hZ2VtZW50IGFuZCBkZWNpc2lvbiBzdXBwb3J0IHRvb2wgZGV2ZWxvcGVkIGFuZCBvd25lZCBieSBOb3J0aHBvaW50ZSAobm93IEVxdWl2YW50KSB1c2VkIGJ5IFUuUy4gY291cnRzIHRvIGFzc2VzcyB0aGUgbGlrZWxpaG9vZCBvZiBhIGRlZmVuZGFudCBiZWNvbWluZyBhIHJlY2lkaXZpc3QuICBcDQpGb3IgYW4gaW4gZGVwdGggdW5kZXJzdGFuZGluZyBvZiB0aGUgbWV0aG9kb2xvZ3kgdXNlZCBpbiBDT01QQVMgcmlzayBhc3Nlc3NtZW50LCBJIHJlY29tbWVuZCB0aGUgW1ByYWN0aXRpb25lci1zLUd1aWRlLXRvLUNPTVBBUy1Db3JlXSgiaHR0cHM6Ly9zMy5kb2N1bWVudGNsb3VkLm9yZy9kb2N1bWVudHMvMjg0MDc4NC9QcmFjdGl0aW9uZXItcy1HdWlkZS10by1DT01QQVMtQ29yZS5wZGYiKSBoYW5kYm9vay4=