1 Installing Packages

1.1 COMPAS

Description: Conformational Manipulations of Protein Atomic Structures
install.packages(“compas”)
compas

library(“readr”)
library(“tidyverse”)
library(“dplyr”)
library(“magrittr”)
library(“lubridate”)

1.2 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.

1.3 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.

1.4 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

1.5 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.”

1.6 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.

2 File Import

2.1 Read in .csv file

recid.dat = read.csv("compas.violent.csv") 

3 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]

4 Make a Copy of recid.dat

external.dat <- recid.dat

5 Number of Distinct Values

individuals <- length(unique(recid.dat$name))
print(paste('there are' , individuals,'unique individuals'))
[1] "there are 4721 unique individuals"

6 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]))

8 ADD DELETE COLUMN(S)

8.1 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")))))))

8.2 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]))

9 RECODE VALUES OF A VARIABLE

10 REPLACE DATETIME COLUMNS

10.1 Transform Date to Date Object

external.dat$c_jail_out <- ymd_hms(external.dat$c_jail_out) #convert character to time stamp
external.dat$c_jail_in <- ymd_hms(external.dat$c_jail_in)   #convert character to time stamp
out_of_jail <- hour(external.dat$c_jail_out)            #convert time stamp into hour format
in_jail <- hour(external.dat$c_jail_in)                 #convert time stamp into hour format
jail_hours <- out_of_jail + in_jail             #calculate total hours between date variable

length(external.dat)
[1] 17
external.dat <- cbind(external.dat, jail_hours = jail_hours) #Add new column to external.dat
external.dat <- external.dat[, c(18, 1:17)]               #assign new column to first column
take5 <- print(head(external.dat[1:3, 1:6]))

10.2 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]))

11 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=