0.はじめに
以下はMJIR2019にて発表予定の「R言語を用いた再生可能な教学IR情報の分析と可視化」(発表者:専修大学西山慶太)の事例紹介において作成したRスクリプトです.
使用するデータはダミーデータを読み込み,“dat”というオブジェクトに格納されていることを前提に進めます.
1.データセットの確認
## sID school department grade GPA credit
## 1 工機1-1 工学部 機会工学科 1 2.05 29
## 2 工機1-1049 工学部 機会工学科 1 3.04 39
## 3 工機1-105 工学部 機会工学科 1 0.42 17
## 4 工機1-1060 工学部 機会工学科 1 2.44 29
## 5 工機1-1101 工学部 機会工学科 1 1.45 9
## 6 工機1-1121 工学部 機会工学科 1 2.50 27
これをみると,sID,school,department,grade,GPA,creditという6つの列にデータが格納させていることがわかります.
それではもう少し詳しく見ていきます.
## 'data.frame': 12000 obs. of 6 variables:
## $ sID : chr "工機1-1" "工機1-1049" "工機1-105" "工機1-1060" ...
## $ school : Factor w/ 7 levels "工学部","社会科学部",..: 1 1 1 1 1 1 1 1 1 1 ...
## $ department: Factor w/ 23 levels "応用ファイナンス学科",..: 4 4 4 4 4 4 4 4 4 4 ...
## $ grade : num 1 1 1 1 1 1 1 1 1 1 ...
## $ GPA : num 2.05 3.04 0.42 2.44 1.45 2.5 2.4 1.16 1.12 2.93 ...
## $ credit : int 29 39 17 29 9 27 25 21 23 34 ...
まずstr()の結果です,12000行6列のデータフレームであることがわかります.また,GPAはnumericつまり数値としてデータが格納されています.creditとgradeはintegerつまり整数値,schoolとdepartmentはFactor型(要素),sIDはcharactorつまり文字列として格納されています.
## sID school department grade
## Length:12000 工学部 :1250 国際法学科:1000 Min. :1.00
## Class :character 社会科学部:3000 法律学科 :1000 1st Qu.:1.75
## Mode :character 情報学部 : 750 経営学科 : 800 Median :2.50
## 人間科学部: 500 経済学科 : 800 Mean :2.50
## 人文学部 :2000 商学科 : 800 3rd Qu.:3.25
## 農学部 :1000 政治学科 : 800 Max. :4.00
## 法学部 :3500 (Other) :6800
## GPA credit
## Min. :0.010 Min. : 1.00
## 1st Qu.:1.690 1st Qu.: 36.00
## Median :2.280 Median : 66.00
## Mean :2.242 Mean : 70.31
## 3rd Qu.:2.830 3rd Qu.:100.00
## Max. :4.000 Max. :159.00
##
つづいてsummary()の結果はそれぞれの変数ごとに,最小値,1/4位点,中央値,平均値,3/4位点,最大値が表示されます.またFactorや文字列などの計算が出来ない変数については属性とデータ数が表示されます.
2.グループごとのGPA順位(ランク)の計算
データの構造等が把握できたので,早速ですがGPA順位の計算に移ります.
文部科学省から出されている修学支援新制度の支援打切りや警告に関する基準の内,「GPA(平均成績)等が下位1/4に属すること」という基準があります.よって特定のグループ内でGPAの順位づけをする必要があります.
まずは,学部,学科,学年の3要因をグループとして用いて計算してみます.
必要なコードはたったこれだけです.計算結果は下の表の通りです.
このようにR言語ではこうしたデータの前処理がとても簡単に,そして高速に実行できます.
3.「警告」ボーダーラインの計算とデータテーブルの作成
上の例では各グループごとのGPA順位を全データが格納されているデータテーブルに列として追加し,保存までしました.
しかし,グループごとの統計量を求められることもありますし,次項から説明する可視化のコードを書く際にも,グループごとの統計量テーブルがあると便利なので,この章の最後にこれを作成しておきます.
#GPA1/4&1/2点の計算
GPArank %>%
group_by(school, department, grade) %>%
mutate(GPA_ec = if_else(GPARank <=0.25,"(2)下位1/4",
if_else(GPARank>=0.5,"(1)上位1/2","(3)中間"))) %>%
group_by(school, department, grade, GPA_ec) %>%
summarize(GPA_under = max(GPA),GPA_upper = min(GPA)) -> GPA_sep
作成したデータテーブルは以下の様になっています
データの前処理はここまでです.グルーピングと順位の計算はRでの処理が圧倒的に楽です.
4.データの可視化
4−1.ヒストグラム
今回のケースでヒストグラムを作成するには前処理したデータすら必要ありません.基データであるdat変数を使用して書いてみます.



