作業二

library(rvest)
ltn <- 'http://news.ltn.com.tw/list/BreakingNews'
lipic <- read_html(ltn) %>% html_nodes('.lipic')
title    <- lipic %>% html_nodes('a.picword') %>% html_text()
url      <- lipic %>% html_nodes('a.picword') %>% html_attr('href')
dt       <- lipic %>% html_nodes('span') %>% html_text()
ltn_news <- data.frame('datetime' = dt, 'title' = title, 'url' = url)
ltn_news
#write.csv(x= ltn_news, file='ltnnews.csv')

資料庫語句

## Create Table
CREATE TABLE customer(
id int AUTO_INCREMENT PRIMARY KEY,
name varchar(50),
gender varchar(1),
address varchar(200)
) ENGINE=InnoDB;

## Alter Table
ALTER TABLE customer CHANGE COLUMN name cname VARCHAR(50) NOT NULL,ADD COLUMN phone VARCHAR(10);

## Describe Schema
DESCRIBE customer;


## Data Insert
INSERT INTO customer(cname,gender,address)
VALUES('John','M','Chiayi');


SELECT * FROM customer;

INSERT INTO customer(cname,gender,address)
VALUES('John1','UNKNOWN','Chiayi');

INSERT INTO customer(cname,gender,address)
VALUES('Mary','F','Tainan');

INSERT INTO customer(cname,gender,address)
VALUES('Brad','M','Chiayi');

## Data Update
UPDATE customer SET cname = 'Johnny' WHERE id = 1;

## Data Select
SELECT * FROM customer;
SELECT cname, gender FROM customer;
SELECT cname, gender FROM customer WHERE gender ='M';

## Data Aggregation with GROUP BY and HAVING
SELECT COUNT(*) FROM customer;
SELECT COUNT(*) FROM customer WHERE gender = 'M';
SELECT COUNT(*) FROM customer WHERE gender = 'F';

SELECT gender, COUNT(*) FROM customer GROUP BY gender;

SELECT gender, COUNT(*) FROM customer 
GROUP BY gender HAVING COUNT(*) >= 2;

進階議題

show engines
SHOW DATABASES;

## Information Schema
USE information_schema;
SHOW TABLES;

SELECT * FROM INFORMATION_SCHEMA.SCHEMATA

SELECT * FROM INFORMATION_SCHEMA.TABLES 
WHERE TABLE_SCHEMA = 'orders';

SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_SCHEMA = 'orders';

## Create Index
create index idx_customer on customer(cname);
create index idx_customer2 on customer(cname,gender);
create index idx_customer3 on customer(cname) using BTREE;

## Delete, Truncate, Drop
DELETE FROM customer WHERE id =1;
DELETE FROM customer;

truncate customer;
select * from customer;
drop table customer;

使用R 連結MySQL

if(dbExistsTable(conn,'iris')){
  dbRemoveTable(conn, 'iris')
  }
logical(0)

讀取蘋果新聞資料

