OmniAICreator/Qiita-1.07M huggingface dataset:
Viz Artist Freeの導入方法について（２）

# Viz Artist Freeインストール

現時点(2019/03/18)でDownlodできるインストーラーバイナリは
```VizArtistFreeBundle-x64-3.12.1.83617.exe```
となってます。

マイナーバージョンがアップするとDownlodできるバイナリもverupするのですが、過去verをDownlodする方法が残念ながら現時点ではありません。マメにDownloadバージョンをチェックして、インストーラーを手持ちストックしておくと良いかもしれません。

Downloadしたインストラーを実行してみてください。
![inst01.jpg](https://qiita-image-store.s3.amazonaws.com/0/323157/759be98b-6bdf-c8a1-e0ad-55975116d902.jpeg)
```Vizrt Viz Graphics Hub```
リアルタイムCGを描画する為の必要なデータ(シーン、フォント、オブジェクト、テクスチャ、マテリアルその他)を収容するデータベースです。
Data Directoryは任意の場所で構いません。

```Vizrt Viz Artist```
プログラム本体です。
これもそのままデフォルトでOKです。
【INSTALL】
してください。

４つのアイコンができていると思います。
![inst02.jpg](https://qiita-image-store.s3.amazonaws.com/0/323157/18954421-f55f-eb84-90a0-95016b601316.jpeg)




# Viz GH Terminal
シーンデータベースです。
Web UIでの操作になりますのでChrome推奨です。
![inst03.jpg](https://qiita-image-store.s3.amazonaws.com/0/323157/e25e4eee-bd58-ffa1-a4c5-51f4ba8e597c.jpeg)
センター3つのBOX一番上のEmergency Shutdownという項目がありますが、このボタンでデータベースのサービスON/OFFをします。基本は稼働させっぱなしで構いません。

2番目のShow Configurationではデータディレクトリを指定できます。
データベースのバックアップはEmergency Shutdownで一度データベースを止めれば、指定しているディレクトリごとごっそりコピー保管することで可能です。

Viz Artist Freeは起動時にどのデータベースにアクセスするか？をログイン画面で問合せにきますので、Viz GH Terminalのサービスを開始して指定してあげてください。聞いてこずにViz Artist Freeが起動する場合はデフォルトでオートログインの設定が入っている状態です。
![inst05.jpg](https://qiita-image-store.s3.amazonaws.com/0/323157/8de5d0f6-2808-7895-d13e-a338821b5981.jpeg)




注意点はPCをシャットダウンする前に事前にViz GH TerminalをOFFにしないと正常に書き込みが終了する前にPCが落ちて稀にデータが壊れる場合があります。
シャットダウンの前にViz GH TerminalのWeb UIからEmergency Shutdownでサービスを落としてください。


#Viz Artist
メインのリアルタイムCG用の制作環境です。
Downlodしてきたversionにもよりますが、起動するためのコンフィグレーションについて残念ながらメーカーのドキュメントがほとんどありません。ひとまず現行verについて起動のための設定を説明しますので、もし起動しないケースの方がいらっしゃれば以下を参考にしてみてください。

Viz Artist Freeは全ての起動環境を設定ファイルに記述しています。
場所は
```C:\ProgramData\vizrt\viz3```
にあり
```VIZ-PCNAME-0-0.cfg```
というcfgファイルを生成します。
※PCNAMEの箇所は実際にお使いのPC名が入ります。

Vizを起動するとこのファイルを自動生成(デフォルト設定)しますが、そのままでは通常ライセンスの設定になっているため起動しません。cfgファイル内の最下部あたりにSECTION LOCAL_DATAという(ワード検索すると早いです)記述セクションがありますので、その中の項目を以下に変更してみてください。
また、cfgファイルが存在する場合は起動時に読み込み各種設定をロードします。
、、この各種設定ですがViz ArtistのGUIでのconfigタブから設定可能な項目、隠し設定項目、将来組み込み予定の設定項目なども含まれておりちょっとしたコードくらいありますので、まあ中身はあまり気にしなくても問題ないです。


```Legacy_Licensing = 0```
```License_Location = VL_L_LOCAL```
```License_Core = ART_ARTIST_FREE```

```Additional_Licenses = ```
もしくは
```# Additional_Licenses = ```
※Additional_Licensesなし、という意味
![inst04.jpg](https://qiita-image-store.s3.amazonaws.com/0/323157/08dbac0f-ecf0-354c-f0c5-e7a1ff0a2346.jpeg)
どうでしょうか？
Viz Artist Free起動したでしょうか？
もちろんViz GH Terminalは起動している前提です。

#Viz Engine 
いわゆる実行環境のみでの起動ショートカットです。
Artistが起動する場合はほぼ使いません。

#Viz Config
cfg設定部分をGUIで変更するためのの起動ショートカットです。
Artistから同じ操作ができるのでほぼ使いません。



以上駆け足ですが起動までの手順でした。
次は現在デフォルト設定での起動になっていますので、次回Esports向けの設定に変更します。
caddy-cgi に機能追加したくてフォーラムで質問してみたらそのまま作者の方が実装してくれてしまった話

CaddyでCGIを使うためのプラグイン、[caddy-cgi](https://github.com/jung-kurt/caddy-cgi)を読んでみた。

そもそもなにがやりたかったのかというと、Caddyfileの中で、

```Caddyfile
cgi {
  match /hello
  exec {.}/app/cgi/hello.sh
  env WORKDIR={.}/app/cgi
}
```

みたいな感じでCGIのルートディレクトリを環境変数`WORKDIR`でCGIスクリプトに渡してCGIスクリプト側で`cd ${WORKDIR}`しているところを、

```Caddyfile
cgi {
  match /hello
  exec {.}/app/cgi/hello.sh
  workdir {.}/app/cgi
}
```

のような感じでCaddyfileでワーキングディレクトリを設定して、`cd`した状態でCGIスクリプトを実行するようにさせたかった。
（systemd.execだと`WorkingDirectory`というディレクティブがある）
caddy-cgiではいまのところ、このようなことはできないっぽいので、プラグインに修正を加えてできるようにしたい。

まず、caddy-cgiがどこでCGIスクリプトをexecしているのかを探す。
CGIなんだから、このプラグインの中でプロセスをexecしてるに違いない、と思ってcmdだとかexecだとかforkだとかのキーワードでgrepしてみたのだが、それっぽい箇所が見当たらず。

そこで、Caddyのフォーラムで質問してみたら、なんとcaddy-cgiの作者のjungさんが直々に答えてくれた。
（アイコン画像から察するに、jungさんは馬を連れているイケおじである）

jungさんによると、

https://caddy.community/t/how-caddy-cgi-plugin-execute-a-cgi-script/5344/2?u=miminashi

> caddy-cgi lets the Go standard library handle this part. See host.go

とのことだった。

これを頭において、もういちど読んでみる。

https://github.com/jung-kurt/caddy-cgi/blob/master/cgi.go#L154 が実際にCGIを実行している箇所っぽい。

`cgiHnd`の出処を探す。
https://github.com/jung-kurt/caddy-cgi/blob/master/cgi.go#L103 の関数定義から、`cgiHnd`の型は`cgi.Handler`だとわかる。

`cgi.Handler`の仕様を見てみる。
https://golang.org/src/net/http/cgi/host.go?s=1282:2432#L51 に

```go
// Dir specifies the CGI executable's working directory.
// If Dir is empty, the base directory of Path is used.
// If Path has no base directory, the current working
// directory is used.
Dir string
```

とあるので、

https://github.com/jung-kurt/caddy-cgi/blob/master/cgi.go#L106 でCGIのワーキングディレクトリを設定していることになる。

そしたら、あとはCaddyfileの`cgi`ディレクティブにサブディレクティブ`workdir`を追加して、[cgi.go#L106](https://github.com/jung-kurt/caddy-cgi/blob/master/cgi.go#L106) でドキュメントルートを渡すかわりに、`workdir`サブディレクティブで設定した値を渡すようにcaddy-cgiを修正すればよさそう。

と、ここまでわかったところで、jungさんから「dirってサブディレクティブ追加したるよ！できたら知らせるよ！」との[返信があった](https://caddy.community/t/how-caddy-cgi-plugin-execute-a-cgi-script/5344/4?u=miminashi)。。。

超ありがたいが、プルリク送れるチャンスでわ！？と思ってたので、世の中そんなに甘くはなかった。
うーん、まあ、自分の学習のために自分でもやってみよっと・・・。


2019-03-19 追記:
https://caddyserver.com/download から落とせるビルド済みバイナリで、caddy-cgiのdirオプションが動作していることを確認できました。
`Caddyfile`は以下のような感じになります。

```Caddyfile
cgi {
  match /dirtest
  exec {.}/app/cgi/dirtest.sh
  #dir /Users/miminashi  # 絶対パスも指定できる
  dir ./app/cgi          # 相対パス指定の場合は、caddyのワーキングディレクトリが起点になる
  #dir {.}/app/cgi       # これはダメ
}
```

ちなみに、[diffはこんな感じ](https://github.com/jung-kurt/caddy-cgi/commit/60380090e2bd15fe8770b5ea6bcad79bca9b6b4a)だった。
メインの修正は思ってた通りの感じだったけど、テスト書いたりとか、ドキュメント修正したりもあるし、いきなりこれをやるのは自分にはちょっと難しかったかもしれない。
でも、このdiffを見たら、caddy-cgiに機能追加してプルリク投げるには何をしたらいいかがわかったし、今度なにか追加したくなったときの参考にしようと思う。

jungさん、本当にありがとうございました。
MacBook Pro (High Sierra)に仮想ubuntuの導入を試みた話

#はじめに
今日はc++はお休みします。ubuntu導入にむきになってついこの時間までやってしまった。
明日は夜に時間あるのでc++をやる。
毎日投稿してたのを途切れさしたくないのでC++関係ないけど自己満足の日記程度に書いとく（**何も参考になりません**）
##環境
MacBook Pro 2013年モデル
mac OS High Sierra　

##目的
parallels Desktopの有料化になったので、無料の仮想デスクトップを見つける。
macbookproに仮想デスクトップのubuntu16.04の導入がしたい。
＊bootcampは再起動がめんどくさいので前使ってたけどやめた。

##試みたこと
・AWSでubuntuにssh接続
 リモートデスクトップによるGUI操作
・virtual Boxによる導入を検討
・やっぱりparallels Desktop

##AWSのEC2
AWSを初めて触ったのでなにがなにやらわからんかった。ネットの記事を探しまくってssh接続までは順調にできた。
でも、そこからリモートデスクトップにつなげるまでにかなりの時間を食った。
ubuntu16.04はxrdpが正常にインストールできなくて、いろいろ試みてみたが諦めた。そして、ubuntu18.04でxrdpを正常にインストールできた。リモートデスクトップにつなげてみてやっとできた！と思ったら、リモートデスクトップのGUI操作が本当に遅くて使い物にならなかった。（私が無料プランを選択したからかも）
そこでawsはもうやめた。楽しかったからまぁいいけど。

##Virtual Box
次に、virtual Boxを検討した。しかしパーティションの分割やらなにやらで、macの容量を削るのがいやで、諦める。

##やっぱりparallels desktopですわ。パーティションの分割とかもいらないし、とてもラクラク。
high sierraからmojaveにするつもりないからparallelsの買い切り版買おうかな。

#終わりに
疲れた
寝る
明日からまたC++投稿します。
Python機械学習プログラミング 第6章 まとめ

[この本](https://www.amazon.co.jp/Python-%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0-%E9%81%94%E4%BA%BA%E3%83%87%E3%83%BC%E3%82%BF%E3%82%B5%E3%82%A4%E3%82%A8%E3%83%B3%E3%83%86%E3%82%A3%E3%82%B9%E3%83%88%E3%81%AB%E3%82%88%E3%82%8B%E7%90%86%E8%AB%96%E3%81%A8%E5%AE%9F%E8%B7%B5-impress-gear/dp/4295003379)の第6章をまとめたものです
##Pipelineクラス
* scikit-learnの変換器と推定器を結合して、関数呼び出しをすっきりとさせる
* 変換器：StandardScaler(標準化), PCA(次元削減)
    * .fit() --> データの統計的性質を取得してメモリに保存
    * .transform() --> それをもとにデータの値をいじくる
* 推定器：LogisticRegression(回帰)
    * .fit() --> トレーニングデータを学習してモデルをfitさせる
    * .predict() --> テストデータをpredict
    
##モデルの選択
* **ハイパーパラメータ**の最適化
    * トレーニングの前に決めておく値
    * 例えばADALINEのコスト関数を最小化するための勾配降下法で登場した学習率$ \gamma $（36ページ）

###ホールドアウト法
* モデル同士の優劣を決めるには、トレーニングデータのみならずテストデータも用いて正解率を出すことにより評価する必要がある
* ただこの方法だと、**特定の**テストデータに適したモデルが選択されることになるので、過学習を防ぐため最終的な性能評価にはまた別のテストデータが必要となる
* そこでトレーニングデータセットの一部を、モデル選択時のテストに用いることにし、これを検出データセットと呼ぶ
    * ただしここでの分け方によって性能の評価が変わってくるかもしれない。そこで...

###k分割交差検証
* トレーニングデータセットをk分割し、そのうち一つを非復元抽出（取ったあとツボに戻さない方）で選んで検出データセットとする、というのをk回繰り返し、k回の正解率(or誤り率)の平均を性能の評価とする
* 納得のいく正解率をだすハイパーパラメータを見つけたら、トレーニングデータセット全体で改めて学習し直す
* 層化k分割交差検証
    * k分割したデータセットそれぞれでクラスの偏りができないような分割をすることでほんのり改善

##バイアスとバリアンスの診断
###復習(3章)
* バイアスが高い＝学習不足
    * モデルの複雑さがデータのパターンを捕捉するには不十分
    * パラメータをもっと増やすと良い
* バリアンスが高い＝過学習
    * 逆にデータに対してモデルが複雑すぎる
    * パラメータを減らすか、トレーニングデータを増やしてみる
    
###学習曲線
<img width="700" alt="スクリーンショット 2019-03-18 0.30.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/379451/00a5acee-f658-62e0-d95f-7aedb2507bc3.png">

###検証曲線
* バイアス、バリアンスの判定基準は学習曲線と同じで、横軸をモデルのハイパーパラメータとしたものである
    * ここではロジスティック回帰の正則化パラメータC(74ページ)
![06_06のコピー.png](https://qiita-image-store.s3.amazonaws.com/0/379451/d4124d07-a29d-5ef5-a332-2b53489102b7.png)

##グリッドサーチ
ハイパーパラメータが複数ある場合などに、様々な値の組合せを愚直に調べて最適な組合せを探す方法だが、考えられるすべての組合せを調べようとすると計算コストがすごいことになる

###入れ子式の交差検証
1. まずデータセット全体をk1分割する
2. そのうち1つをテストデータセットとし、残りのデータをトレーニングデータセットとする
3. k2分割交差検証を行う(トレーニングデータセットをk2等分して1つを検証データセットとする×k2回)
4. 1~3をk1回繰り返す

* 複数のアルゴリズム同士の比較の際に推奨されるらしい

##様々な性能評価指標

###混同行列
<img width="300" alt="スクリーンショット 2019-03-18 0.30.23.png" src="https://qiita-image-store.s3.amazonaws.com/0/379451/a6d75a8a-e50c-effa-3d35-6fe2ff1d05a9.png">
これらの四則演算により様々な性能評価指標が求まる(適合率、再現率、F1スコア等)(全部scikit-learnにあるよ)

###ROC曲線
* 陽性か陰性かの判断に用いるしきい値を0から１まで変化させた時の真陽性率と偽陽性率の変化をプロットしたもの
    * 真陽性率は正解が陽性だった時に陽性と判定する条件付き確率
    * 偽陽性率は正解が陰性だった時に陽性と判定する条件付き確率
* 偽陽性率に対して真陽性率が高ければ高いほどいいので、グラフが対角線より上に来て、左や上の辺に張り付くほどいいモデルだと言える
* よって曲線下面積AUCは性能の指標となる
* この手法はおなじみの一体全の考え方により多クラス問題にも拡張可能らしい
   ![06_10.png](https://qiita-image-store.s3.amazonaws.com/0/379451/8e56c1da-e596-0988-2a9f-2e8c22121836.png)

###クラスに偏りがある場合
* 正解率は万能ではない
    * 機械の故障の点検では、故障なしのデータの割合が圧倒的に多いので、必ず正常と答えるモデルはものすごい正解率を叩き出してしまう
    * だからこそ色々な性能評価指標が提案されている
* アルゴリズムによってはコスト関数や報酬を各トレーニングサンプルに対する合計値としているが、これだと偏りがある場合に多数決になってしまう
    * 少数ラベルへの誤った予測には大きなペナルティを課す、などの工夫が必要
    * scikit-learnでclass_weight='balanced'とするだけでいいそうで
* 色々方法はあるが、万能な解決策はないっぽい
    * その都度頑張る
深層学習で株価やFXなどの時系列データで上昇下降ラベルの分類における精度向上のアイデア（やり方は知らない）

#実装したいがわからないことのメモ

お金を稼ぐならとりあえずお金に関連することを勉強していこうとしてはや半年。勉強をサボっていたこともあってなかなか進んでいないが、どうにかこの春休みである程度勉強を進めたい。

そこで今回は実装方法はわからないが（またはまだ実装していない）精度向上に寄与しそうな要素を少しメモしておく。実装できたら適宜更新するための記事。

##１、説明変数をふやす
ただの力技。FXの予測に使っている指標が１０もないのでまだまだ説明変数を増やせるはず。というかやれる。

##２，説明変数の重要度からいらない変数を絞る
１とは逆に不要な説明変数をへらすことで精度を上げていく方法。ただ、まずは説明変数を増やしてから減らさないといけないので順番的に優先度が下になる。

##３，当てられるときだけあてる
現状、すべての時点で予測を行っているためにあまり精度が良くない。しかし、ただ稼ぐためならすべての時点で予測を必要はなく、当てれるときに当ててくれればいい。

ただ、SVMであれば境界面からの距離などでできるが時系列データに適していないしそもそも為替データなどではデータの個数が多すぎて学習が（最低でも自分の環境では）膨大になりすぎる。

深層学習で信頼度の計算をしたいのだが、計算方法がわからない。実装できない。どうすればいいんだ。教えて偉い人。

###追記

ちょっと調べてみると信頼度計算ではなくscore計算がsoftmax関数では確率に一致するらしい（？）のでそこをとっかかりにしていきたい。

参考URL
https://qiita.com/ishizakiiii/items/3b894b6e987fdf87093e
Cellular_automata

##Code
```java:cellular_automata.pde
int[] rules = {0,0,0,1,1,1,1,0};
int gen = 1;
color on = color(255);
color off = color(0);

void setup(){
  size(101,101);
  frameRate(8);
  background(0);
  set(width/2,0,on);
}

void draw(){
  for(int i = 1; i < width-1; i++){
    int left = get(i-1,gen-1);
    int me = get(i,gen-1);
    int right = get(i+1,gen-1);
    if(rules(left,me,right)==1){
      set(i,gen,on);
    }
  }
  
  gen++;
  if(gen > height-1){
    noLoop();
  }
}

int rules(color a,color b,color c){
  if((a == on) && (b==on) && (c ==on)){return rules[0];}
  if((a == on) && (b==on) && (c ==off)){return rules[1];}
  if((a == on) && (b==off) && (c ==on)){return rules[2];}
  if((a == on) && (b==off) && (c ==off)){return rules[3];}
  if((a == off) && (b==on) && (c ==on)){return rules[4];}
  if((a == off) && (b==on) && (c ==off)){return rules[5];}
  if((a == off) && (b==off) && (c ==on)){return rules[6];}
  if((a == off) && (b==off) && (c ==off)){return rules[7];}
  return 0;
}
```

##実行結果
![スクリーンショット 2019-03-18 2.25.38.png](https://qiita-image-store.s3.amazonaws.com/0/377555/fff5e102-f78e-6147-80f8-ce3bb6e8ed85.png)
Python SeleniumでAmazonをスクレイピングし商品名と価格データを収集するツール作成①

#目次
・**はじめに**
・**Seleniumのインストール**
・**Tkinterのインストール**
・**Chromedriverのダウンロード**
・**Chromedriverを動かしてみる**
・**おわりに**

#はじめに
Amazonでキーワード検索したデータをCSVに落とし込むツールを作成したいと思います。
今回はその前準備を行う手順を記載していきます。

**環境**
**・マシン : Windows10**
**・Chrome version : 73.0.3683.75**
**・Chromedriver versin : 73.0.3683.68**
**・Python : python3.7**


#Seleniumのインストール
今回のスクレイピングはseleniumでのheadlessブラウザで行っているので簡単なインストール手順を書きます。pipでの紹介となります。

```
pip install Selenium
```
……これだけです（笑）

#Tkinterのインストール
同様にTkinterのインストールも行います。

```
pip install Tkinter
```
今回の画面周りはTkinterで作成しています。

#Chromedriverのダウンロード
今回の記事では一番大変な作業になります。
こちらは筆者も苦戦したのでハマったところを主に記載したいと思います。

PythonのライブラリーでChromedriverを使用できるものがありますが環境によっては動作しないものもありますので今回はダウンロードする手順を用います。

まずは使用しているChromeのバージョンをチェックします。
Chromeのウィンドウ右上にあるメニューボタンをクリックし、表示されるメニューから［Google Chrome について］をクリックする

チェックしてから下記のサイトでChromeのバージョンと対応しているChromedriverをダウンロードします。
https://sites.google.com/a/chromium.org/chromedriver/downloads

ダウンロードしたらCドライブ直下にoptフォルダを作成し、さらにwin32フォルダをその中に作成します。
次にそのwin32フォルダ内にダウンロードしたchromedriver.exeを入れます。
階層としてこんな感じです
→**C:\opt\win32\chromedriver.exe**

これでChromedriverのダウンロード作業はおわりです。

#Chromedriverを動かしてみる
では、実際にダウンロードしたChromedriverを動かしてみます。

```python:test.py
from selenium import webdriver

#driverオブジェクト生成
driver = webdriver.Chrome(executable_path = 'C://opt//win32//chromedriver.exe')
```

これだけでうまくいけばブラウザが起動しますが、すぐに消えてしまうのでこうします。

```python:test.py
from selenium import webdriver
import time

#driverオブジェクト生成
driver = webdriver.Chrome(executable_path = 'C://opt//win32//chromedriver.exe')
time.sllep(5)
```

ブラウザを生成してから5秒間とめてやることでより可視化しやすくなると思います。

次は実際にAmazonのページへ飛んでみましょう

```python:test.py
from selenium import webdriver
import time

#driverオブジェクト生成
driver = webdriver.Chrome(executable_path = 'C://opt//win32//chromedriver.exe')

#amzonのURL
amazon_url = 'https://www.amazon.co.jp/'

#ページを取得
driver.get(amazon_url)

#5秒間ストップ
time.sleep(5)
```

これでAmazonのページが表示されれば成功です。

#おわりに
今回の記事は以上になります。
次回はTkinterによる画面の作成を記載していきたいと考えています。

筆者はデザインの才能が皆無かつTkinter自体の経験も浅いので正直かなり素朴なモノとなっております（笑）

**さいごに参考にしたページです**
<a href="https://qiita.com/memakura/items/20a02161fa7e18d8a693">Python + Selenium で Chrome の自動操作を一通り</a>
<a href="https://qiita.com/ktrkmk/items/948da8b4c6e9e2afaddc">ChromeDriver を介した e2e テストで、Chrome が起動せず失敗する</a>
<a href="https://qiita.com/nadechin/items/0a34e2182132cc1a821b">【Python】 実践 Selenium 【前編】</a>
Javaの開発でServletとJSPを分けて使う理由

プログラミング初学者です。
ServletとJSPで分ける理由を調べたので大まかな内容だけアウトプットします。
#Q1: なぜServletとJSPで分けるのか？
###A: ソースコードを管理しやすくするため
基本的に**Servlet**には[ロジック](https://wa3.i-3-i.info/word11179.html)、**JSP**には見た目部分(HTML等)を書くそうです。
イメージとしては、、
・*Servlet→普通のjavaコードを書く。*
・*JSP→大体はHTML等の見た目に関わるコードだが必要に応じてjavaコードが入っている。*

######【具体例】
・複数人で開発する際、別々のファイルで担当を分けて作業をすれば競合が起きない。
・ソースコードの可読性が上がる。　etc........
※他にも様々なメリットがあるので興味のある方は調べてみてください。


調べている中で知ったのですがJSPも仕事をしているときは最終的にサーブレットコンテナによってServletに変換されているそうです。詳しい内容は下記のURLから↓

**[URL](https://wa3.i-3-i.info/word12839.html)**

**【参照元】**
[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典](https://wa3.i-3-i.info/index.html)
Mac mini(Early 2009)のSSDを交換

初投稿です。

しばらく前にはMac miniが久しぶりのモデルチェンジをしたと話題になったのに、我が家では10年モノのCore2Duo Mac miniが現役です。Mojaveサポート外ながらMojave Patcherで無理やり使っています。
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/bdaa0aff-74f9-685f-25e3-328f36133221.jpeg" width=50%>

だいぶ前に余っていたSSDを使ってHDDから換装したものの、容量が逼迫してきました。
AliExpressで中華SSDが安く調達できたので交換することにしました。128GBで2158円でした。
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/c04fded0-5fbd-f5ff-e771-2bbfb3ea71bd.jpeg" width=50%>

さて、このMacビス止めではないので開けるのが大変。隙間に写真のようにパスネットやテレフォンカードを入れ、スクレーパーでこじ開けます。(図書カードやQUOカードだと柔らかくてうまくいかない。)
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/2177bb17-7d22-715e-34ff-d520c3dff1fd.jpeg" width=50%>

少し不安な音がしますが、力をかけるとめりめりと蓋が外れてきます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/ef8c1383-2077-88ac-47ec-3d71d29335bb.jpeg" width=50%>

光学ドライブとSSDとファンが乗っている部分をシステムボードがら分離します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/c22b0dad-192d-447c-b8d7-f227248bc2e2.jpeg" width=50%>

汚いので軽く掃除しておきます。
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/ced62584-2fce-6b56-05e9-58f01208e93b.jpeg" width=50%>

光学ドライブを外すとSSDが現れます。SSDを交換します。
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/21af3660-95f9-aef0-86ca-1e9c3f2636a1.jpeg" width=50%><img src="https://qiita-image-store.s3.amazonaws.com/0/370590/82069622-15ba-7560-1537-170af080998d.jpeg" width=50%>

挿さっていたのはSanDiskのM.2(SATA)64GBを変換ボードにはめたものでした。何に使おうとして余っていたのでしょうか。なんと単純な回路だこと。
<img src="https://qiita-image-store.s3.amazonaws.com/0/370590/3ca9681c-a2c3-338e-4276-688d78e21daa.jpeg" width=50%>

アンテナ線に気をつけながらシステムボードに固定し、蓋を閉めたら完成。

次回、OS再インストール編(→[Mac mini(Early 2009)にmacOS Mojaveをインストール]( https://qiita.com/uuu_n/items/2a72e6b9ebb669e48e9c "Mac mini(Early 2009)にmacOS Mojaveをインストール"))。裏技で最新版のOSを使っているので不具合で苦労しました。
Goでインポートしたパッケージが消されるときの対処法

# 問題

VSCodeでGo言語でプログラムを作成しているとき、
パッケージを利用しようとしてimportに参照先を追加しても削除されます。

main.go

```
package main
import "github.com/kaleidot725/suezo"
```

# 環境
ちなみに次の環境を利用しています。

| 項目 | 内容 |
| --- | --- |
| IDE | Visual Studio Code 1.32.1 |
| Extension | Go |
| Extension | Golang Tdd |


# 解決策

どうやらフォーマッタの問題のようです、
フォーマッタをgoreturnsからgofmtに変更したら解決しました。

1.「Open Folder Settings」を開く
2. 「Format Tools」を「goreturs」から「gofmt」に変える

### 設定へのたどり着き方メモ

#### 💡Open Folder SettingはExplorerを右クリックで開く
<img width="200"　Height="200" alt="Screen Shot 2019-03-18 at 1.46.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/79387/6ed4f8e3-fafd-1367-3de7-6282c4accb50.png">

#### 💡Go Formatと入力するとFormat Toolsが出てくる
<img width="1143" alt="Screen Shot 2019-03-18 at 1.54.43.png" src="https://qiita-image-store.s3.amazonaws.com/0/79387/006f7e55-5895-ce83-baeb-d3c611d71992.png">
GenerativeArt Part1

#ランダムウォーク
void stepの
choiceによってランダムに選択された4方向をつかってdotを描いていくコード

##実行結果
![スクリーンショット 2019-03-18 1.53.12.png](https://qiita-image-store.s3.amazonaws.com/0/377555/d1b370b8-7c63-1663-2948-a5ee58ea8f24.png)


##code
```java:randomWalk_1.pde
class Walker{
  int x;
  int y;

  Walker(){
    x = width/2;
    y = height/2;
  }
  
  void display(){
    stroke(0);
    point(x,y);
  }
  
  void step(){
    int choice = int(random(4));
    
    if(choice == 0){
      x++;
    }else if (choice == 1){
      x--;
    }else if (choice == 2){
      y++;
    }else{
      y--;
    }
  }
}


Walker w;

void setup(){
  size(640,360);
  w = new Walker();
  background(255);
}

void draw(){
  w.step();
  w.display();
}
```
間違えてVCCWで自動生成されるファイルもご丁寧にgitignoreに突っ込んでなかったのでgitで無視させたら1,015,563行の削減ができた話 

<img width="586" alt="スクリーンショット 2019-03-18 1.43.57.png" src="https://qiita-image-store.s3.amazonaws.com/0/244632/f14ad8fe-cc50-8040-e49b-9d3f4fbff92d.png">
えー、ヒッジョーにアホ臭い話なのですが、仕事でやってるWordPress案件をVCCWで回してまして、VCCWで自動生成されるコードを.gitignoreに追加してなかったので追加したら**1,015,563行の削減ができた**ことをお知らせします。

最初は

```
.DS_Store
.ansible
.bundle
.envrc
.github/
.idea/
.travis.yml
.vagrant
npm-debug.log
package.box
playbook.retry

/wordpress/.htaccess
/wordpress/sitemap.xml
/wordpress/sitemap.xml.gz
/wordpress/wp-config.php
/wordpress/wp-content/advanced-cache.php
/wordpress/wp-content/backup-db/
/wordpress/wp-content/backups/
/wordpress/wp-content/blogs.dir/
/wordpress/wp-content/cache/
/wordpress/wp-content/upgrade/
/wordpress/wp-content/wp-cache-config.php
/wordpress/wp-content/ai1wm-backups
```
という.gitignore（多分最初こんな感じ）だったのですが、これをいろいろ自動生成されそうなものを追加していって

```
.DS_Store
.ansible
.bundle
.envrc
.github/
.idea/
.travis.yml
.vagrant
npm-debug.log
package.box
playbook.retry
!*.gitignore
/wordpress/.editorconfig
/wordpress/.htaccess
/wordpress/index.php
/wordpress/license.txt
/wordpress/readme.html
/wordpress/sitemap.xml
/wordpress/sitemap.xml.gz
/wordpress/wp-activate.php
/wordpress/wp-blog-header.php
/wordpress/wp-comments-post.php
/wordpress/wp-config-sample.php
/wordpress/wp-config.php
/wordpress/wp-cron.php
/wordpress/wp-links-opml.php
/wordpress/wp-load.php
/wordpress/wp-login.php
/wordpress/wp-mail.php
/wordpress/wp-settings.php
/wordpress/wp-signup.php
/wordpress/wp-trackback.php
/wordpress/xmlrpc.php
/wordpress/wp-admin/
/wordpress/wp-content/advanced-cache.php
/wordpress/wp-content/backup-db/
/wordpress/wp-content/backups/
/wordpress/wp-content/blogs.dir/
/wordpress/wp-content/cache/
/wordpress/wp-content/languages/
/wordpress/wp-content/plugins/
/wordpress/wp-content/themes/index.php
/wordpress/wp-content/themes/twentyfifteen/
/wordpress/wp-content/themes/twentyseventeen/
/wordpress/wp-content/themes/twentysixteen/
/wordpress/wp-content/themes/twentynineteen/
/wordpress/wp-content/upgrade/
/wordpress/wp-content/ai1wm-backups/
/wordpress/wp-content/wp-cache-config.php
/wordpress/wp-content/index.php
/wordpress/wp-includes/
node_modules/
```

にしました。結果、
<img width="163" alt="スクリーンショット 2019-03-18 1.52.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/244632/c63b7d54-636c-1444-ed4c-f91085aa8cd1.png">
こんなアホなお兄さんの真似はしちゃダメだゾ
AWSでこれ使いますよねな用語まとめ

勤めている会社でAWSをいじって覚えるための枠が設けられる模様でちょっと用語をまとめておきます

## EC2
仮想サーバを調達できるサービス
利用したいサーバのスペックに応じてインスタンスタイプを決める

### AMI（Amazon Machine Image）
仮想サーバに必要な情報が入っていて、２種類ある
大きな違いは生存期間
1. インスタンスストア - インスタンスを停止or削除するとなくなる（リブートはできる）
2. EBS - 作成して削除するまで生存する（インスタンスに依存しない）

、、、こいつか！いつまで経っても自分のアカウントで料金が発生しているのは！
インスタンス停止してから２,3ヵ月くらい経つけど今月も$0.50請求が！
デタッチしてDeleteしてやっと削除しといた

インスタンスストアはインスタンスの停止でも復元できなくなるので、なくなって困るものは置けないのでキャッシュなどに向いていて、基本的にはEBSを指定します

### EIP(Elastic IP Address)
固定のグローバルIPを取得してインスタンスに付与できるサービス

またしても曲者です
EIPはインスタンスでEIPを１つだけ関連づけるとか通常は基本的には料金は発生しません

しかしEIPが関連づけているインスタンスが停止していると料金がかかります
あとインスタンスに関連づいてないEIPも料金がかかります
EIPを別のインスタンスに付け替えまくっても料金がかかります

使わないときはアドレスは解放しましょうということです

## Route 53
DNSサービス
DNSサーバへの問い合わせ結果をキャッシュしておくキャッシュDNSサーバの機能はないです

SLA（Service Level Agreement）１００％で、応答しない時間が発生したりすると払い戻しを受けられるそうです
まあでもその払い戻しもRoute 53にしか使えないですがね
詳しくは↓
[Route 53 SLA](https://d1.awsstatic.com/legal/AmazonRoute53SLA/Amazon%20Route%2053%20Service%20Level%20Agreement%20-%20Japanese%20(2018-11-21).pdf)

## VPC
仮想ネットワークを作成できるサービス
まあ仮想ルータです

AWSアカウントを作成するとデフォルトのVPCが作成されます

## S3
ストレージ

### バケット
S3に格納されるオブジェクトのコンテナ
バケットの名前はユニークでないとダメです（ほかのユーザががすでに作成している名前はダメ）

### S3にはフォルダのようなものがありますが、フォルダではない？
S3はKey-Value型データストアなので最後が/(スラッシュ)で終わるものはValueのないKeyということでサイズが0のファイル扱いとなっています

```
# 以下のような場合はhoge配下にfuga.txtがあるわけではなく、hoge/fuga.txtがKey名
hoge/
hoge/fuga.txt
```

### CloudFront
CDNサービス
EC2やS3などにあるコンテンツをエッジロケーションにコピーし、そこから配信することで高速にコンテンツを提供できる

## RDS
リレーショナルデータベースサービス
OSの管理やパッチ当てなどをAWS側でやってくれます

## ELB
自動で拡張と縮小を行うロードバランサーサービス

## CloudWatch
AWSサービスの監視やモニタリング

## IAM
ユーザーとユーザー権限を管理する

端折ったのは今度かいつか深掘りします
（EBSの時点で個人的な問題が解決してしまった(-_- ;)
GriveでGoogleドライブをLinuxマシンと同期する

Googleドライブは便利ですが、自動でファイルエクスプローラーからアクセスできる機能は、WindowsやAndroid等でしか提供されておらず、Linuxマシンをデスクトップとして使っている場合不便です。

ここでは、Googleドライブのディレクトリの内容を、ローカルの特定ディレクトリの内容と同期して、ファイルをいい感じに移動させたりしたいと思います。

# Grive2のインストール

griveは更新が2年ほど前で終わっていますが、有志がフォークしてgrive2を作っているのでそれを使います。

https://github.com/vitalif/grive2 のREADME.mdやwikiに書いてあるとおり、CMakeでビルドしてインストールするのですが、自分はArchlinuxのAURがあったのでそれを使いました。

# ディレクトリの設定

```
cd $HOME
mkdir google-drive
cd google-drive
grive -a
```


`grive -a`を実行すると、URLが表示されるので、コピーしてブラウザで開きます。
開くと、Googleの認証画面でGoogle Driveへのアクセス権を尋ねられるので、連携or許可をクリックします。

そうすると、認証キーが表示されるのでターミナルに貼り付ければ完了です。

あとは自動でGoogleドライブ上の全ファイル・ディレクトリがダウンロードされます。

# 自動同期

```
systemctl --user enable grive-timer@$(systemd-escape google-drive).timer
systemctl --user start grive-timer@$(systemd-escape google-drive).timer
systemctl --user enable grive-changes@$(systemd-escape google-drive).service
systemctl --user start grive-changes@$(systemd-escape google-drive).service
```

上の例では、`google-drive`という名前のホームディレクトリ直下のディレクトリを同期しています。
`grive-timer@.timer`で5分間隔の自動ダウンロード、`grive-changes@.service`でinotifyファイル検知を使って自動アップロードをしています。

これで、Google Driveでファイルの作成/削除やローカルでファイルの作成/削除をすると、同期されるようになりました。

※AURにはsystemdのファイルがなかったので、ソースから.inを直接ダウンロードして手直しして入れました。

#まとめ

内容が、README.mdを日本語訳しただけなので、ほどんど「いかがでしたかブログ」並に薄くなってしまいましたが、役に立てば嬉しいです。

今回のgrive2は、必要になったらファイルの実態をダウンロードする方式(google drive ocamlfuse mount)とは違い、単純にダウンロードして差分同期を取る方式でした。

自分はネットワーク帯域もストレージ帯域も余裕が有り、こちらのほうが便利で使いやすかったのですが、これは人によって異なると思うので、両方試して自分が使い勝手の良い方を使ってみると良いと思います。
スマート家電コントローラSmart Lifeで出来ること出来ないこと

# スマート家電コントローラでできることをまとめてみた

#### 使ったもの

* 買った家電コントローラ
  [Iriscargo](https://www.amazon.co.jp/dp/B07MHZ7PC5/ref=cm_sw_em_r_mt_dp_U_B1MJCbJBA9P6G)
* スマホ
  iPhone 7, iOS 12.1.4
* **スマホアプリ
  Smart Life 3.8.5**  
  スマート家電コントローラの機能と使い勝手の9割はスマホアプリで決まります。
* Google Home  
  miniではない方です
* テレビ
  [Panasonic REGZA49G20X](https://www.toshiba.co.jp/regza/lineup/spec/49g20x.html)
* 照明（シーリングライト） NEC製  
  照明器具のプリセット設定はSmart Lifeに用意されていません。DIYで設定します。
* エアコン
  [三菱電機霧ヶ峰MSZ-GV283,2014年製](https://www.mitsubishielectric.co.jp/ldg/wink/ssl/displayProduct.do?pid=211311)

#### できることできないこと

| 操作 | Smart Life<br>アプリ | Siri | Google Home<br>アプリ | Google Home<br>音声入力 |
| --- | --------- | ------------ | --- | --- |
| テレビを点けて<br>（テレビのオン・オフ） | できる | できる | できる | できない |
| テレビのボリュームを下げて | できる | できる | できない | できない |
| テレビのチャンネルを変えて | できる | できない | できない | できない |
| 明かりを点けて<br>（照明のオン・オフ） | できる | できない | できない | できない |
| エアコンを点けて<br>（エアコンのオン・オフ） | できる | できる | できる | できる |
| エアコンの温度を20度にして | できる | できる | できない | できない |

IFTTTを使わない場合です。IFTTTを使うと「テレビを点けて」がGoogle Home音声入力で可能になるが、ボリュームやチャンネルは変更できないと思います（未検証）。

#### 総論

私にとってはGoogle Homeの音声入力でテレビのチャンネルを変えたかったのでSmart Lifeはそれができず機能不足でした。IFTTTを使うとテレビの電源のオン・オフだけできそうです。

#### 設定でハマッタ点

* 私の環境の場合、Google HomeのアカウントとSmart Lifeのアカウントのメールアドレスを同一にする必要がありました。気づいて設定を変更したのですが、401 auth permissionエラーが出ました。結局、iPhoneの設定-Safari-履歴とWebサイトデータを消去、することで連携させることができました。一度、アカウントエラーが出ると履歴を消す必要があるようです。
* 家電コントローラIriscargoをスマホアプリとペアリングしてWifi設定を入力するためにはIriscargoのリセットボタンを長押ししてペアリングモードにする必要があります。リセットボタン長押しの動作が紙のマニュアルには書いてありませんでした。ペアリングモードではステータスインジケータが1秒おきに点滅します。私はつまようじで長押ししました。

関連
[スマート家電コントローラ「家電リモコン」で出来ること出来ないこと](https://qiita.com/kenbunji/items/b8357e2b00cb72cb9792)
四平方定理

- [四平方定理](https://yukicoder.me/problems/no/800)

## コンテスト中の考察

- 愚直だと$O(N^4)$で死
- x, y, zを決め打てば$O(N^3)$になる。Nの最大値は2000で、$N^3 = 8\times10^3$。ワンチャン通らねえかなぁと思って投げたらTLE。これに近い解法もTLE。この解法は無理っぽい
- 二分探索とかは無理そう。できても3つ決め打たないと無理っぽいので計算量が死。
- [Prime Square Sum](https://qiita.com/nomikura/items/dbda569b6c83cc1e94a1)と似た雰囲気を感じるので考えてみる。
  - あの問題は$A^2 + B^2 + C^2 = N$の式を考える問題。Aに注目して考えると、$B^2 > 0, C^2 > 0$なので$A^2 < N$となる。よって$A < \sqrt{N}$の範囲で数字を列挙することで解けた。
  - この問題は$x^2 + y^2 + z^2 = w^2 + D$という式。$x$に注目すると$x^2 < w^2 + D$みたいになる。ただ、これをやっても計算量が減らない。なのでこのアプローチは無理。
- 式をこねくり回しても何も出てこない。もう一つ式を作ればなんかうまくいくかと思ったけど全然無理。えーん
- ようつべたのちい
- おしまい



## 解けなかった原因

- 値を一気に確定させないといけないと思ってしまっていた
  - x, y, zを一度に確定させないとwを確定させられずに死ぬって思ってた
  - x, yとz, wを別々に決めて合成するっていう発想がなかった。
  - 解法は半分全列挙らしいんだけど、「半分全列挙=bitをつかう」だと思ってた。アホ



## 解法

- 与式$x^2 + y^2 + z^2 = w^2 + D$を$x^2 + y^2 = w^2 - z^2 + D$に変形する
- すると、左辺に$x, y$で右辺に$w, z​$といった感じに変数が分割される。
- 左辺と右辺の組み合わせを別々に計算しておく。そんで、最後に左辺の組み合わせの数と右辺の組み合わせの数の積を多脚合わせていく。
- 計算量は$O(N^2)$となる



## [コード](https://yukicoder.me/submissions/325401)

```cpp
#include <bits/stdc++.h>
using namespace std;

#define int long long

int N, D;
int XY[2*2000*2000+100]; // XY[i]: 左辺がiになる組み合わせの数
int WZ[2*2000*2000+100]; // WZ[i]: 右辺がiになる組み合わせの数

signed main() {
  cin >> N >> D;
  // 左辺 (x^2 + y^2) の組み合わせを数える
  for (int x = 1; x <= N; x++) {
    for (int y = 1; y <= N; y++) {
      int left = x*x + y*y;
      XY[left]++;
    }
  }

  // 右辺 (w^2 - z^2 + D) の組み合わせを数える
  for (int w = 1; w <= N; w++) {
    for (int z = 1; z <= N; z++) {
      int right = w*w - z*z + D;
      // 式が複雑なので判定を入れておく
      if (right >= 2 and right <= 2*N*N) {
        WZ[right]++;
      }
    }
  }

  int ans = 0;
  // (値がiとなる左辺の場合の数 * 値がiとなる右辺の場合の数)を足し合わせる
  for (int i = 2; i <= 2*N*N; i++) {
    ans += XY[i] * WZ[i];
  }

  cout << ans << endl;

  return 0;
}
```



## [別解](https://yukicoder.me/submissions/325484)

- 本質部分はさっきと同じで式変形して半分全列挙する。片方は前計算で求めておいて、もう片方は二分探索で探す。
- 計算量は$O(N^2logN)$

- [4 Values whose Sum is 0](http://poj.org/problem?id=2785)と同じ解き方（蟻本に載ってる）

```cpp
#include <bits/stdc++.h>
using namespace std;

#define int long long

int N, D;
int AB[2222*2222];

signed main() {
  cin >> N >> D;

  int cnt = 0;
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      AB[cnt] = i*i + j*j;
      cnt++;
    }
  }

  sort(AB, AB+cnt);

  int ans = 0;
  for (int i = 1; i <= N; i++) {
    for (int j = 1; j <= N; j++) {
      int num = i*i - j*j + D;
      int left = lower_bound(AB, AB+cnt, num) - AB;
      int right = upper_bound(AB, AB+cnt, num) - AB;
      ans += right - left;
    }
  }

  cout << ans << endl;

  return 0;
}
```





## 要点

- 等式の半分全列挙
  -  右辺と左辺で別々に値を計算して最後に合成する
  - 全列挙無理→3個決め打ち無理→半分全列挙考えるって感じだろうか。よくわからん



## 感想とか

- 難しい。解けなかった。えーん
- 100人近く通してるので日本は安泰。有能すぎる
- 「半分全列挙＝bitをつかう」だと思ってた。全列挙の半分が高速だったら半分全列挙を考える価値がありそう
- 蟻本の「くじびき」が類題。P8が問題説明でP25が解説。
- 蟻本P147の[4 Values whose Sum is 0](http://poj.org/problem?id=2785)もこの問題の類題。
Tweepyで大量のフォロワー情報を取得する

# 背景
お遊びで、Twitterの某アカウントのフォロワー情報を大量（約20万件）に取得する必要が生じた。
一部トラブルが生じたので、似たようなことをする時の備忘として、方法を残しておく。

# 環境
- Windows 10 Pro
- Python 3.6.6
- Tweepy 3.6.0

# 準備
- 以下の記事を参考に、Twitter APIの登録申請を行う。
    - [Twitter API 登録 (アカウント申請方法) から承認されるまでの手順まとめ　※2018年9月時点の情報](https://qiita.com/kngsym2018/items/2524d21455aac111cdee)
- Tweepyをインストールする（Anaconda）。

# ソースコード
最初は、Qiitaで探した記事を参考に以下のようなコードを動かした。

```python:get_followers1.py
auth = tweepy.OAuthHandler('XXXXX...', 'XXXXX...')
auth.set_access_token('XXXXX...', 'XXXXX...')
api = tweepy.API(auth, wait_on_rate_limit=True)
followers_ids = tweepy.Cursor(api.followers_ids, id='XXX', cursor=-1).items()
for follower_id in followers_ids:
    try:
        user = api.get_user(follower_id)
        user_info = [user.id_str, user.screen_name, user.name, user.created_at]
        print(user_info)
    except tweepy.error.TweepError as e:
        print(e.reason)
```

ところが、数時間後、以下のようなエラーが発生した。

```
During handling of the above exception, another exception occurred:

Traceback (most recent call last):
～（中略）～
    raise ConnectionError(err, request=request)
tweepy.error.TweepError: Failed to send request: ('Connection aborted.', OSError("(10054, 'WSAECONNRESET')",))

プロセスは終了コード 1 で完了しました
```

どうやら認証後、接続時間が長すぎたらしい。
なので、カーソルを保存し、一定周期で認証し直すように変更した。

```python:get_followers2.py
cursor = -1
while cursor != 0:
    auth = tweepy.OAuthHandler('XXXXX...', 'XXXXX...')
    auth.set_access_token('XXXXX...', 'XXXXX...')
    api = tweepy.API(auth, wait_on_rate_limit=True)
    itr = tweepy.Cursor(api.followers_ids, id='XXX', cursor=cursor).pages()
    try:
        for follower_id in itr.next():
            try:
                user = api.get_user(follower_id)
                user_info = [user.id_str, user.screen_name, user.name, user.created_at]
                print(user_info)
            except tweepy.error.TweepError as e:
                print(e.reason)
    except ConnectionError as e:
        print(e.reason)
    cursor = itr.next_cursor
```

今度は最後まで上手くいった。
CodestarでLayerを作ろうとして粘ったがだめだった話

##AWS CloudformationでLayerを作る際の障害
AWS Cloudformationは非常に便利なサービスである反面、痒いところに手が届かないサービスでもある。
lambda Layerは最たるもので、コードのアップロードの方法は今の所S3へのファイルアップロードしかサポートされていない。
[AWS Lambda LayerVersion Content](https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-properties-lambda-layerversion-content.html)
ただ、Layerの素晴らしいところは、複数のlambdaで利用している機能の一部をモジュール化できるところだ。
これは非常に魅力的だが、予めS3にデータをアップロードしておかなければならない。

以下は、どうにかしてlayerをCloudformationで楽にできないかと悪戦苦闘してだめだった失敗談である。

#悪あがき
##状況
Codestarでプロジェクトを作成し、編集していた。途中でLayerが使いたくなった

##所見
まず、一連のサービスについて当時は以下のように認識していた。

- ymlに構造を記載する
- CodeBuildで、buildspecに記載したunixコマンドを実行しているっぽい
- $がついているのは変数っぽい？→変数であることを確認
- ならば、他のUnixコマンドも動くかも？

##echoを試してみる
変数っぽかった
逆説的に、ディレクトリの構造さえわかればS3のバケット名とキーを特定できるのでは？と考えた。

```yml:buildspec.yml
phases:
  install:
    commands:

      # Upgrade AWS CLI to the latest version
      - pip install --upgrade awscli
      - echo $S3_BUCKET

```

```text:codebuild
aws-codestar-ap-northeast-1-<AccountID>-<ProjectName>-pipe

```
buildspecには、unixコマンドが記載されており、変数も実行できることが確認できた。また、CodeBuildのlog画面の上の方に、次のような変数を確認した。

```text:log
CODEBUILD_SRC_DIR=codebuild/output/src780260603/src
```

こちらも`echo`で試してみると、ディレクトリが得られた。

```yml:buildspec.yml
- echo $CODEBUILD_SRC_DIR 
```

```text:codebuild
codebuild/output/src780260603/src

```

`ls`コマンドを使ってみると、たしかにお目当てのファイルがあった。
  -ls $S3_BUCKET
```

```text: log
python1_dir
python2_dir
module_dir
```

では、これをどうにかしてtemplate.yml内に反映させられればできるのではないか？と考えて１時間ほど調べた。

##sedの発見（笑）
そんな中、ふと`buildspec.yml`を見ると、次のような箇所があった。

```yml:buildspec.yml
sed -i.bak 's/\$PARTITION\$/'${PARTITION}'/g;s/\$AWS_REGION\$/'${AWS_REGION}'/g;s/\$ACCOUNT_ID\$/'${ACCOUNT_ID}'/g;s/\$PROJECT_ID\$/'${PROJECT_ID}'/g' template-configuration.json
```
なんとなーく「文字列を置き換えているのかな？」と考えたらビンゴ。
[sed コマンド](https://hydrocul.github.io/wiki/commands/sed.html)
~~常識的なコマンドじゃないかって？こちとら去年Raspberry Piで初めてWidows以外のOSに触った筋金入りの初心者なんだよ。~~

早速使ってみたい。

##sedを使って置換
どうもこうすれば置換できるらしい。

```shell:command
ed -i 's/<置換対象の文字列>/<置換したい文字列>/g;'
```
また、このままでは、`$S3_BUCKET`はテンプレート内でそのまま`$S3_BUCKET`として置換されてしまう。そのため、シングルクオートではなく、ダブルクオートで囲む。
[まくまくsed/awkノート
sed の置換パターンの中でシェルの変数を参照する](https://maku77.github.io/sed/sed/shell-variables.html)
これでいけるはずだッ！！
と思うもエラーログ
```text:log
No such key
```
どうも、S3にはそんなファイルがないようだ
ここからは何度試してもだめだった。

##そもそも前提条件が違った
というかそもそも、さっきから見ていたのは、**決してS3のディレクトリ(キー)構造ではなく、CodeBuild内に構築されているビルド環境内のディレクトリ構造である**という視点が抜けていた。
[CodeBuild の概念](https://docs.aws.amazon.com/ja_jp/codebuild/latest/userguide/concepts.html)


##実質的にLayerのようなものは作れる
色々試したがだめだった。
それでも、共通(または類似)した処理のコード変更が発生した際、いちいち全てのファイルをチェックするのは面倒くさい。


そこで、落ち着いて今考えると次のようなコマンドをbuildspecのcommに記載すれば実質Layerみたいに使えることに気がついた。

```text:directory
cloudformation ---- python1 -- first.py
                |
                |-- python2 -- second.py
                |
                --- common_modules -- common_module.py
```

```yml:buildspec
#略
　- cp ./common_modules/common_module.py ./python1/
　- cp ./common_modules/common_module.py ./python2/
#略
```

~~要するに手段と目的が逆転していたんですね~~

##感想その他
結局やりたかたことはできなかったが、目的は達成できた。
また、なんだかんだCodeBuildやCloudformationの仕様にもなれることができたので良しとする。
~~なお進捗~~
ntopngの日本語版が利用可能になりました

ntopngはネットワークトラフィック測定で有名なツールですが、このたび不思議なご縁がありまして**日本語化のPullRequestを送信し、承認されました!**
[本家ブログポスト。私の名前も載せてもらえました。正確には多言語化対応]
(https://www.ntop.org/announce/ntopng-multilanguage-support-en-it-de-and-jp/)
既にgit cloneすると日本語表示が選択可能となっています。
そこで、今一度ntopngの機能について振り返ってみようと思います。
[本家サイト](https://www.ntop.org/products/traffic-analysis/ntop/)

#ntopngとは
ntopngはntop next generationの略でありネットワークの利用状況を監視するソフトウェアです。ntopngはlibpcapをベースとしておりUnix, MacOSX、Windows上での実行を可能としています。(注:最新のダウンロードのサイトではUbuntu, CentOS/RHEL, Windowsはダウンロード可能なようです。)

#主要機能(Main Feature)
* ネットワークトラフィックをIPアドレス、ポート、L7プロトコル、スループット、ASなど様々観点でソートすることができます。
* リアルタイムにネットワークトラフィックとアクティブなホストを表示します
* スループットやアプリケーションプロトコルといったネットワークメトリックに基づくレポートの作成が可能です
* Top talkers (senders/receivers), top ASs, top L7 applications
* 現在のスループット、ネットワーク遅延、アプリケーション遅延、Round Trip Time(RTT), TCP統計情報(再送、out of orderパケット、パケットロス)、送受信したパケット数、バイト数
* ディスク上にトラフィックの統計情報を保存できるので事後の分析を容易にします。
* ホストの地理上の位置を地図上にマッピングして表示することができます
* ntop社のDPI(Deep Packet Inspection)技術であるnDPIを利用することによりアプリケーションレベルのプロトコル(Facebook, YouTube, BitTorrentなど)を発見することが可能
* Characterise HTTP traffic by leveraging on characterisation services provided by Google and HTTP Blacklist.
* IPトラフィックを分析し、ソース／デスティネーションに基づきソートする
* プロトコルタイプごとにIPプロトコルの利用状況を表示する
* HTML5/AJAXを利用したネットワークトラフィック統計情報の表示
* IPv4とIPv6のフルサポート
* ARP統計情報を含むレイヤ2のフルサポート
* GTP/GREのデトンネリング
* 監視データのMySQL, ElasticSearch, LogStashへのエクスポート
* MySQLにエクスポートしたデータをインタラクティブに分析
* 異常あるいは疑わしいホストを検出するアラートエンジン
* SNMP v1/v2cをサポートしSNMPデバイスを継続的に監視

![Qiita](https://i1.wp.com/www.ntop.org/wp-content/uploads/2017/05/03-ntopng-active-hosts-e.png?fit=1216%2C693&ssl=1)

# 利用可能なバージョンについて
ntopngは以下のバージョンが存在しています。CommunityバージョンはOSSであり無償での利用が可能です。Professional (Small Business Edition)はSmall Office向け、企業向けのEnterpriseの3種類になります。Professional, Enterpriseについてはntopのshopからライセンスを購入することにより永久ライセンスと1年間のサポートが入手可能です。

* Community
* Professional
* Enterprise

Community, ProfessionalバージョンはEnterpriseバージョンと比較して機能制限が存在しています。詳細は以下の表になりますが、主にレポート機能やスケールに関連する最適化、監視可能なＩＦ数、トラフィックレコード時間等に違いがあるようです。

[比較表](https://www.ntop.org/products/traffic-analysis/ntop/)
GitLabのコンテナをWindows上で構築したい

# はじめに
- Docker Desktop for Windowsをインストール
- DockerのSettingsからボリューム設定に使用するドライブを共有化しておく。**共有化する際にエラーが発生する場合は、Windows Firewallの設定か、3rd partyのセキュリティソフトでブロックされている可能性あり。**それらの設定でDefaultSwichのネットワーク通信の許可を行うとうまくいくみたい。

# GitLabのコンテナ作成＆起動
- GitLabのイメージがまだ無くても、docker runで自動的にイメージをダウンロードしてくれる。
- ３つのボリュームを指定する(log, config and data)
    - この時configとlogにはWindowsのディレクトリを指定することが可能。（下記例ではE:/Docker/gitlab/config, E:/Docker/gitlab/logs）
    - 指定の仕方は以下のように＜ドライブ名＞:から始まるようにする（/E/Docker/gitlabではうまくいかなかった。）
    - **dataにWindowsのディレクトリを指定するとうまくいかない模様…代わりにnamed volumeを指定する。** named volumeは”docker volume create gitlab”のようにコマンドを打っても作成できるが、無ければ自動で作成してくれるみたい。以下のコマンドをいきなり打つだけでOKだった。

```
docker run -i --hostname gitlab.sample.com --publish 80:80 --publish 22:22 --name gitlab --restart always --volume E:/Docker/gitlab/config:/etc/gitlab --volume E:/Docker/gitlab/logs:/var/log/gitlab --volume gitlab:/var/opt/gitlab gitlab/gitlab-ce:latest
```
- 起動したらブラウザでlocalhostにアクセスすれば最初のページが見える。ちなみに**上記コマンドを打っても処理がずっとループしているような現象がみられた。**（ページにアクセスは可能だった。）その後、"docker stop gitlab"で停止した後、"docker start gitlab"で再開するとループは見られなかった。
CDK(Chemical Development Toolkit)でAtomic Descriptorを計算する

# はじめに
CDKは、分子に関する記述子の他、原子や結合、原子と原子同士に関する記述子も用意されている。今回は、原子の記述子である次数を求める記述子を使ってみたのでメモっておく。CDKネタが続いて恐縮であるが、もともとCDKに興味を持ったのが原子や結合の記述子が用意されており、これを試したかったからである。

# 環境
- Windows 10
- Java 11
- CDK 2.2

# ソースコード
以下の通りである。

```AtomicDescritor.java
import org.openscience.cdk.DefaultChemObjectBuilder;
import org.openscience.cdk.interfaces.IAtomContainer;
import org.openscience.cdk.io.iterator.IteratingSDFReader;
import org.openscience.cdk.interfaces.IAtom;
import org.openscience.cdk.smiles.SmiFlavor;
import org.openscience.cdk.smiles.SmilesGenerator;
import org.openscience.cdk.tools.manipulator.AtomContainerManipulator;
import org.openscience.cdk.qsar.descriptors.atomic.*;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;

public class AtomicDescriptor {

    public static void main(String args[]){

        if(args.length!=1){
            System.err.println("AtomicDescriptor <sd-file>");
            System.exit(1);
        }
        FileInputStream fis = null;
        IteratingSDFReader isr = null;
        try{
            fis = new FileInputStream(new File(args[0]));
            isr = new IteratingSDFReader(fis, DefaultChemObjectBuilder.getInstance() );

            while( isr.hasNext() ) {
                IAtomContainer mol = (IAtomContainer) isr.next();
                String id = (String) mol.getProperty("cdk:Title");
                SmilesGenerator sg = new SmilesGenerator(SmiFlavor.Generic |SmiFlavor.UseAromaticSymbols);
                AtomContainerManipulator acm = new AtomContainerManipulator();
                AtomDegreeDescriptor add = new AtomDegreeDescriptor();
                try {
                    String can = sg.create(acm.removeHydrogens(mol));
                    System.out.println(id + ":" +can);
                    for (IAtom atom : mol.atoms()) {
                        System.out.println("  " + atom.getAtomicNumber() + ":" + add.calculate(atom, mol).getValue());
                    }
                }catch(Exception e){
                    e.printStackTrace();
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            if(isr != null) {
                try {
                    isr.close();
                }catch(IOException e2) {
                    e2.printStackTrace();;
                }
            }
            if(fis != null) {
                try {
                    fis.close();
                }catch(IOException e2) {
                    e2.printStackTrace();
                }
            }
        }
    }
}
```

# 結果
こんな感じ。原子番号と次数が表示されている。構造がないと分かりにくいと思うが。

```
n-pentane:CCCCC
  6:1
  6:2
  6:2
  6:2
  6:1
cyclopentane:C1CCCC1
  6:2
  6:2
  6:2
  6:2
  6:2
```

# 何をしているか
今回は原子の次数を求めた。次数とは、水素以外の置換基の数である。
例えばCCCCCは、両端の炭素は、3つの水素と1つの炭素と結合してることから次数=1である。真ん中の3つの炭素は、両隣の2つの炭素および、2つの水素と結合してるため、次数=2となる。

他にもさまざまな記述子が用意されているため、今後調査していきたい。

### 参考
どのようなDiscriptorが用意されているかは、以下を参照。
- [CDKのJavaDoc](http://cdk.github.io/cdk/2.2/docs/api/org/openscience/cdk/qsar/descriptors/atomic/package-summary.html)
Nuxt.js の store が cannot read property ... となって動かなかったときの対策

## はじめに

これは Nuxt.js を触り始めたばっかりの超初心者が書いてます。
なので、上級者から見たら「そんなのあったりまえじゃないかー」みたいなことを書いてるかもしれませんがそこはご容赦ください。
逆に、これから始める人が自分みたいに何時間もこんなところで躓かないための道標になれるれば幸いです。

## 事の発端

最近 Nuxt.js をさわりはじめました。
Vue.js 自体は半年くらいいじってて、Vuex も一応多少は使ってる、といったレベルです。

で、今回はなんとなーく Nuxt.js 触り始めて、徐々に規模が大きくなってきたしここいらで Vuex やっとくかーって思って公式ドキュメントとかみながら書いてみたのですが、どうがんばっても（それこそサンプルコード丸写しレベルまでいっても）

```
Cannot read property 'commit' of undefined
```

って怒られてしまう、といった状況になってしまいました。
（あるいは dispatch が無いって言われるパターンもあり）

Vue Devtools をみても、確かに Vuex タブが空っぽで、そりゃ怒られるよな…って状況ではあったのですが、そもそもなぜ出てこないのか。
ぜんぜん意味がわからず、あれこれと調べてみたところ、ある１つの stack overflow の投稿に、思いもよらない解決方法があったのでした。

## 解決方法

<font color="red">$\huge{devサーバーを再起動する}$</font>

以上。

つまり、`Ctrl + C` を押して一旦 Nuxt の dev server を停止し、改めて

```bash
yarn dev # or npm start
```

を実行します。
たったこれだけでした:sob:
<font color="silver">~~悩みまくった3時間を返してくれ~~</font>

どういうわけか、 Nuxt の store はつくっただけじゃ反映せず、dev server を再起動しないといけないみたいです。

まぁ、解決方法がわかってしまえばどうってことはないのですが、ただこれって、多分一旦諦めて、サーバー停止して、翌日とかにまた立ち上げたら治ってしまってただろうし、そうなってたらまた別のプロジェクトを作ったときにおなじようにドハマリしてしまってた可能性もあるわけで、気づけてよかったのかなぁ、と。

そしてきっと多分絶対またやらかすと思うので、忘れないためにもここに残して置こうと思ったのでした。


### 参考リンク

[Vuex store is undefined in NUXT middleware](https://stackoverflow.com/questions/50120277/vuex-store-is-undefined-in-nuxt-middleware)
コマンドライン引数とは

プログラミング初学者です。(Javaを学習中)
コマンドライン引数について疑問に思ったことと、疑問に対する自分なりの理解を書きます。

#Q1: コマンドライン引数とは？
###A: プログラムを起動した際に一番最初に渡される情報
コマンドライン引数に最も多く設定されるのはファイルの情報だそうです。(文字や数値でもOK)
設定するときに必要なデータが入っているフォルダのパスを指定してあげればフォルダの中身の情報が取得できます。
いちいちコードを書かなくてもファイルの情報を勝手に持ってきてくれるから便利だなー。
と感じました。
#Q2: コマンドライン引数の情報はどこに渡されるの？
###A: mainメソッドの引数部分
↓ここです↓
![fullsizeoutput_18.jpeg](https://qiita-image-store.s3.amazonaws.com/0/305584/4501ff8f-0705-b265-2aaa-309745622a77.jpeg)
javaの仮想マシン(VM)から最初に呼び出されるのは、"public static void main(String[] args)"と決まっているらしくString型の配列で受け取っています。ちなみに変数名だけは別に"args"じゃなくても良いそうです。
#Q3: mainメソッドは他の場所から引数の値を受け取れないの？
###A: mainメソッドの引数はコマンドライン引数専用である
mainメソッドプログラムの中で一番最初に呼ばれるため下記の画像のようにメソッドで引数を渡すことができません。
だからコマンドライン引数で情報を渡してあげる必要があるんですね。
![fullsizeoutput_19.jpeg](https://qiita-image-store.s3.amazonaws.com/0/305584/b1a1dfd4-fd46-a977-0aed-b820963199f9.jpeg)

初学者らしい拙い内容になっているとは思いますが、誰かの役に立てれば幸いです。
内容に不備がありましたら恐れ入りますがコメントをください。
読んでいただきありがとうございました。

**【下記参照元】**
*「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典*
https://wa3.i-3-i.info/word11643.html
*Samurai Blog*
https://www.sejuku.net/blog/65082
WSL, UbuntuでPython環境構築を楽したい

# 0. 筆者環境

Windows 10 Home 64bit
Ubuntu 18.04 LTS

# 1. 概要

WSLでUbuntu環境構築してみたので、その際使用したスクリプトを共有する。
このスクリプトでは一般なOS Update～python環境構築までをサポートしているつもり。

# 2. 本体+使用法

以下を"setup.sh"として任意のディレクトリに保存し、実行する。

```shell:setup.sh

#!/bin/bash


# WSL for Ubuntu setup sh
# WSL有効化(PowerShell管理者権限で実行)
# Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Windows-Subsystem-Linux


# 日本に向けてリポジトリ変更
sudo sed -i -e 's%http://.*.ubuntu.com%http://ftp.jaist.ac.jp/pub/Linux%g' /etc/apt/sources.list

# NTP設定(時刻同期)
sudo ln -sf /usr/share/zoneinfo/Asia/Tokyo /etc/localtime
sudo sed -i 's/#NTP=/NTP=ntp.nict.jp/g' /etc/systemd/timesyncd.conf

# Update
sudo apt update
sudo apt full-upgrade -y
sudo apt autoremove -y
sudo apt clean -y

# 日本語化
sudo apt install -y language-pack-ja
sudo apt install -y manpages-ja
sudo update-locale LANG=ja_JP.UTF-8

# Package Install
sudo apt install -y vim-nox git zsh zsh-syntax-highlighting gcc g++ make openssl zlib1g-dev libssl-dev libbz2-dev libreadline-dev libsqlite3-dev vim build-essential curl wget llvm libncurses5-dev xz-utils tk-dev libxml2-dev libxmlsec1-dev libffi-dev liblzma-dev
sudo apt install -y python3-pip

# 好みで、
# chsh -s /bin/zsh

# pyenv
git clone https://github.com/yyuu/pyenv.git ~/.pyenv
echo 'export PYENV_ROOT="$HOME/.pyenv"' >> ~/.bashrc
echo 'export PATH="$PYENV_ROOT/bin:$PATH"' >> ~/.bashrc
echo 'eval "$(pyenv init -)"' >> ~/.bashrc
source ~/.bashrc
pyenv install 3.7.3
pyenv global 3.7.3
pyenv rehash

# pip Update
pip install --upgrade pip
pip3 install --user pipenv
echo 'export PATH="$HOME/.local/bin:$PATH"' >> ~/.bashrc
echo 'export PIPENV_VENV_IN_PROJECT=1' >> ~/.bashrc
source ~/.bashrc

# Python 3.7.2
python -V

```
Pythonチートシート作りました

#️⃣Pythonチートシートを作成しました

コード書くときに
あれちょっと忘れたなーとか
どう書くんだったけかなーとかで

いろいろ調べ物する時間って
もったいないですよね

なのでPythonのチートシートを作成しました。

**Note**

### [Pythonチートシート](https://note.mu/otupy/n/n1bedb9f36e54)



キーワードで検索すれば
探し物を見つけることができるようにしてあります。

使い方を忘れた時などに参考にできるよう
用法にサンプルを添えてあります。

なるべく通常の業務内で良く使うコードをまとめたつもりですが、
足りなければどんどん足しますので
ご要望はコメント願います。

対応version
Python3.6以降


## 項目
```
基本
ジェネレーター
クラス
例外処理(try except)
演算子
文字列関数
組み込み関数
リスト
辞書
range関数
set(集合)
集合演算(set)
map
filter
reduce
enumerate関数
zip関数
内包表記
ソート
日付操作(datetime)
正規表現
UNICODEの正規化(unicodedata)
文字列フォーマット
csv
json
エクセル excel(openpyxl)
sys
ディレクトリ、ファイル操作(os , open , gzip , zip)
コンフィグファイル(configparser)
順列、組み合わせ
ランダムモジュール(random)
数値計算(math , Decimal)
平均、標準偏差を求める(statistics)
スクレイピング(requests , BeautifulSoup)
sqlite(sqlite3)
画像処理(PIL)
```
Androidエミュレーターのhostsを書換えてローカルサーバーへ接続する

# 前置き
小ネタになります:pushpin:
macOSにローカルサーバー立ててiOSシミュレーターとAndroidエミュレーターからアクセスする開発環境を構築しています。iOSシミュレーターはmacOSのhostsを認識しているようでしたが、Andoridエミュレーターでは別途hostsを設定する必要がありました。開発環境はmacOSを想定しています。

# adb/emulatorのパスを通す
必須ではありませんがコンソールの可読性も上がりますのでパスを通しておきます。

1. .bash_profileを編集

    ```bash
$ vi ~/.bash_profile
```
1. パスを追加
AndroidStudio一式をデフォルトでインストールした場合、以下のパスになっていると思います。

    ```bash:.bash_profile
export PATH="$PATH:$HOME/Library/Android/sdk/platform-tools"
export PATH="$PATH:$HOME/Library/Android/sdk/emulator"
```
1. 再読込み

    ```bash
$ source ~/.bash_profile
```

# エミュレーターを設定する
1. 対象エミュレーターを選定

    ```bash
$ emulator -list-avds
Pixel_2_API_28
```
1. 書込み可能状態でエミュレーターを起動

    ```bash
$ emulator -avd Pixel_2_API_28 -writable-system
emulator: WARNING: System image is writable
emulator: INFO: boot completed
```
1. rootを取得
前述の「書込み可能状態でエミュレーターを起動」を行うとコマンドの結果がフォアグラウンドになるので、以降のコマンドはもう1つコンソールを立ち上げて実行します。(バックグランド実行でも良いですね。)

    ```bash
$ adb root
restarting adbd as root
```
1. /systemを書込み可能にして再マウント

    ```bash
$ adb remount
remount succeeded
```
1. hostsに書込む
AndroidシミュレーターからmacOSのローカルホストへ接続するにはIPアドレスに```10.0.2.2```を指定します。```127.0.0.1```ではありません。ご注意ください:construction:

    ```bash
$ adb shell "echo 10.0.2.2 devnokiyo.example.com >> /system/etc/hosts"
```
なお、上記の例では追記しか出来ないので、一度AndroidエミュレーターのhostsファイルをmacOSで編集してから、Androidエミュレーターへ配置する方法も有用だと思います。
    1. Androidシミュレーターのhostsを取得  

        ```bash
$ adb pull /system/etc/hosts .
```
    1. hostsを編集  
    1. hostsをAndroidシミュレーターへ配置  

        ```
$ adb push .hosts /system/etc/hosts
```  
  
    
    この時点でChromeを起動または再起動すると反映されていることが確認できます:clap::clap::clap:
![０２.png](https://qiita-image-store.s3.amazonaws.com/0/240974/af5a03c8-977a-73f2-d8b9-b1c1c6948c37.png)
1. 非rootに変更

    ```bash
$ adb unroot
restarting adbd as non root
```
1. 再起動

    ```bash
$ adb reboot
```

# トラブルシューティング
API28の他、API27でも試してみましたが、筆者の環境では不安定になることがあります。
「書込み可能状態でエミュレーターを起動」を行うとコマンドの結果が、途中から以下のように表示される続けることがあります。

```bash
WARNING: AsyncSocketServer.cpp:99: Error when accepting host connectionError message: Bad file descriptor
    :
    :
```

完全な解決策がわかっていないのですが、AndroidStudioやAndroidエミュレーターを再起動すると解決します。「解決」というより仕切り直しの意味合いが多いですね。

# 参考
[Android Emulatorのhostsを書き換える方法](https://qiita.com/kgmyshin/items/9964b9cc2193d1cae985)
[Android端末のhostsを書き換える方法](https://qiita.com/konifar/items/77744cf8179657adcc3e)
[Androidのエミュレーターから自身のPC(localhost)へ接続](https://araramistudio.jimdo.com/2018/01/11/android%E3%81%AE%E3%82%A8%E3%83%9F%E3%83%A5%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC%E3%81%8B%E3%82%89%E8%87%AA%E8%BA%AB%E3%81%AEpc-localhost-%E3%81%B8%E6%8E%A5%E7%B6%9A)

# 終わりに
筆者はiOS、Androidの順で開発を進めており先入観が2つありました。

* AndroidエミュレーターにもmacOSのhostsが適用されているはず  
→ されてませんでした。
* hostsにローカルIP(ループバック)```127.0.0.1```を追加する  
→ ```10.0.0.22```でした。

ご参考になれば幸いです。
Ubuntu 18.04.2でxrdp(のXorgモード)が使えないので一時的に凌ぐ

おそらくすでにたくさんある情報のn番煎じなんですが､Ubuntu18.04.2に関する情報がかなり少なかったので､同じような人がいたとき用に書いておきます｡
(ちなみに試した環境はXubuntuですが､コマンド的にどのフレーバーでも動きそうな気がします)

## xrdpがUbuntu18.04.2で使えないらしい
https://note.spage.jp/archives/576
https://ubuntuforums.org/showthread.php?t=2413157
ここの情報のおかげでわかったのですが､どうも18.04.2ではxrdpのXorgモードを使う際に必要なxorgxrdpが対応していない?らしく､(少なくとも簡単には)動かないようです｡

無理に弄って壊しても嫌ですし､いつか対応することを前提に､xorg経由ではなく、X11VNC経由でXRDPを使うことで凌ぎます｡

## 1. x11vncをインストールする
本来であればsudo apt install xrdpと少しの操作で使えるようになるはずのxrdpがXorgモードで使えないということなので､できるだけ手間を省いていきます｡
(xrdpは入ってる前提)

```shell

sudo apt install x11vnc
x11vnc -storepasswd #パスワードを設定します
sudo nano /etc/xrdp/xrdp.ini
```

## 2. xrdpの設定を変える
xrdpの設定ファイルで､Xvncに関する設定を少し変更します

```ini:/etc/xrdp/xrdp.ini
[Xvnc]
name=Xvnc
lib=libvnc.so
username=ask
password=ask
ip=localhost 
# ↑ここを一応127.0.0.1からlocalhostに変えておく
port=5900 
# ↑-1を5900に
```

これで設定は終わりです｡

## 3. X11VNCを起動して、RDPクライアント経由でつなぐ
あとは

```
x11vnc -localhost -forever -bg -display :0
```

を叩いておけば､

* localhostのみに(-localhost)､
* ずっと(-forever)､ 
* バックグラウンドで(-bg)

開くVNCサーバーが立ち上がります｡

あとは、先程の設定のおかげでXRDPがVNC経由でつないでくれますので、お好きなRDPクライアントで接続しましょう。

VPSみたいに生VNCが危なくて使えないときには､xrdpを経由することでちょっと安全な認証が使えますので､そういうときにいいですね｡
xorgxrdpがちゃんと対応しない間はこれで凌ごうと思います｡

(2020/02/03編集: XRDPの代わりにVNCで繋げばいいじゃんみたいな表現に見えた気がするのですこし修正しました)