4−2.散布図
しかし,高等教育の修学支援新制度には,GPAの下位1/4の警告要件の他に,標準単位数の5割以下で打切り,6割以下で警告という要件もあります.これらの基準値を念頭に,GPAと修得単位数の二変数を用いて,散布図を書いてみます.ただし,グラフの数が膨大になるため,学年ごとに分けて描写します.
##1年次
GPArank %>%
filter(grade==1) %>%
ggplot(aes(GPA, credit))+
geom_point(size = 1)+
geom_vline(data = GPA_sep %>% filter(grade==1 & GPA_ec=="(2)下位1/4"),
mapping = aes(xintercept = GPA_under), linetype="dashed", color="blue")+
geom_hline(yintercept = ((124/4)*1)*0.6, linetype="dashed", color = "blue")+
geom_hline(yintercept = ((124/4)*1)*0.5, linetype="solid", color = "red")+
facet_wrap(~department,nrow = 5, ncol = 5)+
ggtitle("2018年度 1年次")+xlab("年度内GPA")+ylab("修得単位数")+
labs(caption = "赤実線:支援打ち切り,青点線:警告")+
theme_gray (base_family = "HiraKakuPro-W3")

##2年次
GPArank %>%
filter(grade==2) %>%
ggplot(aes(GPA, credit))+
geom_point(size = 1)+
geom_vline(data = GPA_sep %>% filter(grade==1 & GPA_ec=="(2)下位1/4"),
mapping = aes(xintercept = GPA_under), linetype="dashed", color="blue")+
geom_hline(yintercept = ((124/4)*2)*0.6, linetype="dashed", color = "blue")+
geom_hline(yintercept = ((124/4)*2)*0.5, linetype="solid", color = "red")+
facet_wrap(~department,nrow = 5, ncol = 5)+
ggtitle("2018年度 2年次")+xlab("年度内GPA")+ylab("修得単位数")+
labs(caption = "赤実線:支援打ち切り,青点線:警告")+
theme_gray (base_family = "HiraKakuPro-W3")

##3年次
GPArank %>%
filter(grade==3) %>%
ggplot(aes(GPA, credit))+
geom_point(size = 1)+
geom_vline(data = GPA_sep %>% filter(grade==1 & GPA_ec=="(2)下位1/4"),
mapping = aes(xintercept = GPA_under), linetype="dashed", color="blue")+
geom_hline(yintercept = ((124/4)*3)*0.6, linetype="dashed", color = "blue")+
geom_hline(yintercept = ((124/4)*3)*0.5, linetype="solid", color = "red")+
facet_wrap(~department,nrow = 5, ncol = 5)+
ggtitle("2018年度 3年次")+xlab("年度内GPA")+ylab("修得単位数")+
labs(caption = "赤実線:支援打ち切り,青点線:警告")+
theme_gray (base_family = "HiraKakuPro-W3")

##4年次
GPArank %>%
filter(grade==4) %>%
ggplot(aes(GPA, credit))+
geom_point(size = 1)+
geom_vline(data = GPA_sep %>% filter(grade==1 & GPA_ec=="(2)下位1/4"),
mapping = aes(xintercept = GPA_under), linetype="dashed", color="blue")+
geom_hline(yintercept = ((124/4)*4)*0.6, linetype="dashed", color = "blue")+
geom_hline(yintercept = ((124/4)*4)*0.5, linetype="solid", color = "red")+
facet_wrap(~department,nrow = 5, ncol = 5)+
ggtitle("2018年度 4年次")+xlab("年度内GPA")+ylab("修得単位数")+
labs(caption = "赤実線:支援打ち切り,青点線:警告")+
theme_gray (base_family = "HiraKakuPro-W3")

