OmniAICreator/Qiita-1.07M huggingface dataset:
〜誰ワカ〜　MVC　ルーティング・コントローラー・ビューの基本関係（ついでにモデル）

# 「MVC」 （コントローラー、ビュー　＋　モデル）の関係・流れの基本（基礎編）

## Ruby on Railsにおいて、画面を表示させるまでに知っておくべきこと（２）

こんにちは。　〜誰ワカ〜　Ruby on Rails攻略　のコムリンです。

このページでは、Ruby on Rails攻略において必須だけど必須じゃない！？***「MVC」***についてです。

***「MVC」***は、Ruby on Railsの基礎、基本的な概念です。が、
でも、知っていて損はありませんが、**知らなくても問題ない**かと思います。

（学習しているうちにいつの間にか分かるので）

初学者にはなかなか飲み込む事が難しいと思うし、実際に手を動かさないと**イメージ**が湧かないからです。

なので、**とりあえず**的な感じで**さらっと**行きましょう！



**MVC**とは、
「モデル」「ビュー」「コントローラー」の略。

***モデル（Model)***　はデータを管理するところ。
***ビュー（View)***　は表示画面を管理するところ。
***コントローラー（Controller)***　はモデルとビューを繋げたり処理したりするところ。

です！！

こういう関係があるから、複雑な処理が必要なアプリやサイトがうまく動くのです！！！
それをわざわざ***「MVC」***なんていうかっこいい名前をつけるから・・・なんか難しく感じちゃいません！？w
なんかすごいシステムの仕組みかと思ってましたが、よくよく考えたらしごく単純明快な概念でした。

難しい説明がないことが売りの〜誰ワカ〜なので、めちゃめちゃ簡単なイメージでお伝えしました。


↓Ruby on Rails　の基本的な流れ↓
https://qiita.com/comlin_memo/items/617a6e5bbe96b55c57cf
Ubuntu 19.10にDockerをインストールする


