Julius Schmid
In-class activity 5
Good afternoon all! First let us find out what our working directory
is.
getwd()
[1] "/cloud/project"
Today we are going to query the table quiz2 by using Transact-SQL
inside the R chunks. First, we are going to need to install the package
sqldf.
install.packages("sqldf")
Error in install.packages : Updating loaded packages
We import our new downloaded library sqldf.
library(sqldf)
Loading required package: gsubfn
Loading required package: proto
Warning: couldn't connect to display ":0"Loading required package: RSQLite
We upload the csv file quiz2.csv and import it with the read.csv
function. Since in the data file we have headers, we set header = TRUE.
The separator in this file is a comma.
data1<-read.csv("quiz2.csv",header = TRUE,sep = ",")
We let us give out a summary of the data frame:
summary(data1)
subregion region pop income ipaddr
Length:29 Length:29 Min. : 2311 Min. :26784 Min. : 637
Class :character Class :character 1st Qu.: 19005 1st Qu.:37970 1st Qu.: 12294
Mode :character Mode :character Median : 32122 Median :41595 Median : 30418
Mean : 135940 Mean :43858 Mean : 440130
3rd Qu.: 101482 3rd Qu.:47469 3rd Qu.: 102104
Max. :1554720 Max. :70821 Max. :5394949
ufo2010 infections
Min. : 0.00 Min. : 39
1st Qu.: 0.00 1st Qu.: 123
Median : 2.00 Median : 245
Mean : 16.66 Mean :1117
3rd Qu.: 9.00 3rd Qu.: 672
Max. :169.00 Max. :6781
Let us run a query that returns every single record from the table
data1.
sqldf("SELECT * FROM data1")
Now I would like you to create a query that returns every single
record (row) for the fields region and population.
Let us create a query that returns the first 10 records of the data1
table.
sqldf('SELECT * FROM data1 LIMIT 10')
Next, select all columns from the data1 table, order it by the
parameter infections (from big to small) and return the first 5
columns.
sqldf("SELECT * FROM data1 ORDER BY infections DESC LIMIT 5")
Now run a similar query (limit 7) including the attributes ipadddr ,
ufo2010 ,and infections.
sqldf("SELECT ipaddr, ufo2010, infections FROM data1 ORDER BY infections DESC LIMIT 7")
In the next step, we return the columns region and infections, filter
all the rows where the number of infections is greater than 1000 and
sort the rows by infections from highn to low.
sqldf('SELECT region,infections FROM data1 WHERE infections > 1000 order by 2 desc')
Now I would like you to inspect (create a query) income,region and
population when the condition is income>=50,000. Make comments.
To do this, we select the columns income, region, and population
(pop) from data1 where the income is greater than or equal to
50,000.
sqldf('SELECT income, region, pop FROM data1 WHERE income >= 50000')
These are only six rows, representing Idaho, Colorado, Pennsylvania,
Vermont, California, and New York.
Next, we create a query to return the whole rows of data1 where
either, income is greater than 50000 and infections greater than 2000
(case 1), or the population is greater than 100000 (case 2). Since we
have two conditions for case 1, we use the AND operator and
parentheses.
sqldf('SELECT * FROM data1 WHERE (income > 50000 AND infections > 2000) OR pop > 100000')
Interpret the query ran above and create a query that recreates a
similar case scenario (one that is critical for the success of this
mini-project).
Similarly, let us return all the rows where either, income > 50000
and number of ufos > 40 (case 1), or number of infections >
1000.
sqldf('SELECT * FROM data1 WHERE (income > 50000 AND ufo2010 > 40) OR infections > 1000')
Let us run a query that returns every region and population with a
number of infections between 1000 and 7000.
sqldf('SELECT region,pop FROM data1 WHERE infections between 1000 and 7000')
Interpret the query below and list a hypothetical case scenario in
which this query would be useful.
In this query, we return all data of subregions that start with the
letter A. This could be useful if we have a loss of data and we are
looking for values of a specific subregion which we lost (e.g., NA). But
all we remember is that the subregion started with the letter A. We do
this with the LIKE command and state LIKE “A%” to filter all the rows
where subregion starts with an A.
sqldf('SELECT * FROM data1 WHERE subregion LIKE "A%"')
Last, let us find the average number of infections in our table.
sqldf("SELECT AVG(infections) FROM data1")
Let us inspect the new table defined below data2.
data2<-read.csv("finalexam.csv",header = TRUE,sep = ",")
Let us apply summary to data2 and examine the output.
summary(data2)
region pop income ipaddr
Length:29 Min. : 2311 Min. :26784 Min. : 637
Class :character 1st Qu.: 19005 1st Qu.:37970 1st Qu.: 12294
Mode :character Median : 32122 Median :41595 Median : 30418
Mean : 135940 Mean :43858 Mean : 440130
3rd Qu.: 101482 3rd Qu.:47469 3rd Qu.: 102104
Max. :1554720 Max. :70821 Max. :5394949
ufo2010 infections
Min. : 0.00 Min. : 39
1st Qu.: 0.00 1st Qu.: 123
Median : 2.00 Median : 245
Mean : 16.66 Mean :1117
3rd Qu.: 9.00 3rd Qu.: 672
Max. :169.00 Max. :6781
Next, I would like you to complete the following steps:
1 - Run a query that returns full details for every record from the
west region.
We select all columns (*) of the data2 table and filter the region to
“West”.
sqldf('SELECT * FROM data2 WHERE region == "West"')
2 - Run a query that returns full details for every record from the
east region where the number of infections is greater than 1500.
We select all columns (*) of the data2 table and add a filter where
the region is set to “East” and the infections to greater than 1500 at
the same time (AND).
sqldf('SELECT * FROM data2 WHERE region == "East" AND infections > 1500')
3 - Run a few queries that can potentially help us to make the point
that:
- Region affects the number of infections
Select the columns region and infections, and sort by infections
(high to low):
sqldf('SELECT region, infections FROM data2 ORDER BY infections DESC')
The most infections seem to appear in the West region.
- Population affects the number of infections
Select the pop and infections columns, order by infections (high to
low).
sqldf('SELECT pop, infections FROM data2 ORDER BY infections DESC')
- Income affects the number of infections
Select the income and infections columns, order by infections (high
to low).
sqldf('SELECT income, infections FROM data2 ORDER BY infections DESC')
- ufo2010 affects the number of infections
Select the ufo2010 and infections columns, order by infections (high
to low).
sqldf('SELECT ufo2010, infections FROM data2 ORDER BY infections DESC')
- The different interactions of region and income, and income and
population affects the number of infections.
Select the columns region, income, population, and infections, and
order by infections (high to low).
sqldf('SELECT region, income, pop, infections FROM data2 ORDER BY infections DESC')
LS0tCnRpdGxlOiAiUiBTUUwiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KSnVsaXVzIFNjaG1pZAoKSW4tY2xhc3MgYWN0aXZpdHkgNSAKCgpHb29kIGFmdGVybm9vbiBhbGwhIEZpcnN0IGxldCB1cyBmaW5kIG91dCB3aGF0IG91ciB3b3JraW5nIGRpcmVjdG9yeSBpcy4KYGBge3J9CmdldHdkKCkKYGBgCgpUb2RheSB3ZSBhcmUgZ29pbmcgdG8gcXVlcnkgdGhlIHRhYmxlIHF1aXoyIGJ5IHVzaW5nIFRyYW5zYWN0LVNRTCBpbnNpZGUgdGhlIFIgY2h1bmtzLiBGaXJzdCwgd2UgYXJlIGdvaW5nIHRvIG5lZWQgdG8gaW5zdGFsbCB0aGUgcGFja2FnZSAqKipzcWxkZioqKi4gCmBgYHtyfQppbnN0YWxsLnBhY2thZ2VzKCJzcWxkZiIpCmBgYAoKV2UgaW1wb3J0IG91ciBuZXcgZG93bmxvYWRlZCBsaWJyYXJ5IHNxbGRmLgpgYGB7cn0KbGlicmFyeShzcWxkZikKYGBgCldlIHVwbG9hZCB0aGUgY3N2IGZpbGUgcXVpejIuY3N2IGFuZCBpbXBvcnQgaXQgd2l0aCB0aGUgcmVhZC5jc3YgZnVuY3Rpb24uIFNpbmNlIGluIHRoZSBkYXRhIGZpbGUgd2UgaGF2ZSBoZWFkZXJzLCB3ZSBzZXQgaGVhZGVyID0gVFJVRS4gVGhlIHNlcGFyYXRvciBpbiB0aGlzIGZpbGUgaXMgYSBjb21tYS4KYGBge3J9CmRhdGExPC1yZWFkLmNzdigicXVpejIuY3N2IixoZWFkZXIgPSBUUlVFLHNlcCA9ICIsIikKYGBgCgpXZSBsZXQgdXMgZ2l2ZSBvdXQgYSBzdW1tYXJ5IG9mIHRoZSBkYXRhIGZyYW1lOgpgYGB7cn0Kc3VtbWFyeShkYXRhMSkKYGBgCgpMZXQgdXMgcnVuIGEgcXVlcnkgdGhhdCByZXR1cm5zIGV2ZXJ5IHNpbmdsZSByZWNvcmQgZnJvbSB0aGUgdGFibGUgZGF0YTEuCmBgYHtyfQpzcWxkZigiU0VMRUNUICogRlJPTSBkYXRhMSIpCmBgYAoKTm93IEkgd291bGQgbGlrZSB5b3UgdG8gY3JlYXRlIGEgcXVlcnkgdGhhdCByZXR1cm5zIGV2ZXJ5IHNpbmdsZSByZWNvcmQgKHJvdykgZm9yIHRoZSBmaWVsZHMgcmVnaW9uIGFuZCBwb3B1bGF0aW9uLgoKTGV0IHVzIGNyZWF0ZSBhIHF1ZXJ5IHRoYXQgcmV0dXJucyB0aGUgZmlyc3QgMTAgcmVjb3JkcyBvZiB0aGUgZGF0YTEgdGFibGUuCmBgYHtyfQpzcWxkZignU0VMRUNUICogRlJPTSBkYXRhMSBMSU1JVCAxMCcpCmBgYAoKTmV4dCwgc2VsZWN0IGFsbCBjb2x1bW5zIGZyb20gdGhlIGRhdGExIHRhYmxlLCBvcmRlciBpdCBieSB0aGUgcGFyYW1ldGVyIGluZmVjdGlvbnMgKGZyb20gYmlnIHRvIHNtYWxsKSBhbmQgcmV0dXJuIHRoZSBmaXJzdCA1IGNvbHVtbnMuCmBgYHtyfQpzcWxkZigiU0VMRUNUICogRlJPTSBkYXRhMSBPUkRFUiBCWSBpbmZlY3Rpb25zIERFU0MgIExJTUlUIDUiKQpgYGAKCk5vdyBydW4gYSBzaW1pbGFyIHF1ZXJ5IChsaW1pdCA3KSBpbmNsdWRpbmcgdGhlIGF0dHJpYnV0ZXMgaXBhZGRkciAsIHVmbzIwMTAgLGFuZCBpbmZlY3Rpb25zLgpgYGB7cn0Kc3FsZGYoIlNFTEVDVCBpcGFkZHIsIHVmbzIwMTAsIGluZmVjdGlvbnMgRlJPTSBkYXRhMSBPUkRFUiBCWSBpbmZlY3Rpb25zIERFU0MgIExJTUlUIDciKQpgYGAKCkluIHRoZSBuZXh0IHN0ZXAsIHdlIHJldHVybiB0aGUgY29sdW1ucyByZWdpb24gYW5kIGluZmVjdGlvbnMsIGZpbHRlciBhbGwgdGhlIHJvd3Mgd2hlcmUgdGhlIG51bWJlciBvZiBpbmZlY3Rpb25zIGlzIGdyZWF0ZXIgdGhhbiAxMDAwIGFuZCBzb3J0IHRoZSByb3dzIGJ5IGluZmVjdGlvbnMgZnJvbSBoaWdobiB0byBsb3cuCmBgYHtyfQpzcWxkZignU0VMRUNUIHJlZ2lvbixpbmZlY3Rpb25zIEZST00gZGF0YTEgV0hFUkUgaW5mZWN0aW9ucyA+IDEwMDAgb3JkZXIgYnkgMiBkZXNjJykKYGBgCgpOb3cgSSB3b3VsZCBsaWtlIHlvdSB0byBpbnNwZWN0IChjcmVhdGUgYSBxdWVyeSkgaW5jb21lLHJlZ2lvbiBhbmQgcG9wdWxhdGlvbiB3aGVuIHRoZSBjb25kaXRpb24gaXMgaW5jb21lPj01MCwwMDAuIE1ha2UgY29tbWVudHMuCgpUbyBkbyB0aGlzLCB3ZSBzZWxlY3QgdGhlIGNvbHVtbnMgaW5jb21lLCByZWdpb24sIGFuZCBwb3B1bGF0aW9uIChwb3ApIGZyb20gZGF0YTEgd2hlcmUgdGhlIGluY29tZSBpcyBncmVhdGVyIHRoYW4gb3IgZXF1YWwgdG8gNTAsMDAwLgpgYGB7cn0Kc3FsZGYoJ1NFTEVDVCBpbmNvbWUsIHJlZ2lvbiwgcG9wIEZST00gZGF0YTEgV0hFUkUgaW5jb21lID49IDUwMDAwJykKYGBgClRoZXNlIGFyZSBvbmx5IHNpeCByb3dzLCByZXByZXNlbnRpbmcgSWRhaG8sIENvbG9yYWRvLCBQZW5uc3lsdmFuaWEsIFZlcm1vbnQsIENhbGlmb3JuaWEsIGFuZCBOZXcgWW9yay4KCgpOZXh0LCB3ZSBjcmVhdGUgYSBxdWVyeSB0byByZXR1cm4gdGhlIHdob2xlIHJvd3Mgb2YgZGF0YTEgd2hlcmUgZWl0aGVyLCBpbmNvbWUgaXMgZ3JlYXRlciB0aGFuIDUwMDAwIGFuZCBpbmZlY3Rpb25zIGdyZWF0ZXIgdGhhbiAyMDAwIChjYXNlIDEpLCBvciB0aGUgcG9wdWxhdGlvbiBpcyBncmVhdGVyIHRoYW4gMTAwMDAwIChjYXNlIDIpLiBTaW5jZSB3ZSBoYXZlIHR3byBjb25kaXRpb25zIGZvciBjYXNlIDEsIHdlIHVzZSB0aGUgQU5EIG9wZXJhdG9yIGFuZCBwYXJlbnRoZXNlcy4KYGBge3J9CnNxbGRmKCdTRUxFQ1QgKiBGUk9NIGRhdGExIFdIRVJFIChpbmNvbWUgPiA1MDAwMCBBTkQgaW5mZWN0aW9ucyA+IDIwMDApIE9SIHBvcCA+IDEwMDAwMCcpCmBgYApJbnRlcnByZXQgdGhlIHF1ZXJ5IHJhbiBhYm92ZSBhbmQgY3JlYXRlIGEgcXVlcnkgdGhhdCByZWNyZWF0ZXMgYSBzaW1pbGFyIGNhc2Ugc2NlbmFyaW8gKG9uZSB0aGF0IGlzIGNyaXRpY2FsIGZvciB0aGUgc3VjY2VzcyBvZiB0aGlzIG1pbmktcHJvamVjdCkuCgpTaW1pbGFybHksIGxldCB1cyByZXR1cm4gYWxsIHRoZSByb3dzIHdoZXJlIGVpdGhlciwgaW5jb21lID4gNTAwMDAgYW5kIG51bWJlciBvZiB1Zm9zID4gNDAgKGNhc2UgMSksIG9yIG51bWJlciBvZiBpbmZlY3Rpb25zID4gMTAwMC4KYGBge3J9CnNxbGRmKCdTRUxFQ1QgKiBGUk9NIGRhdGExIFdIRVJFIChpbmNvbWUgPiA1MDAwMCBBTkQgdWZvMjAxMCA+IDQwKSBPUiBpbmZlY3Rpb25zID4gMTAwMCcpCmBgYAoKTGV0IHVzIHJ1biBhIHF1ZXJ5IHRoYXQgcmV0dXJucyBldmVyeSByZWdpb24gYW5kIHBvcHVsYXRpb24gd2l0aCBhIG51bWJlciBvZiBpbmZlY3Rpb25zIGJldHdlZW4gMTAwMCBhbmQgNzAwMC4KYGBge3J9CnNxbGRmKCdTRUxFQ1QgcmVnaW9uLHBvcCBGUk9NIGRhdGExIFdIRVJFIGluZmVjdGlvbnMgYmV0d2VlbiAgMTAwMCBhbmQgNzAwMCcpCmBgYAoKSW50ZXJwcmV0IHRoZSBxdWVyeSBiZWxvdyBhbmQgbGlzdCBhIGh5cG90aGV0aWNhbCBjYXNlIHNjZW5hcmlvIGluIHdoaWNoIHRoaXMgcXVlcnkgd291bGQgYmUgdXNlZnVsLgoKSW4gdGhpcyBxdWVyeSwgd2UgcmV0dXJuIGFsbCBkYXRhIG9mIHN1YnJlZ2lvbnMgdGhhdCBzdGFydCB3aXRoIHRoZSBsZXR0ZXIgQS4gVGhpcyBjb3VsZCBiZSB1c2VmdWwgaWYgd2UgaGF2ZSBhIGxvc3Mgb2YgZGF0YSBhbmQgd2UgYXJlIGxvb2tpbmcgZm9yIHZhbHVlcyBvZiBhIHNwZWNpZmljIHN1YnJlZ2lvbiB3aGljaCB3ZSBsb3N0IChlLmcuLCBOQSkuIEJ1dCBhbGwgd2UgcmVtZW1iZXIgaXMgdGhhdCB0aGUgc3VicmVnaW9uIHN0YXJ0ZWQgd2l0aCB0aGUgbGV0dGVyIEEuIFdlIGRvIHRoaXMgd2l0aCB0aGUgTElLRSBjb21tYW5kIGFuZCBzdGF0ZSBMSUtFICJBJSIgdG8gZmlsdGVyIGFsbCB0aGUgcm93cyB3aGVyZSBzdWJyZWdpb24gc3RhcnRzIHdpdGggYW4gQS4KYGBge3J9CnNxbGRmKCdTRUxFQ1QgKiBGUk9NIGRhdGExIFdIRVJFIHN1YnJlZ2lvbiBMSUtFICJBJSInKQpgYGAKCkxhc3QsIGxldCB1cyBmaW5kIHRoZSBhdmVyYWdlIG51bWJlciBvZiBpbmZlY3Rpb25zIGluIG91ciB0YWJsZS4KYGBge3J9CnNxbGRmKCJTRUxFQ1QgQVZHKGluZmVjdGlvbnMpIEZST00gZGF0YTEiKQpgYGAKCgpMZXQgdXMgaW5zcGVjdCB0aGUgbmV3IHRhYmxlIGRlZmluZWQgYmVsb3cgZGF0YTIuCmBgYHtyfQpkYXRhMjwtcmVhZC5jc3YoImZpbmFsZXhhbS5jc3YiLGhlYWRlciA9IFRSVUUsc2VwID0gIiwiKQpgYGAKCkxldCB1cyBhcHBseSBzdW1tYXJ5IHRvIGRhdGEyIGFuZCBleGFtaW5lIHRoZSBvdXRwdXQuCmBgYHtyfQpzdW1tYXJ5KGRhdGEyKQpgYGAKCk5leHQsIEkgd291bGQgbGlrZSB5b3UgdG8gY29tcGxldGUgdGhlIGZvbGxvd2luZyBzdGVwczoKCjEgLSBSdW4gYSBxdWVyeSB0aGF0IHJldHVybnMgZnVsbCBkZXRhaWxzIGZvciBldmVyeSByZWNvcmQgZnJvbSB0aGUgd2VzdCByZWdpb24uCgpXZSBzZWxlY3QgYWxsIGNvbHVtbnMgKCopIG9mIHRoZSBkYXRhMiB0YWJsZSBhbmQgZmlsdGVyIHRoZSByZWdpb24gdG8gIldlc3QiLgpgYGB7cn0Kc3FsZGYoJ1NFTEVDVCAqIEZST00gZGF0YTIgV0hFUkUgcmVnaW9uID09ICJXZXN0IicpCmBgYAoKMiAtIFJ1biBhIHF1ZXJ5IHRoYXQgcmV0dXJucyBmdWxsIGRldGFpbHMgZm9yIGV2ZXJ5IHJlY29yZCBmcm9tIHRoZSBlYXN0IHJlZ2lvbiB3aGVyZSB0aGUgbnVtYmVyIG9mIGluZmVjdGlvbnMgaXMgZ3JlYXRlciB0aGFuIDE1MDAuCgpXZSBzZWxlY3QgYWxsIGNvbHVtbnMgKCopIG9mIHRoZSBkYXRhMiB0YWJsZSBhbmQgYWRkIGEgZmlsdGVyIHdoZXJlIHRoZSByZWdpb24gaXMgc2V0IHRvICJFYXN0IiBhbmQgdGhlIGluZmVjdGlvbnMgdG8gZ3JlYXRlciB0aGFuIDE1MDAgYXQgdGhlIHNhbWUgdGltZSAoQU5EKS4KYGBge3J9CnNxbGRmKCdTRUxFQ1QgKiBGUk9NIGRhdGEyIFdIRVJFIHJlZ2lvbiA9PSAiRWFzdCIgQU5EIGluZmVjdGlvbnMgPiAxNTAwJykKYGBgCgozIC0gUnVuIGEgZmV3IHF1ZXJpZXMgdGhhdCBjYW4gcG90ZW50aWFsbHkgaGVscCB1cyB0byBtYWtlIHRoZSBwb2ludCB0aGF0OiAKCmEuIFJlZ2lvbiBhZmZlY3RzIHRoZSBudW1iZXIgb2YgaW5mZWN0aW9ucyAKClNlbGVjdCB0aGUgY29sdW1ucyByZWdpb24gYW5kIGluZmVjdGlvbnMsIGFuZCBzb3J0IGJ5IGluZmVjdGlvbnMgKGhpZ2ggdG8gbG93KToKYGBge3J9CnNxbGRmKCdTRUxFQ1QgcmVnaW9uLCBpbmZlY3Rpb25zIEZST00gZGF0YTIgT1JERVIgQlkgaW5mZWN0aW9ucyBERVNDJykKYGBgClRoZSBtb3N0IGluZmVjdGlvbnMgc2VlbSB0byBhcHBlYXIgaW4gdGhlIFdlc3QgcmVnaW9uLgoKYi4gUG9wdWxhdGlvbiBhZmZlY3RzIHRoZSBudW1iZXIgb2YgaW5mZWN0aW9ucyAKClNlbGVjdCB0aGUgcG9wIGFuZCBpbmZlY3Rpb25zIGNvbHVtbnMsIG9yZGVyIGJ5IGluZmVjdGlvbnMgKGhpZ2ggdG8gbG93KS4KYGBge3J9CnNxbGRmKCdTRUxFQ1QgcG9wLCBpbmZlY3Rpb25zIEZST00gZGF0YTIgT1JERVIgQlkgaW5mZWN0aW9ucyBERVNDJykKYGBgCgoKYy4gSW5jb21lIGFmZmVjdHMgdGhlIG51bWJlciBvZiBpbmZlY3Rpb25zCgpTZWxlY3QgdGhlIGluY29tZSBhbmQgaW5mZWN0aW9ucyBjb2x1bW5zLCBvcmRlciBieSBpbmZlY3Rpb25zIChoaWdoIHRvIGxvdykuCmBgYHtyfQpzcWxkZignU0VMRUNUIGluY29tZSwgaW5mZWN0aW9ucyBGUk9NIGRhdGEyIE9SREVSIEJZIGluZmVjdGlvbnMgREVTQycpCmBgYAoKCmQuIHVmbzIwMTAgYWZmZWN0cyB0aGUgbnVtYmVyIG9mIGluZmVjdGlvbnMgCgpTZWxlY3QgdGhlIHVmbzIwMTAgYW5kIGluZmVjdGlvbnMgY29sdW1ucywgb3JkZXIgYnkgaW5mZWN0aW9ucyAoaGlnaCB0byBsb3cpLgpgYGB7cn0Kc3FsZGYoJ1NFTEVDVCB1Zm8yMDEwLCBpbmZlY3Rpb25zIEZST00gZGF0YTIgT1JERVIgQlkgaW5mZWN0aW9ucyBERVNDJykKYGBgCgoKZS4gVGhlIGRpZmZlcmVudCBpbnRlcmFjdGlvbnMgb2YgcmVnaW9uIGFuZCBpbmNvbWUsIGFuZCBpbmNvbWUgYW5kIHBvcHVsYXRpb24gYWZmZWN0cyB0aGUgbnVtYmVyIG9mIGluZmVjdGlvbnMuCgpTZWxlY3QgdGhlIGNvbHVtbnMgcmVnaW9uLCBpbmNvbWUsIHBvcHVsYXRpb24sIGFuZCBpbmZlY3Rpb25zLCBhbmQgb3JkZXIgYnkgaW5mZWN0aW9ucyAoaGlnaCB0byBsb3cpLgpgYGB7cn0Kc3FsZGYoJ1NFTEVDVCByZWdpb24sIGluY29tZSwgcG9wLCBpbmZlY3Rpb25zIEZST00gZGF0YTIgT1JERVIgQlkgaW5mZWN0aW9ucyBERVNDJykKYGBgCg==