5.まとめ
R言語でデータ処理をすると,このように基データから前処理,統計処理,可視化,レポーティングまで,すべてRstudio上で行う事ができます.
加えて,このようなデータ処理はルーチンワークとして毎年行う必要がありますが,Rscriptとして保存しておくと,inputするデータを変えるだけで同じ処理を行うことができます.Excelで処理を行った場合,毎年グループ数×学年の処理が必要となり,業務量が増えるだけでなく,ヒューマンエラーの原因にもなります.
Rを使って業務の効率化を図り,データ処理の再生性を高めることは,大学事務組織にとって有益であると考えられます. ここに記載したプログラム等は2次利用していただいてOKです.ただし,実際の大学業務に使用する際には,自己責任でお願いします.プログラムを使用したことによる不利益等は責任を負いかねますので予めご了承ください.
また,不備等もあろうかと思いますので,ご質問等は西山(k.nis80[at]gmail.com)までお願いします.
LS0tCnRpdGxlOiAiUm1hcmtkb3duIFJlcG9ydGluZyBTY3JpcHQiCmF1dGhvcjogIktlaXRhIE5pc2hpeWFtYSIKZGF0ZTogIjEwLzIvMjAxOSIKb3V0cHV0OgogIGh0bWxfZG9jdW1lbnQ6CiAgICBjb2RlX2Rvd25sb2FkOiB5ZXMKICAgICMgY29kZV9mb2xkaW5nOiBoaWRlCiAgICBoaWdobGlnaHQ6IHplbmJ1cm4KICAgIHRoZW1lOiBmbGF0bHkKICAgIHRvYzogeWVzCiAgICB0b2NfZmxvYXQ6IHllcwogIHdvcmRfZG9jdW1lbnQ6CiAgICB0b2M6IHllcwotLS0KCmBgYHtyIHNldHVwLCBpbmNsdWRlPUZBTFNFfQprbml0cjo6b3B0c19jaHVuayRzZXQoZWNobyA9IFRSVUUpCmxvYWQoIk1KSVIyMDE5LlJEYXRhIikKbGlicmFyeSh0aWR5dmVyc2UpCmxpYnJhcnkoRFQpCmBgYAoKIyAgPHNwYW4gc3R5bGUgPSAiY29sb3I6cmVkIj7mlLnoqILniYjjgYzjgYLjgorjgb7jgZnvvIgyMDE5LzEyLzA577yJPC9zcGFuPiAgIApwZXJjZW50X3JhbmvplqLmlbDjgpLliKnnlKjjgZfjgabooYzjgYbjg6njg7Pjgq3jg7PjgrDoqIjnrpfjgafjga/vvIzlrabkv67mlK/mj7TmlrDliLbluqbjgavlr77lv5zjgafjgY3jgarjgYTkuovpoIXjgYzliKTmmI7jgZfjgZ/jgZ/jgoHvvIzku6XkuIvjga7jg6rjg7Pjgq/jgavmlLnoqILniYjjgpLkvZzmiJDjgZfjgb7jgZfjgZ/vvI7liKnnlKjjga7pmpvjga/ku6XkuIvjga7jg6rjg7Pjgq/jga7mlrnjgpLlvqHopqfjgY/jgaDjgZXjgYTvvI4KCiA8c3BhbiBzdHlsZSA9ICJjb2xvcjpyZWQiPiDmlLnoqILniYhVUkwgIDwvc3Bhbj4gIAo8aHR0cDovL3JwdWJzLmNvbS9rZWl0YV9uaXNoaXlhbWEvNTU3NDMzPgoKCiMg77yQ77yO44Gv44GY44KB44GrICAK44CA5Lul5LiL44GvTUpJUjIwMTnjgavjgabnmbrooajkuojlrprjga7jgIxS6KiA6Kqe44KS55So44GE44Gf5YaN55Sf5Y+v6IO944Gq5pWZ5a2mSVLmg4XloLHjga7liIbmnpDjgajlj6/oppbljJbjgI3vvIjnmbrooajogIXvvJrlsILkv67lpKflrabopb/lsbHmhbblpKrvvInjga7kuovkvovntLnku4vjgavjgYrjgYTjgabkvZzmiJDjgZfjgZ9S44K544Kv44Oq44OX44OI44Gn44GZ77yOICAK44CA5L2/55So44GZ44KL44OH44O844K/44Gv44OA44Of44O844OH44O844K/44KS6Kqt44G/6L6844G/77yMImRhdCLjgajjgYTjgYbjgqrjg5bjgrjjgqfjgq/jg4jjgavmoLzntI3jgZXjgozjgabjgYTjgovjgZPjgajjgpLliY3mj5DjgavpgLLjgoHjgb7jgZnvvI4KCiAKCgoKCiMg77yR77yO44OH44O844K/44K744OD44OI44Gu56K66KqN44CACgpgYGB7ciwgZXJyb3I9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz0gRkFMU0V9CiNkYXTjga7lhYjpoK3ooYzjgpLooajnpLrjgZXjgZvjgosKZGF0ICU+JSAKICBoZWFkKCkKYGBgCuOAgOOBk+OCjOOCkuOBv+OCi+OBqO+8jHNJRCxzY2hvb2wsZGVwYXJ0bWVudCxncmFkZSxHUEEsY3JlZGl044Go44GE44GG77yW44Gk44Gu5YiX44Gr44OH44O844K/44GM5qC857SN44GV44Gb44Gm44GE44KL44GT44Go44GM44KP44GL44KK44G+44GZ77yOICAK44CACuOAgOOBneOCjOOBp+OBr+OCguOBhuWwkeOBl+ips+OBl+OBj+imi+OBpuOBhOOBjeOBvuOBme+8jgoKYGBge3IsIGVycm9yPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmc9IEZBTFNFfQojZGF044Gu5qeL6YCg44KS44G/44KLCmRhdCAlPiUgCiAgc3RyKCkKYGBgCuOAgOOBvuOBmnN0cigp44Gu57WQ5p6c44Gn44GZ77yMMTIwMDDooYw25YiX44Gu44OH44O844K/44OV44Os44O844Og44Gn44GC44KL44GT44Go44GM44KP44GL44KK44G+44GZ77yO44G+44Gf77yMR1BB44GvbnVtZXJpY+OBpOOBvuOCiuaVsOWApOOBqOOBl+OBpuODh+ODvOOCv+OBjOagvOe0jeOBleOCjOOBpuOBhOOBvuOBme+8jmNyZWRpdOOBqGdyYWRl44GvaW50ZWdlcuOBpOOBvuOCiuaVtOaVsOWApO+8jHNjaG9vbOOBqGRlcGFydG1lbnTjga9GYWN0b3LlnovvvIjopoHntKDvvIksc0lE44GvY2hhcmFjdG9y44Gk44G+44KK5paH5a2X5YiX44Go44GX44Gm5qC857SN44GV44KM44Gm44GE44G+44GZ77yOICAK44CACmBgYHtyLCBlcnJvcj1GQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nPSBGQUxTRX0KI2RhdOOBruimgee0hOe1seioiOmHj+OCkuOBv+OCiwpkYXQgJT4lIAogIHN1bW1hcnkoKQpgYGAK44CA44Gk44Gl44GE44Gmc3VtbWFyeSgp44Gu57WQ5p6c44Gv44Gd44KM44Ge44KM44Gu5aSJ5pWw44GU44Go44Gr77yM5pyA5bCP5YCk77yMMS805L2N54K577yM5Lit5aSu5YCk77yM5bmz5Z2H5YCk77yMMy805L2N54K577yM5pyA5aSn5YCk44GM6KGo56S644GV44KM44G+44GZ77yO44G+44GfRmFjdG9y44KE5paH5a2X5YiX44Gq44Gp44Gu6KiI566X44GM5Ye65p2l44Gq44GE5aSJ5pWw44Gr44Gk44GE44Gm44Gv5bGe5oCn44Go44OH44O844K/5pWw44GM6KGo56S644GV44KM44G+44GZ77yOICAKCiMg77yS77yO44Kw44Or44O844OX44GU44Go44GuR1BB6aCG5L2N77yI44Op44Oz44Kv77yJ44Gu6KiI566X44CACgrjgIDjg4fjg7zjgr/jga7mp4vpgKDnrYnjgYzmiormj6HjgafjgY3jgZ/jga7jgafvvIzml6npgJ/jgafjgZnjgYxHUEHpoIbkvY3jga7oqIjnrpfjgavnp7vjgorjgb7jgZnvvI4gIArjgIAgIArjgIDmlofpg6jnp5HlrabnnIHjgYvjgonlh7rjgZXjgozjgabjgYTjgovkv67lrabmlK/mj7TmlrDliLbluqbjga7mlK/mj7TmiZPliIfjgorjgoTorablkYrjgavplqLjgZnjgovln7rmupbjga7lhoXvvIzjgIxHUEHvvIjlubPlnYfmiJDnuL7vvInnrYnjgYzkuIvkvY0xLzTjgavlsZ7jgZnjgovjgZPjgajjgI3jgajjgYTjgYbln7rmupbjgYzjgYLjgorjgb7jgZnvvI7jgojjgaPjgabnibnlrprjga7jgrDjg6vjg7zjg5flhoXjgadHUEHjga7poIbkvY3jgaXjgZHjgpLjgZnjgovlv4XopoHjgYzjgYLjgorjgb7jgZnvvI4gIArjgIDjgb7jgZrjga/vvIzlrabpg6jvvIzlrabnp5HvvIzlrablubTjga7vvJPopoHlm6DjgpLjgrDjg6vjg7zjg5fjgajjgZfjgabnlKjjgYTjgaboqIjnrpfjgZfjgabjgb/jgb7jgZnvvI4K44CACmBgYHtyLCBlcnJvcj1GQUxTRSwgbWVzc2FnZSA9IEZBTFNFLCB3YXJuaW5nPSBGQUxTRX0KI+WtpumDqO+8jOWtpuW5tOOBlOOBqOOBrkdQQeODqeODs+OCr+OCkuS7mOS4jgpkYXQgJT4lICNkYXTjgajjgYTjgYbjg4fjg7zjgr/jg5Xjg6zjg7zjg6DjgYvjgokKICBncm91cF9ieShzY2hvb2wsZGVwYXJ0bWVudCxncmFkZSkgJT4lICNzY2hvb2zjgahncmFkZeOBp+OCsOODq+ODvOODl+WMluOBlwogIG11dGF0ZShHUEFSYW5rID0gcGVyY2VudF9yYW5rKEdQQSkpIC0+R1BBcmFuayAj44Kw44Or44O844OX44GU44Go44GrR1BB44Gu44OR44O844K744Oz44OI44Op44Oz44Kv44KS6KiI566X44GX77yM5paw44GX44GP5a6a576p44GX44GfR1BBUmFua+WIl+OBq+agvOe0jQpgYGAKICAK44CA5b+F6KaB44Gq44Kz44O844OJ44Gv44Gf44Gj44Gf44GT44KM44Gg44GR44Gn44GZ77yO6KiI566X57WQ5p6c44Gv5LiL44Gu6KGo44Gu6YCa44KK44Gn44GZ77yOCuOAgApgYGB7ciwgZXJyb3I9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz0gRkFMU0V9CiPntZDmnpzjga7ooajnpLogIApHUEFyYW5rICU+JSAKICBtdXRhdGUoR1BBUmFuayA9IHJvdW5kKEdQQVJhbmssZGlnaXRzID0gNCkpICU+JSAKICBkYXRhdGFibGUoZmlsdGVyID0gICJ0b3AiLCAKICAgICAgICAgIGV4dGVuc2lvbnMgPSAnU2Nyb2xsZXInLCBvcHRpb25zID0gbGlzdCgKICBkZWZlclJlbmRlciA9IFRSVUUsCiAgZG9tID0gImZydGlTIiwKICBzY3JvbGxZID0gMjAwLAogIHNjcm9sbENvbGxhcHNlID0gVFJVRQopKQpgYGAKCuOAgOOBk+OBruOCiOOBhuOBq1LoqIDoqp7jgafjga/jgZPjgYbjgZfjgZ/jg4fjg7zjgr/jga7liY3lh6bnkIbjgYzjgajjgabjgoLnsKHljZjjgavvvIzjgZ3jgZfjgabpq5jpgJ/jgavlrp/ooYzjgafjgY3jgb7jgZnvvI4gIAoKCiMg77yT77yO44CM6K2m5ZGK44CN44Oc44O844OA44O844Op44Kk44Oz44Gu6KiI566X44Go44OH44O844K/44OG44O844OW44Or44Gu5L2c5oiQCuOAgOS4iuOBruS+i+OBp+OBr+WQhOOCsOODq+ODvOODl+OBlOOBqOOBrkdQQemghuS9jeOCkuWFqOODh+ODvOOCv+OBjOagvOe0jeOBleOCjOOBpuOBhOOCi+ODh+ODvOOCv+ODhuODvOODluODq+OBq+WIl+OBqOOBl+OBpui/veWKoOOBl++8jOS/neWtmOOBvuOBp+OBl+OBvuOBl+OBn++8jiAgCuOAgOOBl+OBi+OBl++8jOOCsOODq+ODvOODl+OBlOOBqOOBrue1seioiOmHj+OCkuaxguOCgeOCieOCjOOCi+OBk+OBqOOCguOBguOCiuOBvuOBmeOBl++8jOasoemgheOBi+OCieiqrOaYjuOBmeOCi+WPr+imluWMluOBruOCs+ODvOODieOCkuabuOOBj+mam+OBq+OCgu+8jOOCsOODq+ODvOODl+OBlOOBqOOBrue1seioiOmHj+ODhuODvOODluODq+OBjOOBguOCi+OBqOS+v+WIqeOBquOBruOBp++8jOOBk+OBrueroOOBruacgOW+jOOBq+OBk+OCjOOCkuS9nOaIkOOBl+OBpuOBiuOBjeOBvuOBme+8jiAgCgpgYGB7ciwgZXJyb3I9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz0gRkFMU0V9CiNHUEExLzTvvIYxLzLngrnjga7oqIjnrpcKR1BBcmFuayAlPiUgCiAgZ3JvdXBfYnkoc2Nob29sLCBkZXBhcnRtZW50LCBncmFkZSkgJT4lIAogIG11dGF0ZShHUEFfZWMgPSBpZl9lbHNlKEdQQVJhbmsgPD0wLjI1LCIoMinkuIvkvY0xLzQiLAogICAgICAgICAgICAgICAgICAgICAgICAgIGlmX2Vsc2UoR1BBUmFuaz49MC41LCIoMSnkuIrkvY0xLzIiLCIoMynkuK3plpMiKSkpICU+JSAKICBncm91cF9ieShzY2hvb2wsIGRlcGFydG1lbnQsIGdyYWRlLCBHUEFfZWMpICU+JSAKICBzdW1tYXJpemUoR1BBX3VuZGVyID0gbWF4KEdQQSksR1BBX3VwcGVyID0gbWluKEdQQSkpIC0+44CAR1BBX3NlcCAKYGBgCgrjgIDkvZzmiJDjgZfjgZ/jg4fjg7zjgr/jg4bjg7zjg5bjg6vjga/ku6XkuIvjga7mp5jjgavjgarjgaPjgabjgYTjgb7jgZkKYGBge3IsIGVycm9yPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmc9IEZBTFNFfQoj57WQ5p6c44Gu6KGo56S6ICAKR1BBX3NlcCAlPiUgCiAgZGF0YXRhYmxlKGZpbHRlciA9ICAidG9wIiwgCiAgICAgICAgICBleHRlbnNpb25zID0gJ1Njcm9sbGVyJywgb3B0aW9ucyA9IGxpc3QoCiAgZGVmZXJSZW5kZXIgPSBUUlVFLAogIGRvbSA9ICJmcnRpUyIsCiAgc2Nyb2xsWSA9IDIwMCwKICBzY3JvbGxDb2xsYXBzZSA9IFRSVUUKKSkKYGBgCiAKIAogIOODh+ODvOOCv+OBruWJjeWHpueQhuOBr+OBk+OBk+OBvuOBp+OBp+OBme+8juOCsOODq+ODvOODlOODs+OCsOOBqOmghuS9jeOBruioiOeul+OBr1Ljgafjga7lh6bnkIbjgYzlnKflgJLnmoTjgavmpb3jgafjgZnvvI4KICAKICAKIyDvvJTvvI7jg4fjg7zjgr/jga7lj6/oppbljJYgCgojIyDvvJTiiJLvvJHvvI7jg5Ljgrnjg4jjgrDjg6njg6AK44CA5LuK5Zue44Gu44Kx44O844K544Gn44OS44K544OI44Kw44Op44Og44KS5L2c5oiQ44GZ44KL44Gr44Gv5YmN5Yem55CG44GX44Gf44OH44O844K/44GZ44KJ5b+F6KaB44GC44KK44G+44Gb44KT77yO5Z+644OH44O844K/44Gn44GC44KLZGF05aSJ5pWw44KS5L2/55So44GX44Gm5pu444GE44Gm44G/44G+44GZ77yOCgpgYGB7ciwgZXJyb3I9RkFMU0UsIG1lc3NhZ2UgPSBGQUxTRSwgd2FybmluZz0gRkFMU0V9Cgoj5YWo5L2T44Gu5YiG5biDCmRhdCAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gR1BBKSkrCiAgZ2VvbV9oaXN0b2dyYW0oKSsKICB0aGVtZV9ncmF5IChiYXNlX2ZhbWlseSA9ICJIaXJhS2FrdVByby1XMyIpIAoKI+WtpumDqOOBlOOBqOOBruWIhuW4gwpkYXQgJT4lIAogIGdncGxvdChhZXMoeCA9IEdQQSwgZmlsbCA9IHNjaG9vbCkpKwogIGdlb21faGlzdG9ncmFtKCkrCiAgZmFjZXRfZ3JpZCggfiBzY2hvb2wpKwogIHRoZW1lX2dyYXkgKGJhc2VfZmFtaWx5ID0gIkhpcmFLYWt1UHJvLVczIikgCgoj5a2m6YOo44O75a2m56eR44GU44Go44Gu5YiG5biDCmRhdCAlPiUgCiAgZ2dwbG90KGFlcyh4ID0gR1BBLCBmaWxsID0gc2Nob29sKSkrCiAgZ2VvbV9oaXN0b2dyYW0oKSsKICBmYWNldF93cmFwKH5kZXBhcnRtZW50LCBucm93ID0gNSwgbmNvbCA9IDUpKwogIHRoZW1lX2dyYXkgKGJhc2VfZmFtaWx5ID0gIkhpcmFLYWt1UHJvLVczIikgCmBgYAoKCgojIyDvvJTiiJLvvJLvvI7mlaPluIPlm7PjgIAK44CA44GX44GL44GX77yM6auY562J5pWZ6IKy44Gu5L+u5a2m5pSv5o+05paw5Yi25bqm44Gr44Gv77yMR1BB44Gu5LiL5L2NMS8044Gu6K2m5ZGK6KaB5Lu244Gu5LuW44Gr77yM5qiZ5rqW5Y2Y5L2N5pWw44Gu77yV5Ymy5Lul5LiL44Gn5omT5YiH44KK77yM77yW5Ymy5Lul5LiL44Gn6K2m5ZGK44Go44GE44GG6KaB5Lu244KC44GC44KK44G+44GZ77yO44GT44KM44KJ44Gu5Z+65rqW5YCk44KS5b+16aCt44Gr77yMR1BB44Go5L+u5b6X5Y2Y5L2N5pWw44Gu5LqM5aSJ5pWw44KS55So44GE44Gm77yM5pWj5biD5Zuz44KS5pu444GE44Gm44G/44G+44GZ77yO44Gf44Gg44GX77yM44Kw44Op44OV44Gu5pWw44GM6Iao5aSn44Gr44Gq44KL44Gf44KB77yM5a2m5bm044GU44Go44Gr5YiG44GR44Gm5o+P5YaZ44GX44G+44GZ77yOCuOAgAoKYGBge3IsIGVycm9yPUZBTFNFLCBtZXNzYWdlID0gRkFMU0UsIHdhcm5pbmc9IEZBTFNFfQojIzHlubTmrKEKR1BBcmFuayAlPiUgCiAgZmlsdGVyKGdyYWRlPT0xKSAlPiUgCiAgZ2dwbG90KGFlcyhHUEEsIGNyZWRpdCkpKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpKwogIGdlb21fdmxpbmUoZGF0YSA9IEdQQV9zZXAgJT4lIGZpbHRlcihncmFkZT09MSAmIEdQQV9lYz09IigyKeS4i+S9jTEvNCIpLAogICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4aW50ZXJjZXB0ID0gR1BBX3VuZGVyKSwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSJibHVlIikrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gKCgxMjQvNCkqMSkqMC42LCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3IgPSAiYmx1ZSIpKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9ICgoMTI0LzQpKjEpKjAuNSwgbGluZXR5cGU9InNvbGlkIiwgY29sb3IgPSAicmVkIikrCiAgZmFjZXRfd3JhcCh+ZGVwYXJ0bWVudCxucm93ID0gNSwgbmNvbCA9IDUpKwogIGdndGl0bGUoIjIwMTjlubTluqbjgIAx5bm05qyhIikreGxhYigi5bm05bqm5YaFR1BBIikreWxhYigi5L+u5b6X5Y2Y5L2N5pWwIikrCiAgbGFicyhjYXB0aW9uID0gIui1pOWun+e3mu+8muaUr+aPtOaJk+OBoeWIh+OCiu+8jOmdkueCuee3mu+8muitpuWRiiIpKwogIHRoZW1lX2dyYXkgKGJhc2VfZmFtaWx5ID0gIkhpcmFLYWt1UHJvLVczIikgCgojIzLlubTmrKEKR1BBcmFuayAlPiUgCiAgZmlsdGVyKGdyYWRlPT0yKSAlPiUgCiAgZ2dwbG90KGFlcyhHUEEsIGNyZWRpdCkpKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpKwogIGdlb21fdmxpbmUoZGF0YSA9IEdQQV9zZXAgJT4lIGZpbHRlcihncmFkZT09MSAmIEdQQV9lYz09IigyKeS4i+S9jTEvNCIpLAogICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4aW50ZXJjZXB0ID0gR1BBX3VuZGVyKSwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSJibHVlIikrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gKCgxMjQvNCkqMikqMC42LCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3IgPSAiYmx1ZSIpKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9ICgoMTI0LzQpKjIpKjAuNSwgbGluZXR5cGU9InNvbGlkIiwgY29sb3IgPSAicmVkIikrCiAgZmFjZXRfd3JhcCh+ZGVwYXJ0bWVudCxucm93ID0gNSwgbmNvbCA9IDUpKwogIGdndGl0bGUoIjIwMTjlubTluqbjgIAy5bm05qyhIikreGxhYigi5bm05bqm5YaFR1BBIikreWxhYigi5L+u5b6X5Y2Y5L2N5pWwIikrCiAgbGFicyhjYXB0aW9uID0gIui1pOWun+e3mu+8muaUr+aPtOaJk+OBoeWIh+OCiu+8jOmdkueCuee3mu+8muitpuWRiiIpKwogIHRoZW1lX2dyYXkgKGJhc2VfZmFtaWx5ID0gIkhpcmFLYWt1UHJvLVczIikgCgojIzPlubTmrKEKR1BBcmFuayAlPiUgCiAgZmlsdGVyKGdyYWRlPT0zKSAlPiUgCiAgZ2dwbG90KGFlcyhHUEEsIGNyZWRpdCkpKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpKwogIGdlb21fdmxpbmUoZGF0YSA9IEdQQV9zZXAgJT4lIGZpbHRlcihncmFkZT09MSAmIEdQQV9lYz09IigyKeS4i+S9jTEvNCIpLAogICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4aW50ZXJjZXB0ID0gR1BBX3VuZGVyKSwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSJibHVlIikrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gKCgxMjQvNCkqMykqMC42LCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3IgPSAiYmx1ZSIpKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9ICgoMTI0LzQpKjMpKjAuNSwgbGluZXR5cGU9InNvbGlkIiwgY29sb3IgPSAicmVkIikrCiAgZmFjZXRfd3JhcCh+ZGVwYXJ0bWVudCxucm93ID0gNSwgbmNvbCA9IDUpKwogIGdndGl0bGUoIjIwMTjlubTluqbjgIAz5bm05qyhIikreGxhYigi5bm05bqm5YaFR1BBIikreWxhYigi5L+u5b6X5Y2Y5L2N5pWwIikrCiAgbGFicyhjYXB0aW9uID0gIui1pOWun+e3mu+8muaUr+aPtOaJk+OBoeWIh+OCiu+8jOmdkueCuee3mu+8muitpuWRiiIpKwogIHRoZW1lX2dyYXkgKGJhc2VfZmFtaWx5ID0gIkhpcmFLYWt1UHJvLVczIikgCgojIzTlubTmrKEKR1BBcmFuayAlPiUgCiAgZmlsdGVyKGdyYWRlPT00KSAlPiUgCiAgZ2dwbG90KGFlcyhHUEEsIGNyZWRpdCkpKwogIGdlb21fcG9pbnQoc2l6ZSA9IDEpKwogIGdlb21fdmxpbmUoZGF0YSA9IEdQQV9zZXAgJT4lIGZpbHRlcihncmFkZT09MSAmIEdQQV9lYz09IigyKeS4i+S9jTEvNCIpLAogICAgICAgICAgICAgbWFwcGluZyA9IGFlcyh4aW50ZXJjZXB0ID0gR1BBX3VuZGVyKSwgbGluZXR5cGU9ImRhc2hlZCIsIGNvbG9yPSJibHVlIikrCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gKCgxMjQvNCkqNCkqMC42LCBsaW5ldHlwZT0iZGFzaGVkIiwgY29sb3IgPSAiYmx1ZSIpKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9ICgoMTI0LzQpKjQpKjAuNSwgbGluZXR5cGU9InNvbGlkIiwgY29sb3IgPSAicmVkIikrCiAgZmFjZXRfd3JhcCh+ZGVwYXJ0bWVudCxucm93ID0gNSwgbmNvbCA9IDUpKwogIGdndGl0bGUoIjIwMTjlubTluqbjgIA05bm05qyhIikreGxhYigi5bm05bqm5YaFR1BBIikreWxhYigi5L+u5b6X5Y2Y5L2N5pWwIikrCiAgbGFicyhjYXB0aW9uID0gIui1pOWun+e3mu+8muaUr+aPtOaJk+OBoeWIh+OCiu+8jOmdkueCuee3mu+8muitpuWRiiIpKwogIHRoZW1lX2dyYXkgKGJhc2VfZmFtaWx5ID0gIkhpcmFLYWt1UHJvLVczIikgCmBgYAoKCgojIO+8le+8juOBvuOBqOOCgSAgCuOAgFLoqIDoqp7jgafjg4fjg7zjgr/lh6bnkIbjgpLjgZnjgovjgajvvIzjgZPjga7jgojjgYbjgavln7rjg4fjg7zjgr/jgYvjgonliY3lh6bnkIbvvIzntbHoqIjlh6bnkIbvvIzlj6/oppbljJbvvIzjg6zjg53jg7zjg4bjgqPjg7PjgrDjgb7jgafvvIzjgZnjgbnjgaZSc3R1ZGlv5LiK44Gn6KGM44GG5LqL44GM44Gn44GN44G+44GZ77yOICAK44CA5Yqg44GI44Gm77yM44GT44Gu44KI44GG44Gq44OH44O844K/5Yem55CG44Gv44Or44O844OB44Oz44Ov44O844Kv44Go44GX44Gm5q+O5bm06KGM44GG5b+F6KaB44GM44GC44KK44G+44GZ44GM77yMUnNjcmlwdOOBqOOBl+OBpuS/neWtmOOBl+OBpuOBiuOBj+OBqO+8jGlucHV044GZ44KL44OH44O844K/44KS5aSJ44GI44KL44Gg44GR44Gn5ZCM44GY5Yem55CG44KS6KGM44GG44GT44Go44GM44Gn44GN44G+44GZ77yORXhjZWzjgaflh6bnkIbjgpLooYzjgaPjgZ/loLTlkIjvvIzmr47lubTjgrDjg6vjg7zjg5fmlbDDl+WtpuW5tOOBruWHpueQhuOBjOW/heimgeOBqOOBquOCiu+8jOalreWLmemHj+OBjOWil+OBiOOCi+OBoOOBkeOBp+OBquOBj++8jOODkuODpeODvOODnuODs+OCqOODqeODvOOBruWOn+WboOOBq+OCguOBquOCiuOBvuOBme+8jiAgCuOAgFLjgpLkvb/jgaPjgabmpa3li5njga7lirnnjofljJbjgpLlm7PjgorvvIzjg4fjg7zjgr/lh6bnkIbjga7lho3nlJ/mgKfjgpLpq5jjgoHjgovjgZPjgajjga/vvIzlpKflrabkuovli5nntYTnuZTjgavjgajjgaPjgabmnInnm4rjgafjgYLjgovjgajogIPjgYjjgonjgozjgb7jgZnvvI4K44CACiDjgZPjgZPjgavoqJjovInjgZfjgZ/jg5fjg63jgrDjg6njg6DnrYnjga/vvJLmrKHliKnnlKjjgZfjgabjgYTjgZ/jgaDjgYTjgaZPS+OBp+OBme+8juOBn+OBoOOBl++8jOWun+mam+OBruWkp+WtpualreWLmeOBq+S9v+eUqOOBmeOCi+mam+OBq+OBr++8jOiHquW3seiyrOS7u+OBp+OBiumhmOOBhOOBl+OBvuOBme+8juODl+ODreOCsOODqeODoOOCkuS9v+eUqOOBl+OBn+OBk+OBqOOBq+OCiOOCi+S4jeWIqeebiuetieOBr+iyrOS7u+OCkuiyoOOBhOOBi+OBreOBvuOBmeOBruOBp+S6iOOCgeOBlOS6huaJv+OBj+OBoOOBleOBhO+8jiAgCuOAgArjgIDjgb7jgZ/vvIzkuI3lgpnnrYnjgoLjgYLjgo3jgYbjgYvjgajmgJ3jgYTjgb7jgZnjga7jgafvvIzjgZTos6rllY/nrYnjga/opb/lsbEoay5uaXM4MFthdF1nbWFpbC5jb20p44G+44Gn44GK6aGY44GE44GX44G+44GZ77yO