**2020/03現在Dockerから公式リポジトリが提供されたため、こちらの導入方法は必要なくなりました**
最新の導入方法は[こちら](https://docs.docker.com/install/linux/docker-ce/ubuntu/)


### 以前この記事の方法で、古いパッケージを導入した方
```sh
sudo vi /etc/apt/sources.list
```
`deb [arch=amd64] https://download.docker.com/linux/ubuntu disco stable`
行を削除します。


~~## 公式パッケージが提供されていない問題~~
~~現在(2019/10/21)Ubuntu 19.10環境向けにDockerのパッケージが配布されていません。~~
~~その為、[公式のインストール手順](https://docs.docker.com/install/linux/docker-ce/ubuntu/)に従ってもインストールが出ません。~~

~~## 解決策~~
~~Ubuntu 19.04向けのパッケージをリポジトリに追加して、インストールします。~~

```sh

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   disco \
   stable"
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
```



## 参考サイト
https://github.com/docker/for-linux/issues/833
realineのエラー

### 要約
- railsプロジェクトで`rails s`のときにreadlineのエラーが出た
- `image not found`エラー
- rbenv使っている
- readlineのバージョンが上がったのが原因
- rbenvからビルドしなおせば直った

### エラー
```shell
/nishizaki/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin18/readline.bundle, 9): Library not loaded: /usr/local/opt/readline/lib/libreadline.7.dylib (LoadError)
  Referenced from: /Users/nishizaki/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin18/readline.bundle
  Reason: image not found - /Users/nishizaki/.rbenv/versions/2.5.5/lib/ruby/2.5.0/x86_64-darwin18/readline.bundle
```

### 背景
rbenvでrubyの2.6.4をインストールした後に、2.5.5に戻したらエラー

rbenvを最新バージョンリストに更新するために

    brew update && brew upgrade ruby-build


readlineが8にアップデート→
readline7がロードされなくなる→
readline7でビルドしていたrbenvの中のrubyがエラーになる

みたい。

こうやってビルドし直せば復活した

    RUBY_CONFIGURE_OPTS=--with-readline-dir=`brew --prefix readline` rbenv install 2.5.5

https://github.com/guard/guard/wiki/Add-Readline-support-to-Ruby-on-Mac-OS-X#option-4-build-ruby-with-gnu-readline-using-rbenv-ruby_build-and-homebrew
AppiumでAndroid端末にインストールされたあらゆるアプリの操作を自動化してみよう

Appiumで端末にインストールされたアプリの操作を自動化しクローリングしたいと思います。

AppiumはSeleniumのようなAPIでアプリの操作をできるツールです。

端末に入っているapkをpullしてAppiumで操作するのでどんなアプリでも操作ができます。

# Appiumをインストール
Appium公式サイトからアプリをダウンロードします。
http://appium.io/


#端末に接続する方法

下記からは端末に接続する方法を書いていきます。
下記に公式のドキュメントがありますので、うまくいかない場合はチェックしてみてください。
https://github.com/appium/appium/blob/master/docs/en/writing-running-appium/caps.md

下記の項目を取得することでAppiumのSessionを開始することができます。

```
appPackage
appActivity
platformVersion
deviceName
app(任意)
```

## Packageの取得

その後、PCにスマートフォンをつなぎ(自分の場合はAndroidです)、下記のコマンドを実行

```
adb shell pm list packages
```

パッケージ一覧を取得できますので、そこから操作したいアプリのパッケージ名をメモしておきます。(`package:` は不要)


## Launch Activityの取得

操作したいアプリを立ち上げ、下記のコマンドを実行することでLaunch Activityを取得することができます。

```
adb shell dumpsys window windows | grep -E "mCurrentFocus"
```

メモしておいてください。

## deviceNameの取得

```
adb shell getprop ro.product.model
```

これもメモしておきます。

## platformVersionの取得

```
adb shell getprop ro.build.version.release 
```

これもメモ

## appの取得(任意)

ここではapkファイルを端末からpullして、PCのapkへのパスを取得します。

まず、端末内のアプリのパスを取得します。

```
adb shell pm list packages -f | grep com.hoge
```

その後、上記で取得できたパスを使ってapkファイルをダウンロードします

```
adb pull /data/app/com.hoge-2NCYKBV5gI-ISQMHfmhcoA==/base.apk
```

ダウンロードしたapkのPCでのパスをメモしておいてください。


## これまでにメモしておいた内容で下記のJSONを作成します。

```
{
  "automationName": "Appium",
  "platformName": "Android",
  "appPackage": "上記で取得した値",
  "appActivity": "上記で取得した値",
  "platformVersion": "上記で取得した値",
  "deviceName": "上記で取得した値",
  "app": "上記で取得した値(任意)"
}
```

---

# JSONを読み込ませてアプリを起動

![https___qiita-image-store.s3.amazonaws.com_0_6817_8ca40d0d-b427-6ae4-778d-f1e4cbdca5dd.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204698/d7faf039-af97-1cda-a7d3-5ee7c817692c.jpeg)

JSON Representationの部分に上記で作成したJSONを設定してStart Session をすることで
端末からpullしたapkを端末に送り込み、インスペクタが起動します。

![Appium-inspector.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/204698/183f4305-a9d8-be4e-b0f2-e2bee5160452.png)

上記のインスペクタを使えばxpathが取得できるので、あとはそれをつかってseleniumを書くようにスクリプトを書いたり、レコーディングの機能を使って端末の操作をコード化することができます。

コードは自分はWebdriver.ioで記述しますが、Ruby,Java,PythonなどでもOKです。
ここはSeleniumの話になってしまうので割愛します。
JavaScriptのステートメントとは



## ステートメントについて

1つの命令の事を**ステートメント**と呼ぶ
（例）
alert("ようこそJavaScriptの世界へ");

alert:ダイアログに表示するタグ
"ようこそ～":ダイアログ内に表示される
「;」:ステートメントの終わりにつける。

- コメントアウト
 - // コメントアウトしたい文
 - /* コメントアウトしたい文 */


- メソッドの呼び方
 - 「オブジェクト名.メソッド名(引数);」
 - 引数が複数ある場合は「,」で区切って指定する。  

- プロパティを記述するときも「オブジェクト名.プロパティ名」
- プロパティに値を設定する時
 - (ex) document.bgColor = "yellow";

- **しかし** document.[bgColor] = "yellow";でも接続可能。好きな方でOK


#### ※ プロパティ名の大文字小文字は区別されているから正確に記述する。
初心者のpythonメモ：演算子

#はじめに
**本メモはPythonの演算子メモです。**

#Pythonの主な演算子
Pythonで数式を入力すると計算をしてくれます

| 演算子       |効果 |例 |
|:-----------------|:------------------|:------------------|
| +            |足し算|1+2=3|
| -            |引き算|5-1=4|
| *            |掛け算|2*3=6|
| /           |割り算|10/2=5.0|
| **            |累算|2**3=8|
| %             |剰余（割り算の余り）|10%3=1|
| //           |割り算結果を小数点以下無視して整数を返す|5//2=2|

#比較演算子と代入演算子
数字の大小を比較する際は、比較演算子を用います。

| 演算子       |数学記号 |例 |
|:-----------------|:------------------|:------------------|
| <            |<|4<2 False|
| >            |>|5>1 True|
| <=            |≦|1<=0 False|
| >=           |≧|3>=3 True|
| !=            |≠|3!=4 True|
| ==             |=|2==3 False|

また、等号(=)は代入演算子、複合代入演算子としても用います。

| 演算子       |説明 |例 |
|:-----------------|:------------------|:------------------|
| =            |=の左辺の変数に右辺のデータを代入|x=3 xに3を代入|
| +=            |+=の左辺の変数に両辺のデータを代入|x+=5 xにx+5を代入|
Mac環境でopenssl@1.1があると古いRubyのインストールに失敗する

OSSのサンプルプログラムを確認するために、古い Ruby をインストールしようとしてハマりました。

## 発生したこと

macOS Catalina (10.15) で Ruby 2.3.1 をインストールしようとしたところ、以下のようなエラーが発生しました。

```
The Ruby openssl extension was not compiled.
ERROR: Ruby install aborted due to missing extensions
Configure options used:
  --prefix=/Users/username/.rbenv/versions/2.3.1
  --with-openssl-dir=/usr/local/opt/openssl@1.1
  --with-readline-dir=/usr/local/opt/readline
  CC=clang
  LDFLAGS=-L/Users/username/.rbenv/versions/2.3.1/lib
  CPPFLAGS=-I/Users/username/.rbenv/versions/2.3.1/include
```

## 解決方法

以下のように環境変数で openssl@1.1 ではなく openssl のディレクトリを指定するとインストールに成功しました。

```
RUBY_CONFIGURE_OPTS="--with-openssl-dir=/usr/local/opt/openssl" rbenv install 2.3.1
```

通常はより新しいバージョンを使用するべきなので、あくまで検証時などローカルで動作させたい場合の迂回策としての解決方法です。
そもそも、Ruby 2.3 はサポートが終了しているので本番環境等で使用するべきではないです。

## 参考

https://github.com/rbenv/ruby-build/issues/1353
ruby-build の issues に上がっていました。
2.4 よりも古い ruby は、openssl@1.1 がインストールされた環境ではビルドに失敗するようです。
Selenium+Pythonでブラウザの自動操作

## Selenium とは？
ブラウザの操作を自動化するツールです。

https://docs.seleniumhq.org/
OS・ブラウザごとのWebDriverと合わせて使用します。

## 実行環境
オフィス用のPC上で実行することを想定して、今回はWindowsを使用します。
Windows10 Pro 1903

## Python3の準備(Anaconda)
Pythonでも良いんですが、今回はAnacondaをインストールします。

https://www.anaconda.com/distribution/
Python 3.7 version をダウンロードしてインストール。

Anaconda Promptを開いて、パッケージをインストールします。

    conda install beautifulsoup4
    conda install selenium

## WebDriverの配置
https://sites.google.com/a/chromium.org/chromedriver/downloads
Current ReleasesからChromeに対応したものをダウンロードし、パスが通るところ（環境変数Pathで設定された場所）に起きます。

## Seleniumの動作の流れ
Seleniumの基本的な流れは以下です。
- Chromeを開く
- ページ内の要素を見つける
- 要素を操作する

今回は例として、Chromeでブラウザを操作して、Googleで猫画像を検索し、その画像が掲載されたHTMLファイルを作成して開きます。

## 今回のコード
``` python:
import time 
import re
import csv
from selenium import webdriver
from bs4 import BeautifulSoup
import os

# get current path
path = os.getcwd()

# open chrome
driver = webdriver.Chrome()
driver.get('https://www.google.com')

time.sleep(1)

# input search form 
neko = driver.find_element_by_name("q")
neko.send_keys("猫");
neko.submit();

time.sleep(1)

# move image search page
nekoimg = driver.find_element_by_xpath('//*[@id="hdtb-msb-vis"]/div[2]/a')
nekoimg.click()

time.sleep(1)

# get page source
html = driver.page_source
bs = BeautifulSoup(html, "html.parser")

# select neko image 
rows = bs.findAll("img",src=re.compile("data:image/jpeg"))

with open("neko.html", "w", encoding='utf-8') as file:
# write html header
    file.write('<!DOCTYPE html>\n')
    file.write('<html>\n')
    file.write('<body>\n')

# write html body 
    for row in rows:
        if row.get("src") != None:
            str = '<img src=\"' + row.get("src") + '">\n'
            file.write(str)
# write html footer
    file.write('</body>\n')
    file.write('</html>\n')

# close browser
driver.get('file:///' + path + '/neko.html')
```

## 解説
まずはwebdriver.Chrome()でサイトを開き、driver.getでサイトを開きます。

```
  driver = webdriver.Chrome()
  driver.get('https://www.google.com')
```

Googleのサイトの検索ボックスに「猫」を入れて検索します。driver.find_element_by_nameで要素（今回だと検索ボックスのnameの値であるq）を指定します。

send_keysでフォームに文字列を入力し、submitで検索します。

```
neko = driver.find_element_by_name("q")
neko.send_keys("猫");
neko.submit();
```

検索画面が開いたら「画像」をクリックします。要素はxpathで指定します。

```
nekoimg = driver.find_element_by_xpath('//*[@id="hdtb-msb-vis"]/div[2]/a')
nekoimg.click()
```

driver.page_sourceでソースコードを取得し、BeautifulSoupでパースします。

```
html = driver.page_source
bs = BeautifulSoup(html, "html.parser")
```

findAllでimgタグのうち、data:image/jpegを含む文字列を検索します。

```
rows = bs.findAll("img",src=re.compile("data:image/jpeg"))
```

取得したimgタグをそのまま貼り付けます。

```
for row in rows:
    if row.get("src") != None:
         str = '<img src=\"' + row.get("src") + '">\n'
         file.write(str)
```

作成したファイルを開きます。

```
driver.get('file:///' + path + '/neko.html')
```
今更聞けないモンテカルロ法(円周率編)

カジノを潰したという都市伝説を持つモンテカルロ法で、円周率を求めます。
C#ですけれど、ソースコードはこちらにあります。
https://github.com/ma3100/AlgorithmPrimer/blob/master/FirstAlgorithmForCSharp/First/MonteCalro.cs
※随時追加予定

# モンテカルロ法とは?

モンテカルロ法は、問題を数値計算で解くのではなく確率を利用して解く事です。

例えば今回テーマにしている円周率の場合、**「円周の長さと直径の比」**から一生懸命計算する訳ですが、モンテカルロ法は上記の計算を必要としません。

そのため、今回学ぶ方法で求める円周率は正確な値ではないのですが、導入としては適しているのでその辺りは割り切ってください。

# モンテカルロ法で円周率を求める際の考え方

※半径が1の円で説明します。

1. 円周率を求めたい円を四分割し、直径と同じ辺を持つ**正方形**で1/4の円を囲みます。
2. 1で出来た範囲の中に一様実数乱数を発生させます。3つしか点を打っていませんが、以下の様な状態になります。
<img width="149" alt="スクリーンショット 2019-10-21 14.03.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36448/20bb4250-f4d9-bf5b-32a0-cd1c8d3abdbc.png">

3. 一様実数乱数であれば、「1/4の円の中に収まる乱数と全ての乱数」の比は、「1/4の円の面積と正方形の面積の比」と同じになります。

1/4の円の面積 : 正方形の面積 = 1/4の円の中に収まる乱数の数 : 全ての乱数の数
1/4の円の中に収まる乱数の数をa,円の外に出た乱数をbと置くと、
円周率/4 : 1 = a : a + b
円周率 = 4a / (a + b)
      = 4a / n(発生した乱数の総数)

# 実装(C#)

```csharp:pymonte.cs
        const int RANDOMNUM = 10000;

        void GetMonteCalro()
        {
            double x, y, montePai;
            var random = new Random();
            var inCircle = 0;
            foreach(var i in Enumerable.Range(0,RANDOMNUM))
            {
                x = random.NextDouble();
                y = random.NextDouble();

                if(x * x + y * y <= 1)
                {
                    inCircle++;
                }
            }

            montePai = (double)4 * inCircle / RANDOMNUM;
            Console.WriteLine($"Answer:{montePai}");
        }
```
※x^2 + y ^2 が半径を超えないのであれば、円の中にあると見なせます。

例えばRANDOMNUMの値を100などにすると、かなり怪しい結果になるのですがこの値を大きくしていくと、だんだんと3.14に近しい数になっていきます。

今回は以上です、次はモンテカルロ法を用いて円の面積を求めていきます。
Serverless FrameworkでTypeScriptを使い、Lambda Layersを使う方法

## serverless framework自体をインストールする

```bash
npm install -g serverless
```

## プロジェクトを作成する

```bash
serverless create --template aws-nodejs-typescript --path my-service
```

## プラグインインストール

```bash
serverless plugin install -n serverless-webpack
```

```
npm install
```

## デプロイ

```bash
serverless deploy --aws-profile sandbox -v
```

デプロイされると、 `endpoints` にURLが表示されています。

そのURLにcurlでアクセスしてみます。

```
curl https://hsnfe8svli.execute-api.us-east-1.amazonaws.com/dev/hello | jq
```

実行すると下記の結果が得られます。(抜粋)

```json
{
  "message": "Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!"
}
```


## 実行してみる

```bash
serverless invoke -f hello -l --aws-profile sandbox
```

### 出力

```
{
    "statusCode": 200,
    "body": "{\n  \"message\": \"Go Serverless Webpack (Typescript) v1.0! Your function executed successfully!\",\n  \"input\": {}\n}"
}
--------------------------------------------------------------------
START RequestId: d2d32d7e-7c23-448d-ac57-45133fcf6422 Version: $LATEST
END RequestId: d2d32d7e-7c23-448d-ac57-45133fcf6422
REPORT RequestId: d2d32d7e-7c23-448d-ac57-45133fcf6422	Duration: 2.07 ms	Billed Duration: 100 ms	Memory Size: 1024 MB	Max Memory Used: 76 MB
```


## Layersプラグインを使う

```
npx sls plugin install --name serverless-layers
```

### S3 Bucketを指定する

```bash
serverless info -v
```

で表示される、`ServerlessDeploymentBucketName` を、`serverless.yaml`のcustomセクションに追加

```yaml
custom:
  serverless-layers:
    layersDeploymentBucket: 'ここにServerlessDeploymentBucketNameの値を入れる'
```

(いちいちこの方法を使わないでも直接参照したい…。だれか知っている人がいたら教えてください)
Mint Linux (Mate/Xfce) に xrdpを利用してremote desktop接続する〜SynologyNas Virtual Machine Manager

# 前に
　　最近Synology NasのVirtual Machine ManagerにMint Linux(Xfce)をインストールしました、そしてxrdpを利用してリモートディスクトップ接続したかったです。
　　でも、何日間ちょこちょこやってみたけど、なかなうまくできませんでした。最初はXfce環境の問題だと思いましたが、Mint Linux(Mate)をインストールしました。でもやはりXfce環境の問題ではないので、Mateでもできませんでした。
　　諦めるかなと思った時に、偶然ある二つ案をやってみたらできるようになりますた。他の人は時間を無駄に使わないためにこの記事が書こうと思っています。では、解決の手順です。

# 手順

### 1, `xrdp`をインストールする

    sudo apt install xrdp

### 2, `xorgxrdp`をインストールする

    sudo apt install xorgxrdp

*ここは重要なんです、`xorgxrdp`をインストールしないとGreen empty desktopとなります。僕の場合ここは一番時間がかかりました。*

### 3, `/etc/xrdp/xrdp.ini`を修正する

    new_cursors=true を　new_cursors=false　に変更

### 4, `/etc/xrdp/startwm.sh`を修正する

Mateの場合は

    exec mate-session (これを挿入)

    test -x /etc/X11/Xsession && exec /etc/X11/Xsession (これは元の行)
    exec /bin/sh /etc/X11/Xsession (これは元の行)

Xfceの場合は

    exec xfce4-session (これを挿入)

    test -x /etc/X11/Xsession && exec /etc/X11/Xsession (これは元の行)
    exec /bin/sh /etc/X11/Xsession (これは元の行)

*ここも重要です、挿入しなかったらMateの場合はBlack empty desktopとなります。Xfceの場合は接続切ります。*

### 5, `/etc/xrdp/startwm.sh`をもう一行追加する

    unset DBUS_SESSION_BUS_ADDRESS(これをここに挿入、下はだめ)
    exec mate-session (先ほど挿入した行)

    test -x /etc/X11/Xsession && exec /etc/X11/Xsession (これは元の行)
    exec /bin/sh /etc/X11/Xsession (これは元の行)

*`unset`の行を挿入しないと、Mateの場合は`「Could not acquire name on session bus」`と表示します。Xfceの場合は接続切ります。*

### 6, `xrdp`を再起動する

    sudo service xrdp restart


ここまではリモートディスクトップで接続できるはずです。　Good Luck！

また、もう一つ重要なものがあります。Windowsリモートディスクトップから接続する時、
<font color=red>**Sessionは「Xorg」を選択してくださくい**</font>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/236892/767bc211-de92-cc77-9232-b0bc1eaae260.png)

# 最後に
　　
　　Mateの場合はリモートディスクトップのレイアウトと直接Mintにログインのディスクトップのレイアウトは同じです、でもXfceの場合はディスクトップのレイアウトは完全に違います、原因はまだわかりません。
もしXfceも同じなディスクトップのレイアウトを設定できれば、ぜひ教えてくださいね＾＾

<font color=gray>*参照した記事：*</font>
１、http://verifiedby.me/adiary/0126
２、https://askubuntu.com/a/1124344
AlpineとCentOSでhttp proxy通過してSSHする(ncのオプションが違う話)

SSHでProxyを経由するときの話。
CentOSでできるのにAlpine（コンテナ）でできなくてしばらくはまったのでメモ
`nc -h`で見るとわかるがオプションが違う

# CentOSの場合

```
yum install nc nmap
ssh -o 'ProxyCommand=nc --proxy-type http --proxy <proxy.server:8080> %h %p' <user>@<host>
```

# Alpineの場合

```
apk add --update --no-cache netcat-openbsd openssh-client
ssh -o 'ProxyCommand=nc -X connect -x <proxy.server:8080> %h %p' <user>@<host>
```

以上。
android adb

[原文](https://www.jianshu.com/p/e5c055f4171f)

### ADB是什么

ADB，即 [Android Debug Bridge](https://developer.android.com/studio/command-line/adb.html) 是一种允许模拟器或已连接的 Android 设备进行通信的命令行工具，它可为各种设备操作提供便利，如安装和调试应用，并提供对 `Unix shell`（可用来在模拟器或连接的设备上运行各种命令）的访问。可以在`Android SDK/platform-tools`中找到 `adb` 工具或下载 [ADB Kits]( http://adbshell.com/downloads) 。

### 查看adb的版本信息

`adb version`

### 显示设备列表

```
adb devices

List of devices attached
LK7N18125001132	device
```

### 关闭usb调试

`adb shell settings put global adb_enabled 0`

### 打开usb调试

`adb shell settings put global adb_enabled 1`

### 查询usb调试开关情况

`adb shell settings get global adb_enabled`

### 打开模拟定位

`adb shell settings put secure  mock_location 1 `

### 打开坐标

`adb shell settings put system pointer_location 1 `

### 模拟home按键

`adb shell input keyevent 3`

### 模拟按下 Power 键

`adb shell input keyevent 26`

### 模拟 touch屏幕事件

点击屏幕(x, y) = (350, 350)位置

`adb shell input tap 350 350`

### 模拟滑动的事件

从屏幕(150, 150) 滑到屏幕(300, 300)

`adb shell input swipe 150 150 300 300`

### 输入文字

`adb shell input text 123`

### 查看 WiFi IP 地址

```
adb shell ip -f inet addr show wlan0

<BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 3000
    inet 192.168.0.100/24 brd 192.168.0.255 scope global wlan0
       valid_lft forever preferred_lft forever

```

### 开启adb服务

默认启动 `5037` 端口

```
adb start-server

netstat -na | grep 5037

tcp4       0      0  127.0.0.1.5037         127.0.0.1.65208        ESTABLISHED
tcp4       0      0  127.0.0.1.65208        127.0.0.1.5037         ESTABLISHED
tcp4       0      0  127.0.0.1.5037         127.0.0.1.65206        ESTABLISHED
tcp4       0      0  127.0.0.1.65206        127.0.0.1.5037         ESTABLISHED
tcp4       0      0  127.0.0.1.5037         127.0.0.1.65204        ESTABLISHED
tcp4       0      0  127.0.0.1.65204        127.0.0.1.5037         ESTABLISHED
tcp4       0      0  127.0.0.1.5037         127.0.0.1.65202        ESTABLISHED
tcp4       0      0  127.0.0.1.65202        127.0.0.1.5037         ESTABLISHED
tcp4       0      0  127.0.0.1.5037         *.*                    LISTEN
```

### 查看系统应用

`adb shell pm list packages -s`

### 查看第三方应用

`adb shell pm list packages -3`

### 查看应用安装路径

`adb shell pm path <package-name>`


###  通过 TCP 连接设备

```shell
adb tcpip 5555
adb connect 192.168.1.3:5555

adb devices
```

### 关闭 adb服务

```
adb kill-server
```

---

参考：

https://juejin.im/post/5b5683bcf265da0f9b4dea96

https://developer.android.com/studio/command-line/adb?hl=zh-Cn

https://cwgoover.github.io/2016/05/31/android-setting-pointer-location/

https://android.stackexchange.com/a/114081

https://segmentfault.com/a/1190000015345637

https://github.com/esauvisky/PGo-CalcaBotaBotaCalca
GKEでclusterrolebindingするにはCloud IAMで権限の付与が必要

GKEのクラスタにArgoをセットアップしようしたらハマったのでメモ

# 起きたこと
Argo Getting Started > 2. Install the Controller and UI

下記のapplyを実行するとRequired "container.roles.create" permission.が発生

```
kubectl apply -n argo -f https://raw.githubusercontent.com/argoproj/argo/stable/manifests/install.yaml
```

エラー内容
```
Error from server (Forbidden): error when creating "https://raw.githubusercontent.com/argoproj/argo/stable/manifests/install.yaml": roles.rbac.authorization.k8s.io is forbidden: User "hoge＠hoge.com" cannot create resource "roles" in API group "rbac.authorization.k8s.io" in the namespace "argo": Required "container.roles.create" permission.
Error from server (Forbidden): error when creating "https://raw.githubusercontent.com/argoproj/argo/stable/manifests/install.yaml": clusterroles.rbac.authorization.k8s.io is forbidden: User "hoge＠hoge.com" cannot create resource "clusterroles" in API group "rbac.authorization.k8s.io" at the cluster scope: Required "container.clusterRoles.create" permission.
Error from server (Forbidden): error when creating "https://raw.githubusercontent.com/argoproj/argo/stable/manifests/install.yaml": clusterroles.rbac.authorization.k8
```

# 対処方法
gcloudのcloud IAMで対象のアカウントにcluster-adminの権限を与えればおｋ

```
gcloud projects add-iam-policy-binding $PROJECT \
  --member=user:person@company.com \
  --role=roles/container.admin
```

## 備忘録
Argoのドキュメントに
>NOTE: On GKE, you may need to grant your account the ability to create new clusterroles

```
kubectl create clusterrolebinding YOURNAME-cluster-admin-binding --clusterrole=cluster-admin --user=YOUREMAIL@gmail.com
```
って書いてあるがこちらも権限が足りないため失敗して辛かった....

## 参考
https://stackoverflow.com/questions/46307325/gke-clusterrolebinding-for-cluster-admin-fails-with-permission-error
libxml-ruby 3.1.0 install on macOS 10.15 Catalina

`xml2` を `homebrew` などからインストールせずに、macOS 10.15 でOSのライブラリ(Xcode)を使って`libxml-ruby` gem をインストール

## gem install

```console
% gem install libxml-ruby -v '3.1.0' -- \
--with-xml2-dir=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr \
--with-xml2-lib=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib \
--with-xml2-include=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2
```

## bundle install

bundler を使う場合は `--with-xml2-include` だけでないとダメだった

```
% bundle config build.libxml-ruby --with-xml2-include=/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2
% bundle
```

---

libxml2 の場所は `xml2-config --cflags` で参照できる。
GCCなど用に `-I` フラグがついてしまうので、そのままでは使えないので今回は上記のようにベタがきにした。

```console
% xml2-config --cflags
-I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/include/libxml2
% xml2-config --libs
-L/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/usr/lib -lxml2 -lz -lpthread -licucore -lm
```

**参考**

* [Cannot install v 3\.0\.0 OSX Sierra · Issue \#140 · xml4r/libxml\-ruby](https://github.com/xml4r/libxml-ruby/issues/140)
* [macOS Catalina\(10\.15\) \+ Xcode11 だと /usr/include が無い \- Qiita](https://qiita.com/yoya/items/c0b26cba3c040c581643)
* [macOS Mojave で libxml\-ruby のインストールに失敗するときは Command Line Tools for Xcode を入れてみる \- Qiita](https://qiita.com/asahiko/items/e5d23fe34025a20804c1)
続・半自動モフり機

# † 前回の続きというか動機
先ごろ、[モーターで上下運動する機構](https://qiita.com/Amb98/items/aef47f143727d524d4f6)を作成した。

これを作成した目的のアレが終わってまもなく、同機構をより洗練された形に実現した投稿を見つけた。
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">思いついたものはすぐ作らないとムズムズする病にかかってるので結局8ピンマイコン使ってきれいに単三乾電池サイズに収める形で作りました。昨日の動画で一体化してるのはオスメス端子で無理やり２つの基板くっつけてる疑似的な一枚基板したがこれは本当に一枚の基板です。　<a href="https://twitter.com/hashtag/FGO?src=hash&amp;ref_src=twsrc%5Etfw">#FGO</a> <a href="https://twitter.com/hashtag/%E8%87%AA%E5%8B%95%E3%83%9C%E3%83%83%E3%82%AF%E3%82%B9%E9%96%8B%E3%81%91%E6%A9%9F?src=hash&amp;ref_src=twsrc%5Etfw">#自動ボックス開け機</a> <a href="https://t.co/qRbG4ybU2M">pic.twitter.com/qRbG4ybU2M</a></p>&mdash; TAKUTEKS_新作触手CG集DLsite＆FANZAにて販売中 (@takuteks) <a href="https://twitter.com/takuteks/status/1183725206579269632?ref_src=twsrc%5Etfw">October 14, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

[リレー式の装置](https://www.switch-science.com/catalog/2455/)が販売されていることは知っていたが、タッチパネルの様式によっては使用不可ということでスルーしていた。当方所有のスマホはXperia Z5 Compact、四年前の製品である。期待はできない。
しかし、自作できるなら。製品よりも若干安く上がることだしと、やってみることにした。
<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/6xmudx3BY3">pic.twitter.com/6xmudx3BY3</a></p>&mdash; ちゃり (@amb98) <a href="https://twitter.com/amb98/status/1186131714839441409?ref_src=twsrc%5Etfw">October 21, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

# † 実装
![半自動モフり機リレー版_ブレッドボード.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/167384/a96e7fa5-3726-9967-67da-c1fdda0c4b2a.png)
実物はハンダ付けがあまりにアレなのでお見せできない。

```c
#define PIN_IN8  8

void setup(){
  Serial.begin(9600);
  pinMode(PIN_IN8,OUTPUT); 
}
 
void loop(){
    Serial.print("PIN8 ON\n");
    digitalWrite(PIN_IN8,HIGH);
    delay(500);
  
    Serial.print("PIN8 OFF\n");
    digitalWrite(PIN_IN8,LOW);
    delay(1500);
}
```
元ネタ氏からご教授いただいた知見は以下の通り。
1.リレーからスマホ画面への線はなるべく短くする
2.GNDは長めにとる
3.スマホ画面に接する部位は天辺が平らな画鋲がよい
4.画鋲はスマホ画面に密着する必要があり、両面テープなどを用いる

なお、リレーはG5V-1 3VDCを使用した。リレー初挑戦であり、なにを使用したらよいのかわからなかったゆえの選択である。
ちなみに、本品はブレッドボード中央の溝をまたげないので、ブレッドボードで使用する場合はまたげるサイズのものを選択し、かつソケット着用がよろしいのではないかと思う。今回、本品用のソケットは未入手である（存在するとして、だが。調べた範囲では見つからなかった）。

# † 野望
動くものがあるのに新たなものを作成した理由は好奇心からだけではない。
これを複数用意すれば自動化の度合いが向上するのではないかという野心もあった。だが、元ネタの方がすでに試して不可という結論を出していた。当方でもこれを確認している。
しかし！　半自動モフり機壱號と併用すれば・・・
<blockquote class="twitter-tweet"><p lang="und" dir="ltr"><a href="https://t.co/vj7Ml7GDc4">pic.twitter.com/vj7Ml7GDc4</a></p>&mdash; ちゃり (@amb98) <a href="https://twitter.com/amb98/status/1186142058731323393?ref_src=twsrc%5Etfw">October 21, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
ご存じの方も多いかと思うが、FGOはスマホを猛烈に加熱する。それとともに挙動が悪くなる。
画鋲とスマホの接触もはがせること前提の両面テープでは満足ではなく、少しでも浮くと反応しなくなる。

# † 結論
完全自動化への道のりは遠い。
フィーリングの正体は何か？

#はじめに
今回は‪[「無意識の脳 自己意識の脳   アントニオ・R・ダマシオ」](https://www.amazon.co.jp/dp/4062118785/‬)
の紹介です。

#結論

アントニオ・R・ダマシオのソーマティック・マーカー仮説は、人間が意思決定の効率化のために、身体的な感情をベースにしているのではないかという説です。
(めちゃくちゃざっくり)

#解説

今回の解説は物凄く難しいので、割愛します。
詳しくは上記の本を読んでください。

その代わりに例を挙げます。

>あなたが激しく怒るような出来事を想像してみて下さい。
今まさに怒りに震えている時、あなたの身体はどのような状態になっていますか？

人が怒る時の身体的状態はだいたい似通っています。
1. 血圧が上がる。
2. 心拍数が上がる。
3. 筋肉に力が入る。
4. 体温が上がる
5. 発汗
6. 呼吸の変化

では仮に、これらの身体的反応が全く発生しないとしましょう。
その時あなたは怒りを覚える事が出来るのでしょうか？

別のケースも考えてみましょう。

>あなたの初恋の時を思い出してください。
もしくは、自分の好みの相手にドキドキした時の事でもいいです。

恋愛感情についても同様です。
ドキドキという擬音語が示す通り、あなたは自分の心臓が激しく脈動するのを感じるかもしれません。

しかしもし心臓の鼓動も正常で、全身の筋肉の緊張も体温の上昇も無かった場合(あと男性の場合は精嚢が空っぽだった場合？)、
あなたは相手に対して恋愛感情を覚えるでしょうか？

(吊り橋効果とかもありましたね。

#これから

次は、「アリータ:バトル・エンジェル」というサイボーグが当たり前になった世界の映画の話をします。
初心者のUNIXコマンドメモ

#はじめに
**本メモはUNIXのコマンドのメモです。**
初心者ですぐ忘れる自分のための備忘録です。
（随時更新）

#ls
今いるディレクトリにあるファイル一覧を表示する

| コマンド       |効果 |
|:-----------------|:------------------|
| ls            | 一覧を表示する|
| ls -a            |一覧を全て表示する（＝隠しファイルも含めて全て）|
| ls -l            |一覧を詳細表示する|
| ls -1           |一覧を縦に表示する（＝詳細までは不要な場合）|
| ls -t            |一覧を更新時間順に表示する|
| ls -x             |一覧を拡張子毎に表示する|

組み合わせて実用的に使用する例は以下の通り

| コマンド       |効果 |
|:-----------------|:------------------|
| ls -la           | 一覧を全て詳細表示する|
| ls -lta            |一覧を全て詳細表示＆更新時間順に表示する|

#pwd
今いるディレクトリ（＝カレントディレクトリ）を表示する
シェルを起動した直後にいるディレクトリのことをホームディレクトリと呼ぶ

| コマンド       |効果 |
|:-----------------|:------------------|
| pwd           | 今いるディレクトリを表示する|

シェルを起動した直後はホームディレクトリとカレントディクトリは同じになる

#mkdir
ディレクトリを作成する

| コマンド       |効果 |
|:-----------------|:------------------|
| mkdir xxx           | ディレクトリ xxx を作成する|

#cd
ディレクトリを移動する

| コマンド       |効果 |
|:-----------------|:------------------|
| cd xxx           | ディレクトリ xxx に移動する|
| cd ..           | １つ上のディレクトリに移動する|

/ を用いて複数個繋げて適用させることが可能になる

| コマンド       |効果 |
|:-----------------|:------------------|
| cd xxx/xxx/           | ディレクトリ xxx/xxx に移動する|
| cd ../../           | ２つ上のディレクトリに移動する|
DEPRECATION WARNING: Class level methods will no longer inherit scoping from `fixed` in Rails 6.1.

# 警告の意味

※ どのコードも意味が無く申し訳ないですが、生成されるSQLの問題なので意味は伝わると信じてます・・・いいサンプルコードが思いつかなくてすいません。

Rails5から6にアップグレードしたらこんな警告が出るようになった。

```
DEPRECATION WARNING: Class level methods will no longer inherit scoping from `fixed` in Rails 6.1. To continue using the scoped relation, pass it into the block directly. To instead access the full set of models, as Rails 6.1 will, use `ShiftUser.unscoped`. (called from block in <class:ShiftUser> at /home/circleci/test_dir/app/models/shift_user.rb:10)
```

問題のコードはこんな感じ。

```rb
class ShiftUser < ApplicationRecord
  scope :fixed, -> {
    ShiftUser.reflected.or(ShiftUser.failed)
  }
```

このコード、私のミスで変なコードになってます。本来意図したコードは下記の感じです。

```rb
class ShiftUser < ApplicationRecord
  enum status: { building: 1, reflected: 2, failed: 3 }
  scope :fixed, -> {
    reflected.or(failed)
  }
```


で、現状6.0まではどっちも同じSQLが発行されます。

```rb
ShiftUser.where(user_id: [1,2]).fixed
# SELECT `shift_user`.* FROM `shift_user` WHERE `shift_user`.`user_id` IN (1, 2) AND (`shift_user`.`status` = 2 OR `shift_user`.`status` = 3)
```

ブロック内で`ShiftUser.reflected`とクラスメソッドから呼んでいるのだからActiveRecordRelationがリセットされそうな感じがするのですが、継承されてるんですね。

この挙動が気持ち悪いので6.1から変えるという話だと思います。たぶんこの辺が関連ISSUEだと思われます。

https://github.com/rails/rails/pull/32380
https://github.com/rails/rails/pull/35186
https://github.com/rails/rails/pull/35280

# どう治すか？

ほとんどの場合下記のように修正すれば問題ないでしょう。

```rb
class ShiftUser < ApplicationRecord
  scope :fixed, -> {
    reflected.or(failed)
  }
```

このように直接メソッド呼ぶようにしておかないと6.1になった時に挙動が変わりますね。現状6.0以前バージョンで6.1の挙動を実現したい場合は`ShiftUser.unscoped`使います。こんな感の2フェーズクエリーでたまに使うかも。

```rb
class ShiftUser < ApplicationRecord
  scope :some_scope, -> {
    where(user_id: ShiftUser.unscoped.pluck(:user_id))
  }
```

現状でこのコードを

```rb
class ShiftUser < ApplicationRecord
  scope :some_scope, -> {
    where(user_id: ShiftUser.pluck(:user_id))
  }
```

こう書いてしまうと下記のように、内側のSQLにも`where(user_id: [1,2])`がくっついて（たぶん）意図してないコードになります。

```rb
ShiftUser.where(user_id: [1,2]).some_scope
# (0.3ms)  SELECT `shift_user`.`user_id` FROM `shift_user` WHERE `shift_user`.`user_id` IN (1, 2)
#   ShiftUser Load (0.4ms)  SELECT `shift_user`.* FROM `shift_user` WHERE `shift_user`.`user_id` IN (1, 2) AND 1=0
```
PocketMine-MPをConohaVPSで立てる(2019/10)

## 突如としてマインクラフトをしたくなる
突然にマインクラフトをしたくなった。理由はいらないのさ。
ハマり始めた人と一緒にやることになったのだが、ワールドを共有しかつ同時にオンラインするには以下の方法がある。

1. Realmsにサブスクライブして400or900円/月(適当)で遊ぶ
 - あんま金払いたくない。解約めんどくさそう。あんま回線良くなさそう。
2. 同じWifiネットワークに接続して遊ぶ
 - 使っているワールドをコピーしてローカルでごちゃごちゃすればまぁ仮想的に同時にワールドを編集することになるけどめんどくさい。ワールドで遊んでたらバッタリ会うみたいなワクワクがないのでナシ。
3. 自分でサーバを立てる
 - 一番めんどくさそう。でもマイクラもインフラにも触れるから楽しいことになりそう。

## 自分でサーバを立てることにする
そろそろ個人で真面目にサービスを作りたかったので、インフラの勉強がてら自分で立てることにした。
Conohaは使ったことがなかったが、ネットを見回した感じ一番マイクラのサーバになってそうで情報量が多そうだと判断したのでConohaをマイクラサーバとして選択した。
とりあえず以下の記事でサーバを立てる。自分はメモリ1GB SSD50GBのプラン(最大900円？)でイメージはOS/CentOsを選んだ。
[ConoHaでサクっとWebサーバーを作ろう](https://qiita.com/HitoshiHaga/items/5e21f9b4f52158e28510)
ここからが長く、必要なミドルウェアを落として、PMMPのコードをコンパイルして。。などを繰り返すことになるが、なかなか上手くいかない。なんせ4,5年前の記事がほとんどで、前までは上手くいっていたんだろうなーみたいな記事がたくさんある。しかも自分は所詮アプリケーションエンジニアなのでデバッグしようにもキツイ。。
とりあえず、[公式の手順](https://pmmp.readthedocs.io/en/rtfd/installation/installing-manually.html)も上手くいかないがこの手順に絞ってエラーを解決していこうと考えた。(この時点でだんだんとRealmsが選択肢に。。しかも俺結局900円払うことになってるじゃん。。)
**このドキュメントにそって作るんだ！他は信頼しすぎるな！**
[公式](https://pmmp.readthedocs.io/en/rtfd/installation/installing-manually.html)

# 手順通りに実行
##1. 一般ユーザを作成
とりあえずrootユーザはよろしくないし、今後の手順でもrootユーザは怒られるので一般ユーザを作成してログイン。


- ユーザを追加
`adduser takeru`

- `takeru`ユーザのパスワード変更
`passwd takeru`

- `takeru`を全権限をもつGroup(Wheel)に追加する。
`sudo gpasswd -a takeru wheel`

- ユーザの切り替え
`su takeru`

- rootディレクトリに権限がないのでホームディレクトリに移動。
`cd`


## 2.`wget -q -O - https://get.pmmp.io | bash -s -`を実行
この時`Please Install ***` と出たら大人しくインストールする。
以下のように流せばおそらく必要なものは揃う。

```
sudo yum install -y make;
sudo yum install -y autoconf;
sudo yum install -y automake;
sudo yum install -y m4;
sudo yum install -y bison;
sudo yum install -y gcc-c++
sudo yum install -y git;
sudo yum install -y cmake;
sudo yum install -y libtool";
```
ミドルウェアが足りてないと↓
<img width="1244" alt="スクリーンショット 2019-10-21 13.09.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243100/6cf654d4-2242-9bfa-1c16-08a250560dba.png">

コンパイルが終わったら、カレントディレクトリが以下のようになる。
<img width="1224" alt="スクリーンショット 2019-10-21 13.28.43.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243100/2ca35114-ff16-51eb-e88f-494c12406fcf.png">

## 3.php7をインストール
- tarをダウンロードする
`wget https://jenkins.pmmp.io/job/PHP-7.3-Aggregate/lastSuccessfulBuild/artifact/PHP-7.3-Linux-x86_64.tar.gz`

- tarを展開
`tar xfz PHP-7.3-Linux-x86_64.tar.gz`

成功すると`~/bin/php7/bin`にphp関連のファイルができているので確認する。

## 4.実行してみる
- `~/`に戻る。
- `./start.sh`を実行する。
すると`./bin/php7/bin/php: error while loading shared libraries: libbz2.so.1.0: cannot open shared object file: No such file or directory`というメッセージが出て実行できない。
いろいろ検索してみるとこんな[blog](https://michaelheap.com/error-while-loading-shared-libraries-libbz2-so-1-0-cannot-open-shared-object-file-on-centos-7)が見つかった。
くそ！ライブラリに不具合があったトラップか！と素直に`sudo yum install -y bzip2-devel`する。
そのあとに`sudo ln -s find /usr/lib64/ -type f -name"libbz2.so.1*" /usr/lib64/libbz2.so.1.0`する。

## 5. 改めて実行してみる
ようやく `./start.sh` で実行できるようになり初期設定のフローが始まる。

## 総括
10/21現在。Realmsで生活しています。
どうやらserver.propertiesもロクに読み込まれていない(spwanMobsとか,シード値とかのプロパティが効いていない)っぽいし、何より情報が少なすぎてこんなんならRealmsにするわ！ってなりました。
誰かのお役に立てたら幸いです。じゃ、ちょっくら木こりしてきます。
gdb switcher

# gdb-switcher
Legacy gdb / gdb-peda / gef (gdb enhanced features) / pwngdb / radare2の切り替えが簡単にできる [gdb-switcher](https://github.com/2O2L2H/gdb-switcher) の紹介

## INSTALL
```
$ git clone https://github.com/2O2L2H/gdb-switcher.git
$ cd gdb-switcher
$ ./install.sh
$ ./setup.sh
$ cd ~
$ source .bashrc
```

## UNINSTALL
`~/.gdbinit`から下記を削除

```
function gdbs() {
      echo -e "\n[*] Which debugger ?"
...
}
```

## USAGE
```
$ gdbs

[*] Which debugger ?

1 : Legacy GDB
2 : peda
3 : gef
4 : pwndbg
5 : radare2
2
[+] gdb-switch => peda

$ ❯ gdb -q ./executable
Reading symbols from ./executable...(no debugging symbols found)...done.
gdb-peda$ 
```
Rust/tokioで非同期チャットサーバー



## TL;DR
- Rust/tokioで非同期チャットサーバーを作ってみました。
- 比較のために、同期サーバー作ってみました。
- テストしてパフォーマンスを比較しました。
- 思った通り、非同期の方がCPU負荷が少なく、同じ処理を実行できました。
- ついでに、C#でも非同期サーバーを実装して、比較しました。
- Rustの方が速そうでした。

※若干説明が正確でないところがあります。正しい理解のためには、公式ドキュメントなど参照してください。

## Rustとは
- GCなしで、安全なメモリ管理
- 実行時コストなしで、抽象化
- 関数型言語からの影響


> 「プログラミング言語「Rust」は、「C」や「C++」並みのパフォーマンスと、開発者が墓穴を掘るのを防ぐ仕組みとを兼ね備えたプログラミング言語だ」

「プログラミング言語「Rust」--2019年こそ学ぶべき7つの理由」
https://japan.techrepublic.com/article/35131764.htm


## Tokioとは
スレッドプールを使って、タスクを並列にいい感じに実行してくれるやつです。
![tokio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227302/fe16160a-beaf-5d1c-c521-65c21608f2e0.png)

※半年ほど前に作ったので、std::futureが入る前の古い方のtokioです。

```
tokio = "0.1.20"
futures = "0.1.25"
```


## Tokioを使って非同期なチャットサーバーを作ってみよう
設計はこんな感じ。
送受信と入室処理がそれぞれ別タスク（別スレッド）で動く。
Channelとは、スレッドセーフなキューだと思ってもらえればOKです。
![rust-chat-design.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227302/4aab4cfa-418f-e74e-f475-f2aa903c2ded.png)


比較のために、同期のチャットも作ってみる。
設計はこんな感じ。
送受信も入室処理も全部同じタスクで処理。
何もすることがない時は、ループがぐるぐる回る。
![sync-chat.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227302/938206a5-84f5-05e2-49c0-0e555707755e.png)

## パフォーマンス測定
- 50人が同時にアクセス
- サーバーは、１部屋１０人ずつでルームを作る
- CLはそれぞれ、10〜100ミリ秒ずつランダムに間を開けながら、20〜200バイトのデータを繰り返し送信


### 結果：同期の場合
![result-sync.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227302/fed5764a-48b2-2829-e1b8-2c4204420c08.png)

CPU使用率が上がったり下がったり。誰も喋っていない時、ループをぐるぐる回っているので、その間CPUが100%になっている

### 結果：非同期の場合
![result-async.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227302/1f56aa11-7e77-78da-deab-e2306179d902.png)

いい感じにCPU使用率が安定している。計画どおり (￣ー￣)ﾆﾔﾘ

### C#で非同期もやってみた
![result-async-cs.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/227302/2d9a09c1-49ec-1eba-7973-987e6d5944cb.png)

CPU使用率はRustと同じくらい。でも、ネットワークの速度がRustより半分くらい遅い。
やっぱりRustは速い！ということに違いない。

### わかったこと
- 非同期の方がCPUを効率よく使える（あたりまえですが・・）
- C#よりRustで書いた方が速度が出る

C#は async/awaitが使えるので非同期も簡単に書ける。
Rustももうすぐ async/awaitが来るので期待大。

## Rustを使って良かったところ
- トレイトを使ってソケットの送受信の機能を抽象化。Room側のソースはTCP/WebSocket を意識しないで書ける。しかも抽象化による実行時コストがゼロ。
- Futureトレイトを使うことで、タスクが書きやすい（でも async/await があればもっと書きやすくなるはず）

## Rustを使ってつらかったところ
- Future使った時に型推論がどう動くのかが理解できずに苦しんだ
- ドキュメントがあまり整備されてない
- サンプルが少ない


## 今回つかったソース

サーバー：
https://github.com/mas-yo/rustgs/tree/lt20190605
テストクライアント：
https://github.com/mas-yo/rustgs-testcl/tree/lt20190605
SSH接続のショートカットをつくる

SSH接続するとき、毎回コマンド打つのも面倒なので、エイリアスつくってみたら楽になったのでメモ。

## 環境

* MacOS 10.14.6
* zsh

## 構成

```
.
├── .ssh/
│   ├── config
│   └── conf.d/
|       └── *.conf
├── .conf/
│   └── *.sh
└── .zshrc
```

### .ssh/config

SSH接続するときに参照される接続情報が記載されているファイル。

普通はこのファイルに接続情報が記載されていくのですが、数が増えると管理が大変なので、いくつか分割して `conf.d` 以下に設定ファイルとして管理する。

外部ファイルから読み込むときの設定だけ追記しておく。

```bash:config
...
Include ~/.ssh/conf.d/*.conf
```

### .ssh/conf.d/*.conf

SSH接続するときの情報がまとまっているファイル。

以下のような情報が記載される。

``` bash:*.conf
Host host.com
  HostName host.com
  User user_name
  IdentityFile ~/.ssh/rsa_file
  ServerAliveInterval 60
  AddKeysToAgent yes
```

### .conf/*.sh

sshコマンドのオプション指定・接続先指定もまとめてエイリアスを作るためのファイル。

```
alias ssh-host='ssh host.com'
```

### .zshrc

上記の各変更を読み込むための設定を追記。

```bash:.zshrc
...
for f in ~/.conf/*; do source $f; done
```

以上の設定を反映すると

```bash
$ ssh-host
```

とコマンド実行すれば、接続ができます。
[Java]StringからPath型に変換して、パスを取得する方法

Java8で、ファイルパスを取得する際にPathクラスというものが必要になったのだが、処理中にStringのものも混在していて逐一変換しないといけない状態があったのでメモ書き。

結論から言うと、Pathクラスのresolveメソッドで、引数にStringの文字列を渡してあげればパス全体をPath型として認識させてあげることができる。

参考サイト：Path (Java Platform SE 8 )
https://docs.oracle.com/javase/jp/8/docs/api/java/nio/file/Path.html

resolveメソッドで指定した引数を追加された状態で、ファイルパスの全体を設定することができる。

具体例：Path型で指定したパス→/test/pathTest
	      Stringで追加したいパス→hoge.txt
	      
結果：resolveメソッドを使用した結果→/test/pathTest/hoge.txt
※区切り文字は「/」と仮定

もし解釈が違っていたとか、もっと楽な方法があるのでしたら教えていただけると幸いです。
Jacksonとは？

こんにちは。
ぽんぽこです。

本日はJacksonについてお話しします。

では本編へ。

##Jacksonとは？
JacksonはJavaで使えるJSONライブラリです。
JSON形式の文字列をJavaのオブジェクトに直接マッピングしたり、
逆にJavaオブジェクトをJSON文字列に変換できたりします。

HTTPレスポンスをパースしたりオブジェクトをBase64エンコーディングする時などに便利です。

要するにすごーーーく便利な物です！

##Jacksonを使うメリット

Jacksonを使えるとJSONを簡単に扱えます。
Jsonを使えるようになると、とても色々なことができるようになり、世界が大きく広がります。
なぜなら、TwitterやFacebook、GoogleなどのWEBサービスとはJSONでやりとりするからです。

つまり、JSONが分かれば、世の中にあるWEBサービスの色々な機能を自分で使えるようになります！！

Jsonの良さについては別の記事で紹介します！

##Jacksonの使い方

Jacksonを利用するにはライブラリのダウンロードが必要です。
別の記事で紹介したMavenを利用する場合は以下を依存関係に指定します。

Mavenで利用する場合

    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.2.3</version>

Mavenを利用しない場合は以下のjarをダウンロードします。
>
jackson-databind-2.9.9-sources.jar
jackson-annotations-2.9.0-sources.jar
jackson-core-2.9.9-sources.jar

上記の方法でJacksonを使用することができるので
みなさんも試してみてください！

では次回、Jsonとは？でお会いしましょう。
では。
【python3】pip3をプロキシ環境で使用する

#経緯
私はプロキシを使用しないといけない環境で開発しています。これによってpip3がエラーを吐くという状態に陥ってしまいました。

#対策
pip3実行時にプロキシを使用するオプションをつける。

#やり方
プロキシを使用するのに認証情報が必要な場合のやり方です。

```bash
pip3 --proxy=http://username:password@addless:port install ~
```
Herokuでバックグラウンドジョブ実行中にDynoが再起動されるのを回避する方法

## はじめに

Herokuで構築していたアプリケーションでバックグラウンドジョブを設定していた時にたまたまDynoの再起動タイミングと重なってしまい処理がコケてしまったので、それを防ぐ方法について書いておこうと思います。

Dynoのライフサイクルについては[こちら](https://jp.heroku.com/dynos/lifecycle)に少し記載があります。

> アプリとシステム全体の健全性を維持するため 1 日に 1 回以上再起動されます（再起動の時点で残っているリクエストは、問題なく処理されます）。複数の dyno を実行するアプリの場合、各 dyno は異なる間隔で再起動されます。

> dyno の再起動は Dyno Manager によって自動的かつ透過的に行われ、ログに記録されます。スケジュールにもとづく再起動だけでなく、新しいコードがリリースされたり、アドオンが変更されたり、設定変数が変更されたりした場合も dyno は自動的に再起動されます。また、手動で dyno を再起動することもできます。

## buildpackの追加

[Heroku CLIを拡張するbuildpack](https://jp.heroku.com/elements/buildpacks)を追加します。

```
$ heroku buildpacks:add https://github.com/heroku/heroku-buildpack-cli -a アプリ名
```

## CLI用認証トークンの設定

```
$ heroku authorizations:create

// 上記のコマンドで返却されたトークンを以下でアプリに設定する
$ heroku config:set HEROKU_API_KEY=トークン -a アプリ名
```

## Heroku Schedulerアドオンを追加する

```
// アドオン追加
$ heroku addons:create scheduler:standard -a アプリ名

// アドオンのページを開く
$ heroku addons:open scheduler -a アプリ名
```

## Heroku Schedulerの設定

例えば以下のような構成のDynoを毎日指定時刻に再起動させたいとする
![Image 2019-10-21 at 1.03.24 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19716/17d916a6-aa90-e89f-62dd-adc3623cfad9.png)


アドオンページの 「Add Job」から新しいジョブを追加
すると以下のようなページが表示されるので、設定を行っていく
![Image 2019-10-21 at 1.07.18 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19716/e21d3a82-cbfd-5659-c580-40be00234b90.png)


1. どのタイミングか
2. コマンド
3. Dyno size
4. Save

を設定する。

再起動を行うコマンドですが、アプリによって設定が異なる可能性があるので、以下は参考程度に

```
/app/.heroku/bin/heroku restart -a アプリ名 指定のDyno
```

となるので、webとworkerをで一つずつジョブを作成し、それぞれのコマンド設定の項目へ以下のように設定しました。

web dyno:

```
/app/.heroku/bin/heroku restart -a アプリ名 web.1
```

worker dyno:

```
/app/.heroku/bin/heroku restart -a アプリ名 worker.1
```

以下が設定した画面です。
![Image 2019-10-21 at 1.13.52 PM.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/19716/115d4098-6264-21b8-960c-18343136af2d.png)


> 設定する時間がUTCとなっているので、その点に注意して再起動タイミングを設定してください。

以上となります。
kubectl apply で SchemaError(io.k8s.api.apps.v1.DeploymentList) と出たときの対処法

この記事はMacで開発していることを前提に書いてます

## 現象
- GKEのバージョンを1.14.xにアップグレードした後にkubectl applyを実行したら、以下のようなエラーが出ました

```
$ kubectl apply -f deployment.yaml 
error: SchemaError(io.k8s.api.apps.v1.DeploymentList): invalid object doesn't have additional properties
```

## 原因
- kubectlのClientバージョンが古い場合に起こるようです
- kubectl versionで見てみます

```
$ kubectl version
Client Version: version.Info{Major:"1", Minor:"10", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14+", Platform:"linux/amd64"}
```

## 対処法
### kubectlのバージョンを上げます
- usr/local/bin下のkubectlを削除します
- 最新のkubectlをダウンロードして、usr/local/bin下に置きます
  
```
$ rm /usr/local/bin/kubectl
$ curl -LO https://storage.googleapis.com/kubernetes-release/release/$(curl -s https://storage.googleapis.com/kubernetes-release/release/stable.txt)/bin/darwin/amd64/kubectl
$ chmod +x ./kubectl
$ sudo mv ./kubectl /usr/local/bin/kubectl

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"16", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"14+", Platform:"linux/amd64"}
```

### kubectlのバージョンを上げないで一時的に済ます場合は--validate=falseをつけます

```
$ kubectl apply -f deployment.yaml --validate=false
deployment.extensions "hoge" configured
```

## 参考URL
- [Kubernetes create deployment unexpected SchemaError
](https://stackoverflow.com/questions/55417410/kubernetes-create-deployment-unexpected-schemaerror)
Rails6の本番環境でBlocked hostエラーが発生したときの対処法

# 結論
下記のいずれかでエラーを回避できます。

※ひとまずエラーを回避するための方法として記載しておりますが、これがベストな対処法かは判断し兼ねます。対応は自己責任でお願いいたします。

## エラー回避策①
`config/environments/development.rb`に下記を記載し、ホワイトリストに許可したいhostを追加する。

```config/environments/development.rb
Rails.application.configure do
（中略）
  config.hosts << "<許可したいホスト名>"
（中略）
end
```

後述するエラーメッセージにしたがった方法です。
今回の私の場合、`config.hosts << "thawing-caverns-37676.herokuapp.com"`を記載しました。


## エラー回避策②

同じく`config/environments/development.rb`に下記を記載し、ホワイトリスト全体をクリアする。
これにより、すべてのホスト名に対するリクエストを通過させることができる。

```config/environments/development.rb
Rails.application.configure do
（中略）
  config.hosts.clear
（中略）
end
```

ただし、せっかくRails6で追加された保護機能を無効化してしまうため、推奨は①のような気がします。

# 発生したエラー
Rails6で開発した環境をherokuへプッシュしてアクセスしようとしたところ、下記のようなエラーが発生した。

<img width="1159" alt="スクリーンショット 2019-10-21 12.15.27.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/465401/8e17f546-e828-8939-531e-31d152a7baeb.png">

```
Blocked host: thawing-caverns-37676.herokuapp.com
To allow requests to thawing-caverns-37676.herokuapp.com, add the following to your environment configuration:
config.hosts << "thawing-caverns-37676.herokuapp.com"
```

※thawing-caverns-37676.herokuapp.comはherokuのアプリ名

# 原因
調べてみると、Rails6へのアップデート時の変更点の一つである
**DNSリバインディング攻撃からの保護**
という機能が原因のようです（[Railsガイド〜Ruby on Rails 6.0 リリースノート〜](https://railsguides.jp/6_0_release_notes.html)参照）。

上記機能の[Pull Request](https://github.com/rails/rails/pull/33145)によると、攻撃を保護するための`ActionDispatch::HostAuthorization`という新しいミドルウェアが導入されたことにより、許可するホストは自分で設定しなくてはならなくなったようです。
（デフォルトでは0.0.0.0、::、およびlocalhostからのリクエストを許可）

# まとめ
対処法として、`config/environments/development.rb`に下記のいずれかを記載する。

対処法①　ホワイトリストに許可したいhostを追加

```
config.hosts << "<許可したいホスト名>"
```

対処法②　ホワイトリスト全体をクリア

```
`config.hosts.clear`
```

# 参考
https://www.fngtps.com/2019/rails6-blocked-host/
E-MapReduceのMetaServiceについて

今回の記事はアリババクラウドのビッグデータ処理サービス<a href="https://jp.alibabacloud.com/product/e-mapreduce?spm=a21mg.8156306.901798.39.40ec1284iWraOy">E-MapReduce</a>について、触れさせていただきたいと思います。

E-MapReduceは2.1.0 versionから、MetaServiceと呼ばれる機能をサポートするようになりましたが、業務上まだ利用されたことがない方がいらっしゃっるかと思いますので、その機能が一体なにできるのかを皆んさんに共有させて頂きたいです。

<!--more-->


### MetaServiceとは
一言でいうと、MetaServiceはE-MapReduceのRAMロールに一時的なセキュアトークンを払い出すウェブサービスです。その他、E-MapReduceクラスタの所属リージョンや、所属ネットワークタイルなどの情報を示すこともできます。

### なぜMetaService必要なのか
MetaServiceが出る前に、MapReduceやHive、Sparkなどでジョブを開発する際に、ユーザーアカンウトのAccessKeyId及びAccessKeySecretを明示的に設定ファイルやコマンドパラメータなどに書かなければいけないですが、もちろん、セキュリティに情報漏洩のリスクが存在しております。

例えば、MapReduceの場合、下記のようなの入力を避けるができませんでした。




```java
conf.set("fs.oss.accessKeyId", "${accessKeyId}");
conf.set("fs.oss.accessKeySecret", "${accessKeySecret}");
conf.set("fs.oss.endpoint","${endpoint}");
```



E-MapReduceクラスタ上にも、OSSのファイルを読み書きする際に、下記のようなAccessKeyIdとAccessKeySecret付きのURLを指定しなければなりませんでした。
<pre class="EnlighterJSRAW" data-enlighter-language="null">hadoop fs -ls oss://[accessKeyId:accessKeySecret@]bucket[.endpoint]/object/path</pre>
このような課題を解決してくれるのがMetaServiceを利用したE-MapReduceアプリケーションロール (AliyunEmrEcsDefaultRole)です。デフォルトでは、クラスタを作成するときに、AliyunEmrEcsDefaultRole及びバインドする権限ポリシーが自動的に付与されるので、別にユーザー自身が作業する必要がありません。

ポリシードキュメントと権限付与ポリシーは以下となりますが、ご覧のように、OSSへアクセスアクションが与えられました。また必要に応じて、OSSへアクセス権限を調整したり（例えば、特定ディレクトリのみへのアクセスを制限したい場合）、LogServiceなど他のサービスへのアクセス権限を付与したりすることも可能です。
<pre class="EnlighterJSRAW" data-enlighter-language="null">{
  "Statement": [
    {
      "Action": "sts:AssumeRole",
      "Effect": "Allow",
      "Principal": {
        "Service": [
          "emr.aliyuncs.com"
        ]
      }
    }
  ],
  "Version": "1"
}</pre>
<pre class="EnlighterJSRAW" data-enlighter-language="null">{
  "Version": "1",
  "Statement": [
    {
      "Action": [
        "oss:GetObject",
        "oss:ListObjects",
        "oss:PutObject",
        "oss:DeleteObject",
        "oss:ListBuckets",
        "oss:AbortMultipartUpload"
      ],
      "Resource": "*",
      "Effect": "Allow"
    }
  ]
}</pre>
MetaServiceによって、MapReduceやSparkなどの開発を行う際に、上記のように、AccessKeyId及びAccessKeySecretを入力する必要がなくなりました。また、クラスタ上で、OSSへサクセスする際にも、AccessKeyIdとAccessKeySecret付きのURLの指定も必要なく、Hadoopに慣れ親しんだユーザーが容易にコマンドを記述することができました。
<pre class="EnlighterJSRAW" data-enlighter-language="null">hadoop fs -ls oss://bucket/path
hadoop fs -cp oss://bucket/path1 oss://bucket/path2</pre>

### まとめ
いかがでしたでしょうか、MetaServiceを使い、ロールに必要な権限だけを付与することで、AccessKeyId及びAccessKeySecret漏洩のリスクを減らすだけではなく、ユーザーエクスペリエンスの向上にも繋がります、特に、OSS リソースに対話的にアクセスする場合に、OSS パスの長い文字列のURLを書く必要もなくなりましたので、皆さんぜひご活用してください。
JavaScriptの概要


随時追記します

ソースプログラムのマシン語の変換方式

- コンパイラ方式
 - 「コンパイラ」っていうソフトウェア使って一気に変換を行う 
- インタプリタ方式
 -  1行ずつ変換していく

☆**JavaScript**は**インタプリタ方式**だよ

Java、C#、Python とかは本格的な**オブジェクト指向**の概念を取り入れている
JavaScriptは簡単なオブジェクト指向を取り入れている⇒**オブジェクトベース指向**
####⇒　初心者に優しいよ！！！！！！！




##JavaScriptに必要なものは？
- エディタ（メモ帳とかサクラエディタとか）
- エディタの文字コード⇒**UTF-8**にする
- プログラムを動かすにはWebブラウザを使用

##必要なことその2
- 2つの<'meta>タグが必要
 - プログラミング言語の指定
 - 文字コードの指定
- <'script>タグのtype属性は、「text/javascript」を指定
MaxCompute SQLでデータ更新と削除する方法

既にご存じの方もいらっしゃると思いますが、MaxCompute SQLでは、データ更新(Update)と削除(Delete)をサポートしません。ただ、実際の業務の中で必要なケースも存在しています。そのケースに遭遇した場合にどうすればいいのでしょうか。本記事で実際の例を交えながら、対策を皆さんに共有させて頂きたいと思います。

<!--more-->
<ul style="list-style-type: square;">
<li><span style="font-size: 14pt;"><strong>データ更新</strong></span></li>
</ul>
MaxComputeでデータ投入を行う際に、Insert Into/Overwrite 2種類の方法があり、それぞれ違う意味合いを持ちます。Insert Intoは、テーブルやパーティションに追加データが挿入されるのに対し、<span class="keyword cmdname" data-spm-anchor-id="a21mg.p38356.a3.i5.4e852c320Mi3F9">Insert Overwrite</span> は、テーブルやパーティションから元のデータを削除してからデータが挿入され、データの置き換えとも言えます。

MaxCompute SQLは、SQLに似たような構文を使用できますが、SQL全ての標準に準拠しているわけではないため、Update文がありません。ただ、Insert Overwrite文を上手く活用すれば、データ更新を実現することも可能です。それでは、事前に作成したdemoテーブルを使い、試して見ます。

demoテーブル (Partitionは'20181208'です)は下記のようとなります。
<pre class="EnlighterJSRAW" data-enlighter-language="sql">select * from demo where dt = '20181208';</pre>
<img class="alignnone size-full wp-image-4574" src="https://techblog.sbcloud.co.jp/assets/2018/12/スクリーンショット-2018-12-18-16.07.55.png" alt="" width="871" height="192" />

cityコラムの一行目のBerlinをMunichに更新したいのであれば、下記の構文で実行すると、レコード更新ができるようになりました。
<pre class="EnlighterJSRAW" data-enlighter-language="sql">insert overwrite table demo partition (dt='20181208') select customerid,customername,contactname,address,case when city='Berlin' then 'Munich' else city end as city,postalcode,country from demo where dt = '20181208';

select * from demo where dt='20181208';</pre>
<img class="alignnone size-full wp-image-4577" src="https://techblog.sbcloud.co.jp/assets/2018/12/スクリーンショット-2018-12-18-16.10.39.png" alt="" width="872" height="186" />

<ul style="list-style-type: square;">
<li><strong><span style="font-size: 14pt;">データ削除</span></strong></li>
</ul>
標準SQLと同様に、テーブルの全レコードを削除したいのであれば、TRUNCATE TABLE table_nameを使えば、問題なく実現することができます。もし指定したいレコードを削除したい場合は、上述のInsert Overwrite文を利用して実現することも可能です、demoテーブルの例で使い方をみて見ましょう。例えば、'Munich'が含まれている行を削除したいならば、下記の構文を実行すると、削除動作ができるようになります。
<pre class="EnlighterJSRAW" data-enlighter-language="sql">insert overwrite table demo partition (dt='20181208') select customerid,customername,contactname,address,city,postalcode,country from demo where city != 'Munich' and dt='20181208';

select * from demo where dt='20181208';</pre>
<img class="alignnone size-full wp-image-4598" src="https://techblog.sbcloud.co.jp/assets/2018/12/スクリーンショット-2018-12-18-17.10.32.png" alt="" width="875" height="174" />

<ul style="list-style-type: square;">
<li><span style="font-size: 14pt;"><strong>まとめ</strong></span></li>
</ul>
いかがでしたでしょうか。Update文とDelete文がないため、悩ましい更新と削除の作業はInsert overwrite構文を活用すれば、実現できるようになりました。皆さんもぜひ活用してください。