download.file('https://raw.githubusercontent.com/ywchiu/rtibame/master/data/applenews.RData', 'applenews.RData')
trying URL 'https://raw.githubusercontent.com/ywchiu/rtibame/master/data/applenews.RData'
Content type 'application/octet-stream' length 1044040 bytes (1019 KB)
downloaded 1019 KB
load('applenews.RData')
library(RJDBC)
jar.loc<-'C:\\Program Files (x86)\\MySQL\\Connector.J 5.1\\mysql-connector-java-5.1.39-bin.jar'
drv<-JDBC("com.mysql.jdbc.Driver",jar.loc,identifier.quote="`")
conn <-dbConnect(drv, "jdbc:mysql://localhost/appledaily", "root", "test")
if(dbExistsTable(conn, 'news_main')){
  dbRemoveTable(conn, 'news_main')
}
logical(0)
dbSendUpdate(conn, 'CREATE TABLE news_main (
id       int(11) NOT NULL AUTO_INCREMENT,
content  text,
title    varchar(1000)DEFAULT NULL,
dt       datetime DEFAULT NULL,
category varchar(1000)DEFAULT NULL,
view_cnt int(11)DEFAULT NULL,
PRIMARY KEY(id)
)ENGINE=InnoDB;')
applenews <- cbind(id=1:nrow(applenews), applenews)
dbWriteTable(conn, 'news_main', applenews, append=TRUE,row.names=TRUE,overwrite=FALSE)
[1] TRUE
news <- dbReadTable(conn, 'news_main')
res <-dbGetQuery(conn, 
"SELECT category, count(*) AS cnt FROM news_main
GROUP BY category ORDER BY COUNT(*) DESC")
pie(res$cnt, labels = res$category)

barplot(res$cnt, names.arg = res$category, col=as.factor(res$category))

#?barplot
dbSendUpdate(conn, 'drop table news_main;')
dbDisconnect(conn)
[1] TRUE
USE appledaily;
DESCRIBE applenews;


CREATE TABLE news_main (
id       int(11) NOT NULL AUTO_INCREMENT,
content  text,
title    varchar(1000)DEFAULT NULL,
dt       datetime DEFAULT NULL,
category varchar(1000)DEFAULT NULL,
view_cnt int(11)DEFAULT NULL,
PRIMARY KEY(id)
)ENGINE=InnoDB;

使用dplyr

# R Style
applenews[applenews$category == '3C'  ,   ]
Warning message:
In strsplit(code, "\n", fixed = TRUE) :
  input string 1 is invalid in this locale
library(dplyr)
# dplyr Style
filter(applenews, category=="3C")
# R Style
applenews[applenews$category == '3C' & applenews$view_cnt > 1000  ,   ]
# dplyr Style
filter(applenews, category=="3C"&view_cnt>1000)
filter(applenews, category%in%c("3C"))
# R Style
applenews[, c("category","view_cnt")]
# dplyr Style
select(applenews, category, view_cnt)
# R Style
applenews[applenews$category=="3C", c('category', 'view_cnt')]
# dplyr Style
applenews %>% 
  select(category,view_cnt) %>%
  filter(category=="3C")
## SELECT category, view_cnt 
## FROM applenews
## WHERE category = <e2>€<9c>3C<e2>€<9d>
## ORDER BY view_cnt
# R Style
applenews$view_cnt <- as.numeric(applenews$view_cnt)
a <- applenews[applenews$category=='3C',c('category', 'view_cnt')]
a[order(a$view_cnt, decreasing = TRUE),]
# dplyr Style
applenews %>% select(category, view_cnt) %>%
  filter(category=='3C') %>% arrange(desc(view_cnt))
# mutate
freqsum <- applenews %>% select(view_cnt) %>% sum()
freqsum
[1] 21574014
applenews %>% 
  select(title,category,view_cnt) %>%    
  mutate(portion=view_cnt/freqsum)
applenews <- applenews %>% mutate(portion=view_cnt/freqsum)
head(applenews)
# Group By 
## R Style
tapply(applenews$view_cnt, applenews$category, sum)
                      3C 
                  146308 
                    甇<a3>憒<b9> 
                  672949 
                    <e7><94>暑 
                 3417804 
                    <e5><e7> 
                  220812 
                    蝷暹<9c><83> 
                 5721750 
                    <e6>瘝<bb> 
                 1701980 
                    憡<a8><82> 
                 3571005 
                    <e6><99><b0><9a> 
                  260499 
                    鞎∠<b6><93> 
                  618243 
                    <e5><8b> 
                  123287 
                    <e5><9c><9a><9b> 
                 2485621 
<e5><9c><9a><9b>","LA","SF","NY","US 
                   43627 
          <e5><9c><9a><9b>","SF","US 
                   11163 
                    <e6><90><a5><87> 
                  668307 
                    隢<a3><87> 
                  312592 
                    擃 
                 1598067 
applenews %>% select(view_cnt, category) %>%
  group_by(category) %>% summarise(view_sum = sum(view_cnt)) %>% arrange(desc(view_sum))
applenews %>% select(view_cnt, category) %>%
  group_by(category) %>% summarise(view_mean = mean(view_cnt)) %>% arrange(desc(view_mean)) %>% filter(view_mean > 20000)
applenews %>% group_by(category) %>% summarise_each(funs(sum), view_cnt, portion) %>% arrange(desc(portion))
applenews %>% group_by(category) %>% summarise_each(funs(min(., na.rm=TRUE), max(., na.rm=TRUE)), matches("view_cnt"))
## Count Data
## select count(category) from applenews
applenews%>%select(category)%>%summarise_each(funs(n()))
## select count(distinct(category)) from applenews
applenews%>%select(category)%>%summarise_each(funs(n_distinct(category)))
cat_stat <- applenews %>% group_by(category) %>% summarise(view_sum=sum(view_cnt)) %>% arrange(desc(view_sum))
barplot(cat_stat$view_sum, names.arg = cat_stat$category, col = factor(cat_stat$category))

pie(cat_stat$view_sum, label =cat_stat$category)

Homework 3

download.file('https://github.com/ywchiu/rtibame/raw/master/Data/purchase.csv', 'purchase.csv')
trying URL 'https://github.com/ywchiu/rtibame/raw/master/Data/purchase.csv'
Content type 'text/plain; charset=utf-8' length 3497968 bytes (3.3 MB)
downloaded 3.3 MB
purchase <- read.csv('purchase.csv', header=TRUE, stringsAsFactors = FALSE)
View(purchase)
str(purchase)
'data.frame':   54772 obs. of  7 variables:
 $ X       : int  0 1 2 3 4 5 6 7 8 9 ...
 $ Time    : chr  "2015-07-01 00:00:01" "2015-07-01 00:00:03" "2015-07-01 00:00:19" "2015-07-01 00:01:10" ...
 $ Action  : chr  "order" "order" "order" "order" ...
 $ User    : chr  "U312622727" "U239012343" "U10007697373" "U296328517" ...
 $ Product : chr  "P0006944501" "P0006018073" "P0002267974" "P0016144236" ...
 $ Quantity: int  1 1 1 1 1 1 1 1 1 1 ...
 $ Price   : num  1069 1680 285 550 249 ...
purchase$Time <- as.POSIXct(purchase$Time)
#strftime(purchase$Time, '%H:%M')
LS0tDQp0aXRsZTogIkRlbW8yMDE2MTEyNiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNCiMjIOS9nOalreS6jA0KYGBge3J9DQpsaWJyYXJ5KHJ2ZXN0KQ0KbHRuIDwtICdodHRwOi8vbmV3cy5sdG4uY29tLnR3L2xpc3QvQnJlYWtpbmdOZXdzJw0KDQpsaXBpYyA8LSByZWFkX2h0bWwobHRuKSAlPiUgaHRtbF9ub2RlcygnLmxpcGljJykNCg0KdGl0bGUgICAgPC0gbGlwaWMgJT4lIGh0bWxfbm9kZXMoJ2EucGljd29yZCcpICU+JSBodG1sX3RleHQoKQ0KdXJsICAgICAgPC0gbGlwaWMgJT4lIGh0bWxfbm9kZXMoJ2EucGljd29yZCcpICU+JSBodG1sX2F0dHIoJ2hyZWYnKQ0KDQpkdCAgICAgICA8LSBsaXBpYyAlPiUgaHRtbF9ub2Rlcygnc3BhbicpICU+JSBodG1sX3RleHQoKQ0KDQpsdG5fbmV3cyA8LSBkYXRhLmZyYW1lKCdkYXRldGltZScgPSBkdCwgJ3RpdGxlJyA9IHRpdGxlLCAndXJsJyA9IHVybCkNCmx0bl9uZXdzDQoNCiN3cml0ZS5jc3YoeD0gbHRuX25ld3MsIGZpbGU9J2x0bm5ld3MuY3N2JykNCmBgYA0KIyMg6LOH5paZ5bqr6Kqe5Y+lDQpgYGANCiMjIENyZWF0ZSBUYWJsZQ0KQ1JFQVRFIFRBQkxFIGN1c3RvbWVyKA0KaWQgaW50IEFVVE9fSU5DUkVNRU5UIFBSSU1BUlkgS0VZLA0KbmFtZSB2YXJjaGFyKDUwKSwNCmdlbmRlciB2YXJjaGFyKDEpLA0KYWRkcmVzcyB2YXJjaGFyKDIwMCkNCikgRU5HSU5FPUlubm9EQjsNCg0KIyMgQWx0ZXIgVGFibGUNCkFMVEVSIFRBQkxFIGN1c3RvbWVyIENIQU5HRSBDT0xVTU4gbmFtZSBjbmFtZSBWQVJDSEFSKDUwKSBOT1QgTlVMTCxBREQgQ09MVU1OIHBob25lIFZBUkNIQVIoMTApOw0KDQojIyBEZXNjcmliZSBTY2hlbWENCkRFU0NSSUJFIGN1c3RvbWVyOw0KDQoNCiMjIERhdGEgSW5zZXJ0DQpJTlNFUlQgSU5UTyBjdXN0b21lcihjbmFtZSxnZW5kZXIsYWRkcmVzcykNClZBTFVFUygnSm9obicsJ00nLCdDaGlheWknKTsNCg0KDQpTRUxFQ1QgKiBGUk9NIGN1c3RvbWVyOw0KDQpJTlNFUlQgSU5UTyBjdXN0b21lcihjbmFtZSxnZW5kZXIsYWRkcmVzcykNClZBTFVFUygnSm9objEnLCdVTktOT1dOJywnQ2hpYXlpJyk7DQoNCklOU0VSVCBJTlRPIGN1c3RvbWVyKGNuYW1lLGdlbmRlcixhZGRyZXNzKQ0KVkFMVUVTKCdNYXJ5JywnRicsJ1RhaW5hbicpOw0KDQpJTlNFUlQgSU5UTyBjdXN0b21lcihjbmFtZSxnZW5kZXIsYWRkcmVzcykNClZBTFVFUygnQnJhZCcsJ00nLCdDaGlheWknKTsNCg0KIyMgRGF0YSBVcGRhdGUNClVQREFURSBjdXN0b21lciBTRVQgY25hbWUgPSAnSm9obm55JyBXSEVSRSBpZCA9IDE7DQoNCiMjIERhdGEgU2VsZWN0DQpTRUxFQ1QgKiBGUk9NIGN1c3RvbWVyOw0KU0VMRUNUIGNuYW1lLCBnZW5kZXIgRlJPTSBjdXN0b21lcjsNClNFTEVDVCBjbmFtZSwgZ2VuZGVyIEZST00gY3VzdG9tZXIgV0hFUkUgZ2VuZGVyID0nTSc7DQoNCiMjIERhdGEgQWdncmVnYXRpb24gd2l0aCBHUk9VUCBCWSBhbmQgSEFWSU5HDQpTRUxFQ1QgQ09VTlQoKikgRlJPTSBjdXN0b21lcjsNClNFTEVDVCBDT1VOVCgqKSBGUk9NIGN1c3RvbWVyIFdIRVJFIGdlbmRlciA9ICdNJzsNClNFTEVDVCBDT1VOVCgqKSBGUk9NIGN1c3RvbWVyIFdIRVJFIGdlbmRlciA9ICdGJzsNCg0KU0VMRUNUIGdlbmRlciwgQ09VTlQoKikgRlJPTSBjdXN0b21lciBHUk9VUCBCWSBnZW5kZXI7DQoNClNFTEVDVCBnZW5kZXIsIENPVU5UKCopIEZST00gY3VzdG9tZXIgDQpHUk9VUCBCWSBnZW5kZXIgSEFWSU5HIENPVU5UKCopID49IDI7DQoNCmBgYA0KDQojIyDpgLLpmo7orbDpoYwNCmBgYA0Kc2hvdyBlbmdpbmVzDQpTSE9XIERBVEFCQVNFUzsNCg0KIyMgSW5mb3JtYXRpb24gU2NoZW1hDQpVU0UgaW5mb3JtYXRpb25fc2NoZW1hOw0KU0hPVyBUQUJMRVM7DQoNClNFTEVDVCAqIEZST00gSU5GT1JNQVRJT05fU0NIRU1BLlNDSEVNQVRBDQoNClNFTEVDVCAqIEZST00gSU5GT1JNQVRJT05fU0NIRU1BLlRBQkxFUyANCldIRVJFIFRBQkxFX1NDSEVNQSA9ICdvcmRlcnMnOw0KDQpTRUxFQ1QgKiBGUk9NIElORk9STUFUSU9OX1NDSEVNQS5DT0xVTU5TDQpXSEVSRSBUQUJMRV9TQ0hFTUEgPSAnb3JkZXJzJzsNCg0KIyMgQ3JlYXRlIEluZGV4DQpjcmVhdGUgaW5kZXggaWR4X2N1c3RvbWVyIG9uIGN1c3RvbWVyKGNuYW1lKTsNCmNyZWF0ZSBpbmRleCBpZHhfY3VzdG9tZXIyIG9uIGN1c3RvbWVyKGNuYW1lLGdlbmRlcik7DQpjcmVhdGUgaW5kZXggaWR4X2N1c3RvbWVyMyBvbiBjdXN0b21lcihjbmFtZSkgdXNpbmcgQlRSRUU7DQoNCiMjIERlbGV0ZSwgVHJ1bmNhdGUsIERyb3ANCkRFTEVURSBGUk9NIGN1c3RvbWVyIFdIRVJFIGlkID0xOw0KREVMRVRFIEZST00gY3VzdG9tZXI7DQoNCnRydW5jYXRlIGN1c3RvbWVyOw0Kc2VsZWN0ICogZnJvbSBjdXN0b21lcjsNCmRyb3AgdGFibGUgY3VzdG9tZXI7DQpgYGANCiMjIOS9v+eUqFIg6YCj57WQTXlTUUwNCmBgYHtyfQ0KbGlicmFyeShSSkRCQykNCg0KamFyLmxvYzwtJ0M6XFxQcm9ncmFtIEZpbGVzICh4ODYpXFxNeVNRTFxcQ29ubmVjdG9yLkogNS4xXFxteXNxbC1jb25uZWN0b3ItamF2YS01LjEuMzktYmluLmphcicNCg0KZHJ2PC1KREJDKCJjb20ubXlzcWwuamRiYy5Ecml2ZXIiLGphci5sb2MsaWRlbnRpZmllci5xdW90ZT0iYCIpDQoNCg0KY29ubiA8LWRiQ29ubmVjdChkcnYsICJqZGJjOm15c3FsOi8vbG9jYWxob3N0L29yZGVycyIsICJyb290IiwgInRlc3QiKQ0KDQpkYldyaXRlVGFibGUoY29ubiwgJ2lyaXMnLCBpcmlzKQ0KZGJMaXN0VGFibGVzKGNvbm4pDQpkZiAgPC0gZGJSZWFkVGFibGUoY29ubiwiaXJpcyIpDQoNCnJlcyA8LSBkYkdldFF1ZXJ5KGNvbm4sIA0KIlNFTEVDVCBgU2VwYWwuTGVuZ3RoYCwgU3BlY2llcyBGUk9NIGlyaXMiKQ0KDQpyZXMgPC0gZGJHZXRRdWVyeShjb25uLCANCiJTRUxFQ1QgU3BlY2llcywgU1VNKGBTZXBhbC5MZW5ndGhgKQ0KRlJPTSBpcmlzIA0KR1JPVVAgQlkgU3BlY2llcyIpDQoNCnJlcyA8LSBkYkdldFF1ZXJ5KGNvbm4sIA0KIlNFTEVDVCBTcGVjaWVzLCBDT1VOVCgqKSBBUyBjbnQNCkZST00gaXJpcyANCkdST1VQIEJZIFNwZWNpZXMiKQ0KDQpwaWUocmVzJGNudCwgbGFiZWxzID0gcmVzJFNwZWNpZXMpDQoNCmlmKGRiRXhpc3RzVGFibGUoY29ubiwnaXJpcycpKXsNCiAgZGJSZW1vdmVUYWJsZShjb25uLCAnaXJpcycpDQp9DQoNCmRiRGlzY29ubmVjdChjb25uKQ0KDQpgYGANCg0KIyMg6K6A5Y+W6JiL5p6c5paw6IGe6LOH5paZDQpgYGB7cn0NCmRvd25sb2FkLmZpbGUoJ2h0dHBzOi8vcmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbS95d2NoaXUvcnRpYmFtZS9tYXN0ZXIvZGF0YS9hcHBsZW5ld3MuUkRhdGEnLCAnYXBwbGVuZXdzLlJEYXRhJykNCg0KbG9hZCgnYXBwbGVuZXdzLlJEYXRhJykNCg0KDQpsaWJyYXJ5KFJKREJDKQ0KDQpqYXIubG9jPC0nQzpcXFByb2dyYW0gRmlsZXMgKHg4NilcXE15U1FMXFxDb25uZWN0b3IuSiA1LjFcXG15c3FsLWNvbm5lY3Rvci1qYXZhLTUuMS4zOS1iaW4uamFyJw0KDQpkcnY8LUpEQkMoImNvbS5teXNxbC5qZGJjLkRyaXZlciIsamFyLmxvYyxpZGVudGlmaWVyLnF1b3RlPSJgIikNCg0KY29ubiA8LWRiQ29ubmVjdChkcnYsICJqZGJjOm15c3FsOi8vbG9jYWxob3N0L2FwcGxlZGFpbHkiLCAicm9vdCIsICJ0ZXN0IikNCg0KaWYoZGJFeGlzdHNUYWJsZShjb25uLCAnbmV3c19tYWluJykpew0KICBkYlJlbW92ZVRhYmxlKGNvbm4sICduZXdzX21haW4nKQ0KfQ0KDQpkYlNlbmRVcGRhdGUoY29ubiwgJ0NSRUFURSBUQUJMRSBuZXdzX21haW4gKA0KaWQgICAgICAgaW50KDExKSBOT1QgTlVMTCBBVVRPX0lOQ1JFTUVOVCwNCmNvbnRlbnQgIHRleHQsDQp0aXRsZSAgICB2YXJjaGFyKDEwMDApREVGQVVMVCBOVUxMLA0KZHQgICAgICAgZGF0ZXRpbWUgREVGQVVMVCBOVUxMLA0KY2F0ZWdvcnkgdmFyY2hhcigxMDAwKURFRkFVTFQgTlVMTCwNCnZpZXdfY250IGludCgxMSlERUZBVUxUIE5VTEwsDQpQUklNQVJZIEtFWShpZCkNCilFTkdJTkU9SW5ub0RCOycpDQoNCmFwcGxlbmV3cyA8LSBjYmluZChpZD0xOm5yb3coYXBwbGVuZXdzKSwgYXBwbGVuZXdzKQ0KDQpkYldyaXRlVGFibGUoY29ubiwgJ25ld3NfbWFpbicsIGFwcGxlbmV3cywgYXBwZW5kPVRSVUUscm93Lm5hbWVzPVRSVUUsb3ZlcndyaXRlPUZBTFNFKQ0KDQpuZXdzIDwtIGRiUmVhZFRhYmxlKGNvbm4sICduZXdzX21haW4nKQ0KDQoNCnJlcyA8LWRiR2V0UXVlcnkoY29ubiwgDQoiU0VMRUNUIGNhdGVnb3J5LCBjb3VudCgqKSBBUyBjbnQgRlJPTSBuZXdzX21haW4NCkdST1VQIEJZIGNhdGVnb3J5IE9SREVSIEJZIENPVU5UKCopIERFU0MiKQ0KcGllKHJlcyRjbnQsIGxhYmVscyA9IHJlcyRjYXRlZ29yeSkNCmJhcnBsb3QocmVzJGNudCwgbmFtZXMuYXJnID0gcmVzJGNhdGVnb3J5LCBjb2w9YXMuZmFjdG9yKHJlcyRjYXRlZ29yeSkpDQojP2JhcnBsb3QNCg0KZGJTZW5kVXBkYXRlKGNvbm4sICdkcm9wIHRhYmxlIG5ld3NfbWFpbjsnKQ0KZGJEaXNjb25uZWN0KGNvbm4pDQoNCmBgYA0KDQpgYGANClVTRSBhcHBsZWRhaWx5Ow0KREVTQ1JJQkUgYXBwbGVuZXdzOw0KDQoNCkNSRUFURSBUQUJMRSBuZXdzX21haW4gKA0KaWQgICAgICAgaW50KDExKSBOT1QgTlVMTCBBVVRPX0lOQ1JFTUVOVCwNCmNvbnRlbnQgIHRleHQsDQp0aXRsZSAgICB2YXJjaGFyKDEwMDApREVGQVVMVCBOVUxMLA0KZHQgICAgICAgZGF0ZXRpbWUgREVGQVVMVCBOVUxMLA0KY2F0ZWdvcnkgdmFyY2hhcigxMDAwKURFRkFVTFQgTlVMTCwNCnZpZXdfY250IGludCgxMSlERUZBVUxUIE5VTEwsDQpQUklNQVJZIEtFWShpZCkNCilFTkdJTkU9SW5ub0RCOw0KDQpgYGANCg0KIyMg5L2/55SoZHBseXINCmBgYHtyfQ0KIyBSIFN0eWxlDQphcHBsZW5ld3NbYXBwbGVuZXdzJGNhdGVnb3J5ID09ICczQycgICwgICBdDQoNCmxpYnJhcnkoZHBseXIpDQojIGRwbHlyIFN0eWxlDQpmaWx0ZXIoYXBwbGVuZXdzLCBjYXRlZ29yeT09IjNDIikNCg0KIyBSIFN0eWxlDQphcHBsZW5ld3NbYXBwbGVuZXdzJGNhdGVnb3J5ID09ICczQycgJiBhcHBsZW5ld3Mkdmlld19jbnQgPiAxMDAwICAsICAgXQ0KDQojIGRwbHlyIFN0eWxlDQpmaWx0ZXIoYXBwbGVuZXdzLCBjYXRlZ29yeT09IjNDIiZ2aWV3X2NudD4xMDAwKQ0KZmlsdGVyKGFwcGxlbmV3cywgY2F0ZWdvcnklaW4lYygiM0MiKSkNCg0KIyBSIFN0eWxlDQphcHBsZW5ld3NbLCBjKCJjYXRlZ29yeSIsInZpZXdfY250IildDQoNCiMgZHBseXIgU3R5bGUNCnNlbGVjdChhcHBsZW5ld3MsIGNhdGVnb3J5LCB2aWV3X2NudCkNCg0KDQojIFIgU3R5bGUNCmFwcGxlbmV3c1thcHBsZW5ld3MkY2F0ZWdvcnk9PSIzQyIsIGMoJ2NhdGVnb3J5JywgJ3ZpZXdfY250JyldDQoNCiMgZHBseXIgU3R5bGUNCmFwcGxlbmV3cyAlPiUgDQogIHNlbGVjdChjYXRlZ29yeSx2aWV3X2NudCkgJT4lDQogIGZpbHRlcihjYXRlZ29yeT09IjNDIikNCg0KDQoNCiMjIFNFTEVDVCBjYXRlZ29yeSwgdmlld19jbnQgDQojIyBGUk9NIGFwcGxlbmV3cw0KIyMgV0hFUkUgY2F0ZWdvcnkgPSDigJwzQ+KAnQ0KIyMgT1JERVIgQlkgdmlld19jbnQNCg0KIyBSIFN0eWxlDQphcHBsZW5ld3Mkdmlld19jbnQgPC0gYXMubnVtZXJpYyhhcHBsZW5ld3Mkdmlld19jbnQpDQoNCmEgPC0gYXBwbGVuZXdzW2FwcGxlbmV3cyRjYXRlZ29yeT09JzNDJyxjKCdjYXRlZ29yeScsICd2aWV3X2NudCcpXQ0KDQphW29yZGVyKGEkdmlld19jbnQsIGRlY3JlYXNpbmcgPSBUUlVFKSxdDQoNCg0KIyBkcGx5ciBTdHlsZQ0KYXBwbGVuZXdzICU+JSBzZWxlY3QoY2F0ZWdvcnksIHZpZXdfY250KSAlPiUNCiAgZmlsdGVyKGNhdGVnb3J5PT0nM0MnKSAlPiUgYXJyYW5nZShkZXNjKHZpZXdfY250KSkNCg0KDQoNCiMgbXV0YXRlDQpmcmVxc3VtIDwtIGFwcGxlbmV3cyAlPiUgc2VsZWN0KHZpZXdfY250KSAlPiUgc3VtKCkNCmZyZXFzdW0NCg0KDQphcHBsZW5ld3MgJT4lIA0KICBzZWxlY3QodGl0bGUsY2F0ZWdvcnksdmlld19jbnQpICU+JSAgICANCiAgbXV0YXRlKHBvcnRpb249dmlld19jbnQvZnJlcXN1bSkNCg0KYXBwbGVuZXdzIDwtIGFwcGxlbmV3cyAlPiUgbXV0YXRlKHBvcnRpb249dmlld19jbnQvZnJlcXN1bSkNCg0KaGVhZChhcHBsZW5ld3MpDQoNCiMgR3JvdXAgQnkgDQoNCiMjIFIgU3R5bGUNCnRhcHBseShhcHBsZW5ld3Mkdmlld19jbnQsIGFwcGxlbmV3cyRjYXRlZ29yeSwgc3VtKQ0KDQphcHBsZW5ld3MgJT4lIHNlbGVjdCh2aWV3X2NudCwgY2F0ZWdvcnkpICU+JQ0KICBncm91cF9ieShjYXRlZ29yeSkgJT4lIHN1bW1hcmlzZSh2aWV3X3N1bSA9IHN1bSh2aWV3X2NudCkpICU+JSBhcnJhbmdlKGRlc2Modmlld19zdW0pKQ0KDQphcHBsZW5ld3MgJT4lIHNlbGVjdCh2aWV3X2NudCwgY2F0ZWdvcnkpICU+JQ0KICBncm91cF9ieShjYXRlZ29yeSkgJT4lIHN1bW1hcmlzZSh2aWV3X21lYW4gPSBtZWFuKHZpZXdfY250KSkgJT4lIGFycmFuZ2UoZGVzYyh2aWV3X21lYW4pKSAlPiUgZmlsdGVyKHZpZXdfbWVhbiA+IDIwMDAwKQ0KDQoNCmFwcGxlbmV3cyAlPiUgZ3JvdXBfYnkoY2F0ZWdvcnkpICU+JSBzdW1tYXJpc2VfZWFjaChmdW5zKHN1bSksIHZpZXdfY250LCBwb3J0aW9uKSAlPiUgYXJyYW5nZShkZXNjKHBvcnRpb24pKQ0KDQoNCg0KYXBwbGVuZXdzICU+JSBncm91cF9ieShjYXRlZ29yeSkgJT4lIHN1bW1hcmlzZV9lYWNoKGZ1bnMobWluKC4sIG5hLnJtPVRSVUUpLCBtYXgoLiwgbmEucm09VFJVRSkpLCBtYXRjaGVzKCJ2aWV3X2NudCIpKQ0KDQoNCiMjIENvdW50IERhdGENCg0KIyMgc2VsZWN0IGNvdW50KGNhdGVnb3J5KSBmcm9tIGFwcGxlbmV3cw0KYXBwbGVuZXdzJT4lc2VsZWN0KGNhdGVnb3J5KSU+JXN1bW1hcmlzZV9lYWNoKGZ1bnMobigpKSkNCiMjIHNlbGVjdCBjb3VudChkaXN0aW5jdChjYXRlZ29yeSkpIGZyb20gYXBwbGVuZXdzDQphcHBsZW5ld3MlPiVzZWxlY3QoY2F0ZWdvcnkpJT4lc3VtbWFyaXNlX2VhY2goZnVucyhuX2Rpc3RpbmN0KGNhdGVnb3J5KSkpDQoNCg0KDQpjYXRfc3RhdCA8LSBhcHBsZW5ld3MgJT4lIGdyb3VwX2J5KGNhdGVnb3J5KSAlPiUgc3VtbWFyaXNlKHZpZXdfc3VtPXN1bSh2aWV3X2NudCkpICU+JSBhcnJhbmdlKGRlc2Modmlld19zdW0pKQ0KDQpiYXJwbG90KGNhdF9zdGF0JHZpZXdfc3VtLCBuYW1lcy5hcmcgPSBjYXRfc3RhdCRjYXRlZ29yeSwgY29sID0gZmFjdG9yKGNhdF9zdGF0JGNhdGVnb3J5KSkNCg0KDQpwaWUoY2F0X3N0YXQkdmlld19zdW0sIGxhYmVsID1jYXRfc3RhdCRjYXRlZ29yeSkNCmBgYA0KDQojIyBIb21ld29yayAzDQoNCmBgYHtyfQ0KZG93bmxvYWQuZmlsZSgnaHR0cHM6Ly9naXRodWIuY29tL3l3Y2hpdS9ydGliYW1lL3Jhdy9tYXN0ZXIvRGF0YS9wdXJjaGFzZS5jc3YnLCAncHVyY2hhc2UuY3N2JykNCnB1cmNoYXNlIDwtIHJlYWQuY3N2KCdwdXJjaGFzZS5jc3YnLCBoZWFkZXI9VFJVRSwgc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQ0KVmlldyhwdXJjaGFzZSkNCnN0cihwdXJjaGFzZSkNCg0KcHVyY2hhc2UkVGltZSA8LSBhcy5QT1NJWGN0KHB1cmNoYXNlJFRpbWUpDQojc3RyZnRpbWUocHVyY2hhc2UkVGltZSwgJyVIOiVNJykNCmBgYA0KDQo=