OmniAICreator/Qiita-1.07M huggingface dataset:
CentOS5.3のOpensshアップグレード


突如古いサーバ（centos5.3）からGitPullできなくなり、Opensshをアップグレードしなければならなくなったので、その時のメモです。

原因は下記
https://githubengineering.com/crypto-removal-notice/

対処方法としては、openssh4.3を6.5にリプレイスする

```
yum clean all
yum install rpm-build gcc make openssl-devel pkgconfig krb5-libs krb5-devel pam-devel man
wget http://mirror.aarnet.edu.au/pub/OpenBSD/OpenSSH/portable/openssh-6.5p1.tar.gz
tar zxvf openssh-6.5p1.tar.gz
cp ./openssh-6.5p1/contrib/redhat/openssh.spec /usr/src/redhat/SPECS/
cp openssh-6.5p1.tar.gz /usr/src/redhat/SOURCES/

vi /usr/src/redhat/SPECS/openssh.spec
------------------------------------------------------
# Do we want to disable building of x11-askpass? (1=yes 0=no)
%define no_x11_askpass 1

# Do we want to disable building of gnome-askpass? (1=yes 0=no)
%define no_gnome_askpass 1
------------------------------------------------------

cd /usr/src/redhat/SPECS
rpmbuild -bb openssh.spec
# ここでエラーになる場合はspecファイルに記載されている依存パッケージをyumでインストールするといいかも

cd /usr/src/redhat/RPMS/x86_64/
ls -l
-rw-r--r-- 1 root root 616088  3月  5 15:29 openssh-6.5p1-1.x86_64.rpm
-rw-r--r-- 1 root root 808511  3月  5 15:29 openssh-clients-6.5p1-1.x86_64.rpm
-rw-r--r-- 1 root root  16795  3月  5 15:29 openssh-debuginfo-6.5p1-1.x86_64.rpm
-rw-r--r-- 1 root root 422547  3月  5 15:29 openssh-server-6.5p1-1.x86_64.rpm

rpm -Uvh *.rpm
```

上記でアップグレードするが、最後の `rpm -Uvh *.rpm` で下記のエラーが出てしまった。

```
rpm -Uvh *.rpm
エラー: 依存性の欠如:
	openssh = 4.3p2-36.el5 は (インストール済み)openssh-askpass-4.3p2-36.el5.x86_64 に必要とされています
```

恐らく、openssh4.3を6.5にリプレイスする際に、openssh-askpass4.3がopenssh4.3を参照しているからリプレイスできないのでは？と考えました（合っているかどうかは分かりませんが）。
因みにインストールする順番を変えても同じようにエラーがでてしまいます。

で、色々悩んだ結果、私の場合 `rpm -Uvh --nodeps *.rpm` で解決しました。
`--nodeps` は `依存関係を無視` です。
API Connect におけるJWTの認証

# JWTによる認証の重要化

近年、Serverless化、MicroService化によってJWTによる認証の重要度が増した事は別記事[JWTによる認証の分散化](https://qiita.com/Mr-K/items/0771b62bc53c39231671)に書きました。
すると、API ConnectでJWTを扱う為にはどうすれば良いかが気になります。

# JWTの発行元・発行先でのAPI呼び出し

これは、[JWTによる認証の分散化](https://qiita.com/Mr-K/items/0771b62bc53c39231671)のおさらいですが、
JWTは発行元（いわゆるトークン・エンドポイント）があります。おさらいついでに図も載せておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/192988/6751e5bf-810c-406e-770a-c6c3b1d0a15e.png)

| 項番 | 内容 |
|------|:--------------|
| ①    | JWT発行元に対するログイン  |
| ②    | JWT発行元でのログインフォームによる認証       |
| ③    | JWTの発行      |
| ④    | JWTを利用したAPIの実行       |
| ⑤    | JWTの検証（復号後のハッシュ検証）   |
| ⑥    | 検証後のAPI実行   |

JWTを発行するサービスは、Auth0が有名ですが、続々と登場するに違いありません。各種クラウドもそのようなサービスを持っています。
自分で作成するには、下記のようなライブラリを使ったりして、実装すると良いでしょう。

Python: https://github.com/rohe/pyjwkest
Java: https://bitbucket.org/connect2id/nimbus-jose-jwt/wiki/Home
Go: https://github.com/dgrijalva/jwt-go

```Go
	token := jwt.New(jwt.SigningMethodHS256)
	token.Claims["exp"] = time.Now().Add(time.Hour * 72).Unix()
	token.Claims["iss"] = "auth.service"
	token.Claims["iat"] = time.Now().Unix()
	token.Claims["email"] = user.Email
	token.Claims["sub"] = user.Username
```

API Connectはこの図の中のどの役割が可能なのでしょうか。

# JWTの発行

実はAPI Connectは、発行元にも、API使用者にもなります。
発行元になるには、jwt-generate ポリシーを使用します。

JWTを作成するには、鍵（JWK）が必要です。これは、細かい事は省きますが共通鍵暗号にする場合、HS256を使用し、JWT発行元JWT検証側で同じ鍵を使用します。

RS256　等は速度的に遅くなりますが公開鍵と秘密鍵の組（対称鍵）ですので発行元と検証側で別々の鍵を使います。

これは、https://mkjwk.org/ 等のサイトで作成できます。その他、前出のライブラリ等を使用しても良いでしょう。
発行者の情報もこのポリシー内で設定できます。

# JWTを利用したAPIの利用

API呼び出し時のチェックは、APIのアセンブリに jwt-varidate ポリシーを配置する事で可能です。

これでJWTがauthorization: Bearerヘッダーにない もの、また　JWT自体の署名が正当に評価されないものがはじかれます。

ここで先程も述べたように HS256を使用している場合は、JWTを発行した時と同じ鍵（JWK）を使用して、JWTを検証します。
RS256の場合は公開鍵と秘密鍵が別です。
取得したハッシュと発行元が付けた署名が同じ値であれば、検証完了で、APIを使用しても良い事になります。

# 検証のみのJWT利用

Auth0やGoogle Identity Platformを使用してJWTの発行元を用意する場合、セキュリティの考慮点から鍵を定期的に変えている場合があります。その場合は、GatewayScriptにて　鍵情報を提供しているエンドポイントから公開鍵　を取得し、その鍵を使用してJWTを検証する必要があります。

# IBM Cloud Private

IBMが提供しているサービスに、ローカルにKubernetesやIstio等を全て1セットにして導入できる　IBM Cloud Privateというものがあります。ここに Helmの Chart経由で API Connectが導入できるようになるかも知れませんので、そうなると Kubernetes上の Micro Service達をJWT認証するケースも出てきます。
その認証フロントとして API Connectを使用する場合、どのようなネットにするかが肝になると思われます。鍵が流出しない・セキュリティ的に問題ない検証環境でしたら最初の HS256を使用したパターンでも問題ないのかと思います。
別出しの認証局にした場合は先の議論のように認証エンドポイントを叩く必要があります。
いずれにしろ世の中は複雑化する一方ですね。

# 参考情報

・JWTを使用したポリシーのデモ ： https://developer.ibm.com/apiconnect/2016/08/16/securing-apis-using-json-web-tokens-jwt-in-api-connect-video-tutorial/
・MicroServiceとKubernetes・JWT ： https://classroom.udacity.com/courses/ud615
・UdacityのKubernetes実験リポジトリ：https://github.com/udacity/ud615/blob/master/app/handlers/login.go
・Google Identity Platformのjwks_uri（鍵提供エンドポイント） ： https://developers.google.com/identity/protocols/OpenIDConnect#discovery
・API ConnectとAuth0によるセキュア環境の作成： https://github.com/ozairs/apiconnect/tree/master/jwt
・IBM Cloud Private用Chart一覧：https://github.com/IBM/charts
ALTER TABLE INCLUDING ROWS文の動作を試す (Oracle Database 12.2) 

# テーブルのメンテナンス
  テーブルから不要なデータを削除する場合にはDELETE文を実行します。一方ででテーブルの表領域を移動する場合や再構成するためにはALTER TABLE MOVE文を実行します。
  ALTER TABLE MOVE文は表領域の指定を行わなずに、同一表領域内でテーブルの再構成を行う場合にも実行できます。Oracle Database 12cではこのデータの移動と不要データの削除を同時に行うALTER TABLE MOVE INCLUDING ROWS文がサポートされました。

# 実行例
使い方は簡単です。ALTER TABLE MOVE文に残すレコードを示す条件文を指定します
（マニュアル https://docs.oracle.com/cd/E82638_01/SQLRF/ALTER-TABLE.htm#GUID-552E7373-BF93-477D-9DA3-B2C9386F2877）。

## 例1 特定のレコードのみ残して同一表領域内で再構成
下記の例では、30日より前のレコードを削除しています。

```
SQL> ALTER TABLE orders MOVE INCLUDING ROWS WHERE order_date >= to_date(sysdate - 30) ;

```

## 例2 パーティションのマージ
下記の例では、パーティション h1_2018とh2_2018を、パーティション y2018にマージしています。その際にorder_status列がNULLのレコードを削除しています。
パーティションのマージだけでなく、パーティションのスプリットや、通常のテーブルからパーティション・テーブルへの変換時にもINCLUDING ROWS句を指定することができます。

```
SQL> ALTER TABLE orders MERGE PARTITION h1_2018, h2_2018 INTO PARTITION y2018
       INCLUDING ROWS order_status IS NOT NULL ;

```
## 例3 表領域の移動
下記の例では、パーティション y2017を表領域pastに移動しています。その際にorder_status列がNULLのレコードを削除しています。

```
SQL> ALTER TABLE orders MOVE PARTITION y2017 TABLESPACE past 
       INCLUDING ROWS order_status IS NOT NULL ;
```

# オプションの指定
ALTER TABLE MOVE文が素晴らしいのは、ONLINE指定が可能であることとデータの移動にNOLOGGINGが指定できることです。この機能により大量データの移動を運用中に、高速に行うことができます。

## 例4 NOLOGGINGとONLINE指定

```
SQL> ALTER TABLE orders MOVE ONLINE NOLOGGING INCLUDING ROWS WHERE order_date >= to_date(sysdate - 30) ;

```
Angularで作るER DIAGRAM TOOL - 第十回　モデルへエンドポイントを追加

##（１）モデルにエンドポイントを追加

/src/app/service/jsPlumb.service.ts
https://github.com/dog-ears/er-diagram-tool/commit/4123becc84351ee6a3f8b121836475d0d82b330c#diff-da7afb11f9169e78d9b5cfea7afcc510

・モデルのビューが生成されたときに呼ばれるinitModel()に、Endoint追加処理を記述します。
・追加先は、正確にはModelではなく、ModelのH2になります。
・オプションの意味は以下の通り

isSource: true, --- エンドポイントがコネクションの始点になるかどうか？
isTarget: true, --- エンドポイントがコネクションの終点になるかどうか？

これでプレビューします。

![cap10_1.jpg](https://qiita-image-store.s3.amazonaws.com/0/103767/ea27ee5f-86de-ed20-a4b8-ff4cc642fd1a.jpeg)

くっついて表示されるはずのエンドポイントとModel H2が、
離れて表示されてしまいました。

原因は、jsPlumbがエンドポイントを付与した後に、
googleアイコンが読み込まれて、幅が変わったためです。

ということで、アイコンの幅をあらかじめCSSで指定します。

/src/styles.css
https://github.com/dog-ears/er-diagram-tool/commit/4123becc84351ee6a3f8b121836475d0d82b330c#diff-0fd3637456511d89012d5274dd855970

これでうまく行ったかに見えますが、
この状態で、長い名前のschemaを追加すると・・・

![cap10_3.jpg](https://qiita-image-store.s3.amazonaws.com/0/103767/407b54db-c8b6-5438-c332-9e1bcc738872.jpeg)

モデルの幅が変わることにより、
また、エンドポイントが離れてしまいました。

ということで、エンドポイントを再描画する機能を追加します。



##（２）エンドポイント再描画機能追加

再描画が必要なタイミングは以下の通り。

・モデルの名前変更
・schemaの追加・変更・移動・削除

いずれも、htmlの描画が終わったあととなるため、
上記、変更タイミングで、フラグを立てて、
実際の再描画は、AppComponentのngAfterViewChecked()で行います。

/src/app/service/jsPlumb.service.ts
https://github.com/dog-ears/er-diagram-tool/commit/311d734be13d37ce306d7cca63573e32e305ceab#diff-da7afb11f9169e78d9b5cfea7afcc510

・repaintEverything()を実装



/src/app/service/data.service.ts
https://github.com/dog-ears/er-diagram-tool/commit/311d734be13d37ce306d7cca63573e32e305ceab#diff-ae990bb302f27e60323deb45d6746b17

・メンバ変数flg_repaintを追加。Constructorで初期値設定
・deleteModel()、deleteSchema()、moveSchema()の最後に、フラグを立てる処理追加



/src/app/modal-model/modal-model.component.ts
https://github.com/dog-ears/er-diagram-tool/commit/311d734be13d37ce306d7cca63573e32e305ceab#diff-ae990bb302f27e60323deb45d6746b17
/src/app/modal-schema/modal-schema.component.ts
https://github.com/dog-ears/er-diagram-tool/commit/311d734be13d37ce306d7cca63573e32e305ceab#diff-2588015c073ce9535c2d4c6b404f79ea

・モーダルが閉じるとき（ngOnDestroy()）でフラグを立てる処理追加



/src/app/app.component.ts
https://github.com/dog-ears/er-diagram-tool/commit/311d734be13d37ce306d7cca63573e32e305ceab#diff-5c26d2c8f8838f32ace87fdecd6344ea

・ngAfterViewChecked()追加。フラグが立っているとき、フラグを消して、再描画を呼び出します。
ngAfterViewChecked()は、何回も処理されるため、console.logはコメントアウト。

![cap10_2.jpg](https://qiita-image-store.s3.amazonaws.com/0/103767/b927c619-c047-2339-6647-d437c818ffc0.jpeg)

プレビューすると、無事endpointがついてきました。
これで、モデルのH2同士をつなぐ処理は完了です。

しかし、最終的に欲しいものは、モデルのH2同士はつなぎません。
モデルAAAとモデルBBBをつなぐ場合、つなぐのは[AAA - H2] と [BBBのschema(AAA_id)]になります。

ということで、次回はone-to-manyのリレーションの実装に進みます。
vulsでのリモートスキャン対象ホストが、sshd_configでForceCommand が設定されているとエラーが出る

### vulsでのリモートスキャン対象ホストが、ForceCommand が設定されているとエラーが出る
[ssh接続でのコマンドを記録したり、接続コマンドを制限して](https://dev.classmethod.jp/cloud/aws/record-ssh-session-through-a-bastion-host/)、ForceCommandでシェルをかましているケースは多いと思います。

そんなホストにスキャンをかけると様々なエラーが出ます。
`Unknown OS Type` みたいな感じで。 

### 解決方法
vuls稼働ホスト(ローカルIP)の時だけ、ForceCommandを無効にしましょう

```sh:/etc/ssh/sshd_config
ForceCommand /usr/bin/sshlog/shell

Match Address xxx.xxx.xxx.xxx
    ForceCommand none
```
設定を変更したら、sshdを再起動しましょう

```
service sshd restart
```

### 結論

OpenSSHのMatchディレクティブは便利
SSH秘密鍵のSSH-AGENTをつかった管理ベストプラクティスを考えてみた

# 暗号化されたSSH秘密鍵のパスフレーズ入力を出来る限り省略、なおかつ安全に運用する
- SSH秘密鍵のパスフレーズは必要
- しかも11文字以上の長いものが推奨される
- `ssh`や`git`のたびにパスフレーズをいちいち入力するのは大変
- `ssh-agent`のプロセスを管理する
- 必要なときにだけパスフレーズを入力(シェル起動時に入力とかしたくない)
- `ssh-add`された鍵を一定時間で自動消去


## SSH秘密鍵にちゃんとパスフレーズをつけよう。
- SSH接続に公開鍵認証を取り入れるのは当然ですが、秘密鍵にちゃんとパスフレーズつけてますか？
- （※もちろんパスワードログインはちゃんとOFFにしてね！）
- パスフレーズをめんどくさくて付けていない場合はPCやUSBメモリなんかに入った秘密鍵が漏れたら即アウトです。

### ***パスフレーズちゃんとつけてます！***
- 何文字のパスフレーズを付けていますか？
- 短いパスフレーズは↓くらいの時間で解除できるという検証結果もあります。

[SSH秘密鍵のパスフレーズは（つけるなら）11文字以上にしましょうねという話](http://freak-da.hatenablog.com/entry/20100901/p1)
> CPU	Intel Core i7 2.67GHz 
(実験では１コアしか使っていない)

>|パスフレーズ文字数|解析にかかった時間|
|---:|---: 
|5文字|8秒|
|6文字|480秒|
|7文字|8時間|
|8文字|20日|
|9文字|3.3年|
|10文字|197年|


## ssh-agent
-  ssh-agentはsshを使っていれば入ってるはず。
- ssh-agentを使えば、毎回パスレーズを入力しなくても1回入力しただけで覚えててくれる
- [秘密鍵のパスフレーズ入力をスルーする](https://qiita.com/onokatio/items/397a5899a0ec16c7e60a)

## ssh-agentの問題点
- 登録するときssh-addコマンドで秘密鍵ファイルを登録しなければいけない
- 登録するとずっと生の秘密鍵が残ってしまい明示削除しなければずっと使える状態のまま
- ssh-agentを一度起動すると、ログアウトしてもプロセスが残ったままになる
- 解答された鍵ファイルはプロセスごとに残っているのでプロセスを再利用する必要がある

#ssh-agentをプロセス管理して自動立ち上げ
- .bashrcに書き込んで、シェル立ち上げ時にプロセスがなければ立ち上げる
- 立ち上げたプロセスの情報を `~/.ssh-agent` ファイルに保存
- プロセスがあればそれを再利用
- ファイルの有効時間を設定

```bash:.bashrc
# 有効時間（好きな秒数に設定)
SSH_KEY_LIFE_TIME_SEC=3600

SSH_AGENT_FILE=$HOME/.ssh-agent
test -f $SSH_AGENT_FILE && source $SSH_AGENT_FILE > /dev/null 2>&1
if [ $( ps -ef | grep ssh-agent | grep -v grep | wc -l ) -eq 0 ]; then
    ssh-agent -t $SSH_KEY_LIFE_TIME_SEC > $SSH_AGENT_FILE
    source $SSH_AGENT_FILE > /dev/null 2>&1
fi

```

# 実際に使われるときにパスフレーズを入力させる設定
- `~/.ssh/config`のサーバー設定に***`AddKeysToAgent yes`***
- `.bashrc`にて`ssh-agent -t sec`をしたのは`~/.ssh/config`には有効時間が設定できなかったため

```conf:.ssh/config
Host my-server
	HostName myhost.mydomain.jp
	User taro	
	IdentityFile ~/.ssh/taro_secret_key
	AddKeysToAgent yes

```

# ログオフの際に`ssh-agent`のプロセスを終了させる。
このままだとログオフしても鍵が保存されたままになってしまうので、
ログオフ時にプロセスを自動で終了させる。

```conf:.bash_logout
ssh-agent -k
```



# 有効時間の前にssh-agentに登録されている鍵を削除する
- 現在、登録されている鍵を一覧
  - `ssh-add -l`
- 特定の鍵を削除
  - `ssh-add -d [key_file_path]`
- 全削除
  - `ssh-add -D`



# [SSH秘密鍵のSSH-AGENTをつかった管理ベストプラクティスを考えてみた](http://mashi.exciton.jp/archives/250)
今更ながらJobSchedulerを使うメモ

Android 8.0以前のバージョンでは、AlarmServiceで定期処理をスケジューリングするのが普通だったんじゃないかと思いますが、

> アプリがフォアグラウンドにある場合、そのアプリはフォアグラウンド サービスとバックグラウンド サービスの両方を制限なく作成して実行できます。 
...
そのウィンドウの終了時に、アプリは アイドル状態 であると見なされます。 システムはこの時点で、アプリがサービスの `Service.stopSelf()` メソッドを呼び出したかのように、アプリのバックグラウンド サービスを停止します。

ってことでまあAlarmServiceで定期処理できなくなったってことです(今更)。

> 多くの場合、アプリではバックグラウンド サービスを `JobScheduler` ジョブに置き換えることができます。

https://developer.android.com/about/versions/oreo/background.html?hl=ja

「`JobScheduler`とな(使い方分かってない)」ってなったわけですが、実はこれ、Android 5.0からあったんですね(知らなんだ)
まあそんな話はさておき、、

# JobSchedulerとは

今更感ある話ですが、`JobScheduler`は、アプリで行う必要があるバックグラウンドでの処理(Job)をなるべくユーザーエクスペリエンスに影響がないように実行しよう、というサービスです。
具体的には、ユーザーが他のこと(たとえばゲーム)を同じ端末上で行っていた場合、バックグラウンドで重い処理をするとパフォーマンスに影響するかもしれないので、ユーザーが端末を使用していないときに処理を行ったりということが簡単に実現できるということになります。

# サンプル

Google samplesにサンプルが上がっていますが、なんとなく使いにくいところがあったのでちょっとカスタマイズしたものを[こちら](https://github.com/KoFuk/android-JobScheduler)に用意しました。

# Try

まず、`android.app.job.JobService`を継承したクラスを作ります。`onStartJob(JobParameters params)`と`onStopJob(JobParameters params)`をオーバーライドする必要があります。`onStartJob`の中に実行したい処理を書いていく形になります。`onStartJob`内でもネットワークの通信は別のスレッドで行う必要があります。
また、Jobと付いているもののServiceなので、Manifestに登録する必要があります。

```xml:AndroidManifest.xml
<service
    android:name=".service.MyJobService"
    android:permission="android.permission.BIND_JOB_SERVICE" />
```

`android:permission="android.permission.BIND_JOB_SERVICE"`というのがないとIllegalArgmentExceptionで死にます。
`android:exported="true"`がGoogleのサンプルにはありましたが、APIドキュメントにもexportしろとは書いていないですし、私が試した範囲では問題なく動作したので必要ないと思います。
Jobを登録するには以下のようにします。

```java
JobInfo info = new JobInfo.Builder(1, new ComponentName(context, MyJobService.class))
        .build();
JobScheduler scheduler = (JobScheduler) getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(info);
```

これだけです。簡単ですね！
`JobInfo.Builder`に分かりにくい項目があったのでメモします。

- setPeriodic(long intervalMillis)  
JobをintervalMillisごとに繰り返します。この指定が15分未満だと強制的に15分にされるので注意が必要です。
また、`setOverrideDeadline`とは両立できません。両方指定すると見事にクラッシュします。

## 1日1回Jobを実行する場合はどういう実装にすればよいかという話

AlarmManagerを使用する場合は`BOOT_COMPLETED`を`BroadcastReceiver`でつらまえていたと思いますが、JonInfoにsetPersistedというのがあるのでこれをtrueにすればOKです。Jobが消えるというのは自分で明示的にキャンセルした場合とアプリをアップデートしたときになるので、`MY_PACKAGE_REPLACED`で再びスケジュールしてやればいいです。
その上で、setPeriodic(1000 * 60 * 60 * 24)を設定すれば1日1回実行できます。

### 追記
どうやらAndroid N からはsetPeriodic(long intervalMillis, long flexMillis)を使う必要があるようです。flexMillisには遅れてもいい時間をミリ秒単位で渡すことになっています。
その際、flexMillsはJobInfo.getMinFlexMillis()で取得される値かintervalMillsの5%の時間のいずれか高い方よりも大きい値にする必要があります。https://developer.android.com/reference/android/app/job/JobInfo.Builder.html#setPeriodic(long,%20long)

## 追記

JobSchedulerやAlarmManagerを素で使おうとするとAPIレベルの差を吸収できるようにしなければならないので面倒くさいです。GoogleがWorkManagerというものを出してくれているので、こちらを使うようにしていくといいんじゃないかと思います。定期処理周りの互換性を確保してくれるライブラリとして、[evernote/android-job](https://github.com/evernote/android-job) などもありますが、「新しいプロジェクトはWorkManagerを使ってね。このライブラリは将来的に非推奨にするよ」と言っています。
ethreumにおける署名検証


##アドレスの生成
ランダムな秘密鍵を元にECDSAを用いて公開鍵を作成。
公開鍵をKeccac-256を用いてハッシュ化し、末尾20バイトを抜き出す。その頭に16進法を表すプレフィックス"0x"をつけることでアドレスを生成する。
一つのアカウントと秘密鍵、公開鍵、アドレスが一対一で対応している。アドレスから公開鍵を作成することや公開鍵から秘密鍵を生成することはできない。

##電子署名
作成者の保証と内容の非改竄性を実現するための仕組み。
署名生成と署名検証（https://ja.wikipedia.org/wiki/%E9%9B%BB%E5%AD%90%E7%BD%B2%E5%90%8D)
![Digital_Signature_diagram_ja.svg.png](https://qiita-image-store.s3.amazonaws.com/0/116240/0568e29b-284f-8e54-6bf3-211a426927ee.png)

##ethereumにおける署名検証

文書とアドレスから署名shaと検証に使うデータv,r,sを作成する

```javascript:signature.js
function signString(text) {
  //文書をハッシュ化
  let sha = '0x' + web3.sha3(text);
  /*アカウントのアドレス（ここではマイナーのアドレス)とハッシュ値を渡して署名(132文字)を作成*/
  let sig = web3.eth.sign(coinbase, sha);
  //プレフィックス"0x"を取り除く
  sig = sig.substr(2, sig.length);
　//前半64文字にプレフィックス"0x"をつける
  let r = '0x' + sig.substr(0, 64);
　//後半64文字にプレフィックス"0x"をつける
  let s = '0x' + sig.substr(64, 64);
　//末尾２文字を１６進法に変換し２７を足す
  let v = web3.toDecimal(sig.substr(128, 2)) + 27;
  return {sha, v, r, s};
}
```

署名からアドレスを復元する

```solidity:test.sol
contract Test {
    function check(bytes32 data, uint8 v, bytes32 r, bytes32 s) constant returns(address) {
      return ecrecover(data, v, r, s);
    }
}
```
検証対象のアドレスと復元したアドレスが一致しているか確認することによって署名を検証する。

##ecrecoverのソースコード

```javascript:ecrecover.js
exports.ecrecover = function (msgHash, v, r, s) {
  //r,sを結合させる
  const signature = Buffer.concat([exports.setLength(r, 32), exports.setLength(s, 32)], 64)
  const recovery = v - 27
  if (recovery !== 0 && recovery !== 1) {
    throw new Error('Invalid signature v value')
  }
  const senderPubKey = secp256k1.recover(msgHash, signature, recovery)
  return secp256k1.publicKeyConvert(senderPubKey, false).slice(1)
}
```

##参考
(https://web3js.readthedocs.io/en/1.0/web3-eth.html)
(https://github.com/ethereumjs/ethereumjs-util/blob/master/index.js)
(https://github.com/ethereum/web3.js/issues/392)
UnityでのCoroutine取り扱いメモ

UnityでCoroutineを利用する際のメモ

# IEnumeratorに参照を入れてコルーチンを一時停止・再開させるとき

* 入れ子呼び出しは再開されない
* WaitForSecondsは内部でカウントが止まらない。

一時停止・再開できるサウンド再生完了コールバック

```csharp:AudioSourceExtention.cs
public static IEnumerator PlayWithCompCallback(this AudioSource audioSource, AudioClip audioClip, float volume = 1f, UnityAction compCallback = null)
{
    audioSource.clip = audioClip;
    audioSource.volume = volume;
    audioSource.Play();
    float timer = 0f;

    //WaitForSecondsを使うとCoroutineを一時停止・再開できなくなるのでwhileで対応//
    while (timer < audioClip.length)
    {
        timer += Time.deltaTime;
        yield return null;
    }

    if (compCallback != null)
    {
        compCallback();
    }
}
```
OmiseGo SDKのエンティティ

# OmiseGo SDK のエンティティ

下記を参考。
https://github.com/omisego/ewallet/blob/develop/docs/design/entities.md

- **Minted Tokens(鋳造されたトークン)**:シンボル(OMG,BTC,USDT)で識別される通貨(ロイヤリティポイント, 暗号通貨, トークン化された法定通貨)。デフォルトでは、ブロックチェーンによって裏付けされていなく、プロバイダーがプロバイダーの残高とユーザの残高間、または口座間でやり取りをする内部的な転送のみ作成することができる。もし、プロバイダーがトークンの裏付けが必要なら、ブロックチェーン上のスマートコントラクトのアドレスはトークンの詳細をユニークに識別できるよう定義する必要がある。

- **Mint(鋳造)**:トークンが流通されるたびに発生するレコード

- **Account(口座)**:ユーザと残高をグループ化されたもの。 ビジネスの要望に応じて、プロバイダーの管理者によって、論理的にグループ化される。e.g. 各商品のブランドのためのアカウント、各お店の視点、各セールスチーム、各リージョンオペレーションなどがいえる。

- **Users(ユーザ)**:ユーザは、通常のユーザ、またはスタッフユーザ(管理者)となることができる。一つ目は、プロバイダーによってeWalletのデータベースに追加され作られたエンドユーザ。二つ目のケースでは、OmiseGoの管理者パネルにアクセスできるユーザ。

- **Balances(残高)**:アドレスによって識別された残高は、グループトランザクションまたは、金銭を持つために使われる。ユーザは、必要ならば、ひとつ以上の残高をもつことができ、残高は異なる通貨を持つことができる。もっと詳しい情報は個々を参照。(https://github.com/omisego/ewallet/blob/develop/docs/balances.md)


- **Transactions(トランザクション)**:
トランザクションは、二つの残高の値の交換である。トランザクションは、ローカル台帳に複式簿記で保存される。複式簿記は、入力されると、貸方/借方勘定がそれとリンクされる。「すべての貸方の合計」ー「すべての借方の合計」が、0となる。「すべての貸方の合計」ー「すべての借方の合計」をまとめたうえで、トークンはアドレスの残高に付与されることになる。

- **Access Key(アクセスキー)**:プロバイダーのサーバアプリケーションが、eWalletとやり取りするために使われる。キーペア。このコンビネーションは、タイミングベースアタックを避けるために、一つのキーの代わりとして、ここでは使われる。

- **Secret Key(シークレットキー)**:パスワードとして利用されるシークレットキー、リクエストを承認するために、プロバイダーのバックエンドアプリケーションから送られる。

- **API key(APIキー)**:eWalletに対して、重要ではないAPIコールを実行するためのモバイルアプリケーションから送られる保存のきかないキー。

- **Access token(アクセストークン)**:eWalletが生成する一次的なトークンで、プロバイダーのバックエンドアプリケーションを介してクライアントに返る。APIキーとともに、eWalletに重要でないAPIコールを実行するときに使われる。
例外

#例外の種類

##例外の種類
エラーの種類は大きく以下の3つ。
1.文法エラー
2.実行時エラー
3.論理エラー

###1.文法エラー
・文法の誤りによるコンパイルミス
・例はセミコロン忘れ、スペルミスなど
・コンパイルされない

###2.実行時エラー
・実行中に不具合が発生することで発生するエラー
・例はあるはずのファイルが削除される、あるはずの値がnull値になっているなど
・コンパイルされる

###3.論理エラー
・構文ミスにより、実行結果が意図していたものと異なること
・例は電卓ソフトで3＋5が35と出力されるなど
・コンパイルされる

###まとめると・・・
３種類あるが
・**「2.実行時エラー」に対しては、エラー発生時を想定したコードを記述して対応！**
・**「1.文法エラー」・「3.論理エラー」は、元々のコードを修正して対応！**

##例外を表すクラスとその種類
・エラー発生状況毎にクラスが用意されており、継承階層で構成されている
・クラス毎の意味・継承階層図は以下の通り

<img width="888" alt="スクリーンショット 2018-03-05 9.38.13.png" src="https://qiita-image-store.s3.amazonaws.com/0/229025/b82bddb0-2f7b-0f95-7eb9-f7ab8448142f.png">

###まとめると・・・
**`Exception`に対しては、エラー発生時に対応出来るようなコードを記述する必要がある**

#例外の処理

##例外の調べ方
例外はJavaAPIに記載されている
###例
<img width="1381" alt="スクリーンショット 2018-03-05 14.23.18.png" src="https://qiita-image-store.s3.amazonaws.com/0/229025/e749a3d2-22be-c4ee-39a9-9eaafdd30a05.png">


##例外処理の種類
例外処理の種類は大きく以下の２つ。
1.catch構文
2.throws構文

##1.catch構文

###catch構文とは
例外が発生した場合の処理を、自身のメソッド内に記述する際に使用する

###使用方法
```java
try {
　　本来の処理
}catch (例外クラス 変数名) {
　　例外が発生した場合の処理
}finally{
　　例外があってもなうても必ず実行する処理
}
```
[処理の流れ]
①`try`メソッド内に処理を記述し、例外が発生した場合は、エラークラスのインスタンスを`catch`に渡す
②`catch(例外クラス 変数名)` の`(例外クラス 変数名)`で例外インスタンスを受け取る。
　メソッド内には受け取った後の処理を記述する。
③`finally`では、ファイルを閉じる・切断などの処理を実施する。

###例外インスタンスが持つ情報
####①例外情報の解説文
いわゆる、エラーメッセージ。`String getMessage()`で表示。
####②スタックトレース
JVMがプログラムのメソッドをどのような順序で呼び出し、どこで例外が発生したか。
`void printStackTrace`で内容表示。
###例
```java
	public static void main (String[] args) {
		FileWriter fw = null;
		try {
			fw = new FileWriter("date.txt");//インスタンスの生成
			fw.write("hellow");//中にhellowと書き込む
		}catch (Exception e) {
			System.out.println("何らかの例外が発生しました");
		}finally{
			try {
				fw.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}
```
###補足
・`catch (Exception e)`は`Exception`の子孫の、例外インスタンスなら全て受け取るという意味
・FileWriterクラスについては以下参照
　https://docs.oracle.com/javase/jp/6/api/java/io/FileWriter.html
　https://www.sejuku.net/blog/20657

###`finaly`を省略した書き方
```java
try (
　　ファイルインスタンスの生成
){
　　ファイルに対する処理
}catch{
}
```
()内で開かれた、ファイルやデータベースは、処理終了後に自動で`close`メソッドを呼び出してくれる。

##2.throws構文

###throws構文とは
例外が発生した場合の処理を、呼び出し元のメソッドにお願いする際に記述する方法

###使用方法
```java
メソッド名　　throws 例外クラス名1,例外クラス名2 
```
[補足]
・`throws`を宣言する事で、`try catch文`の記述が義務では無くなる
・呼び出し元メソッドは、`try catch文`を記述する必要がある

#例外を発生させる方法

###考え方
発生した例外を受け取るだけでなく、例外を通知する事が可能

###使用方法
```java
throw 例外インスタンス名
```
###例
```java
//mainメソッド
public class Main {
	public static void main(String[] args) {
		Person person = new Person();
		person.setAge(-100);

	}
}
```

```java
//Personクラス
public class Person {
	int age;
	public void setAge(int age) {
		if(age<0) {
			throw new IllegalArgumentException("年齢は正の数を指定すべきです。");
		}
		this.age = age;
	}


}
```

```java
//出力結果
Exception in thread "main" java.lang.IllegalArgumentException: 年齢は正の数を指定すべきです。
	at Java15.Person.setAge(Person.java:7)
	at Java15.Main.main(Main.java:6)
```


・IllegalArgumentExceptionクラスについては以下参照
https://docs.oracle.com/javase/jp/7/api/
ユーザーにJSONの編集をさせたい時に使えるJSONエディタ

こんにちは、レガシーなプロジェクトが多く、やっとこさOSSの世界にアンテナ張り出した途端、目からマグロの鱗が落ちまくってる20代のおっさんです。

### JSON_editorを見つけた
以前もjQueryUIで同じようなものを作ったのですが、もっと華麗にしたいので、新しく考え、[Vuejsでテーブルをクリックすると、モーダルで編集すると言うやつ](https://qiita.com/blue-ossan/items/429c0eb7915b7410bc7f)を作ろうとしましたが、色々と課題も多く、工数がかかりそうなので、やっぱり別の技術を探索したところ、Githubに[jdorn/json-editor](https://github.com/jdorn/json-editor)というのを見つけました。

JSON Schemaだけ作っちゃえば、後は勝手にやってくれちゃうと言うスグレモノ。JSONで色々画面入力やるなら、かなり良さげ。


### ファーストタッチ
ザクッと使った結果、使い物にはなるみたいで、圧倒的にメリットも大きいようなので、日本語化ファイルを作って、動くようにしてみました。もちろん、見つけていないだけで、他にも似たようなものはあるかもしれません。

欠点は、エンドユーザーには多分使えないから、普通にPCが触れる人向けってことでしょうか。今回は社内向けですのでOKです。社内向けに使えば、他の欠点も見えてくるでしょう。そうすれば、自分でゴニョゴニョ作るか、プルリクするか、でしょう。

### 使ってみた

とりあえず、使いたいWebサイトのスクリプトフォルダにでも置き、インポートします。そんなのはエンジニアなら勝手にやってください。

#### スキーマを作る
json schemaが必要ですので、作る必要があります。
.NETで使うなら、JSON.NETのメソッドを使うと手っ取り早いです。もちろんNameやRequiredを設定して置くと便利ね。
配列の必須やらの細かい設定とかは足りないみたいなので、スキーマにしてからテキストで調整するといいかも。
こんなメソッドを作って、JSONスキーマにしたいクラスを渡すと、一発ですね。

```CSharp:こんなメソッド
        public static string GenerateSchema(Type type)
        {

            var generator = new JSchemaGenerator();
            generator.ContractResolver = new CamelCasePropertyNamesContractResolver();

            JSchema schema = generator.Generate(type);

            return schema.ToString();
        }
```

#### 埋め込む

てきとーなDivなりを作ります。
それをめがけて、json_editorを蹴りましょう。ザクッと使えそうな感じの設定は、おおよそこれだけで良いようです。
今回はBootstrap3のテーマです。~~歌います。~~自己流でテンプレートとかCSSもアレンジできるようなので、見やすく使いやすくなるか、ちょっと弄ってみます。

```javascript:♪～

        var editor = new JSONEditor(jsonEditEl, {
            theme: 'bootstrap3',
            schema: "ここにスキーマ",

            disable_collapse: true,
            disable_array_reorder: true,
            display_required_only: true,
            startval: "ここに初期値のJSON"),
        });
```
細かい設定はGithubを読んでくださいね。

できました。

## 参考サイト
[JSONスキーマのJSONスキーマを作って簡易作成フォームにしてしまう [jdorn/json-editor]](https://qiita.com/RAWSEQ/items/38c78eec83e0f9be6622)
[JSON Editor – JSON Schemaから入力検証つきフォーム生成](https://www.moongift.jp/2014/06/json-editor-json-schema%E3%81%8B%E3%82%89%E5%85%A5%E5%8A%9B%E6%A4%9C%E8%A8%BC%E3%81%A4%E3%81%8D%E3%83%95%E3%82%A9%E3%83%BC%E3%83%A0%E7%94%9F%E6%88%90-2/)
決済stripe早見表 [随時更新]

作りきっかけになったのは、Stripeは、多様なことができるのでどこにどのドキュメントが落ちているかわからないためにまとめることにしました。

さっそく、やってみたいと思います。


### テストカードとトークンがあるページ
https://stripe.com/docs/testing

自分がよくつかうのはこのtest token

```
number: ‘4242424242424242’,
exp_month: 12,
exp_year: 2018,
cvc: ‘314’
```

### quick startページ


https://stripe.com/docs/quickstart

これで安全なtokenが作れそうだ

```
<form action="your-server-side-code" method="POST">
  <script
    src="https://checkout.stripe.com/checkout.js" class="stripe-button"
    data-key="stripe token"
    data-amount="999"
    data-name="company name"
    data-description="Example charge"
    data-image="https://stripe.com/img/documentation/checkout/marketplace.png"
    data-locale="auto"
    data-currency="jpy">
  </script>
</form>
```
例外一覧

```BaseException
 +-- SystemExit
 +-- KeyboardInterrupt
 +-- GeneratorExit
 +-- Exception
      +-- StopIteration
      +-- StandardError
      |    +-- BufferError
      |    +-- ArithmeticError
      |    |    +-- FloatingPointError
      |    |    +-- OverflowError
      |    |    +-- ZeroDivisionError
      |    +-- AssertionError
      |    +-- AttributeError
      |    +-- EnvironmentError
      |    |    +-- IOError
      |    |    +-- OSError
      |    |         +-- WindowsError (Windows)
      |    |         +-- VMSError (VMS)
      |    +-- EOFError
      |    +-- ImportError
      |    +-- LookupError
      |    |    +-- IndexError
      |    |    +-- KeyError
      |    +-- MemoryError
      |    +-- NameError
      |    |    +-- UnboundLocalError
      |    +-- ReferenceError
      |    +-- RuntimeError
      |    |    +-- NotImplementedError
      |    +-- SyntaxError
      |    |    +-- IndentationError
      |    |         +-- TabError
      |    +-- SystemError
      |    +-- TypeError
      |    +-- ValueError
      |         +-- UnicodeError
      |              +-- UnicodeDecodeError
      |              +-- UnicodeEncodeError
      |              +-- UnicodeTranslateError
      +-- Warning
           +-- DeprecationWarning
           +-- PendingDeprecationWarning
           +-- RuntimeWarning
           +-- SyntaxWarning
           +-- UserWarning
           +-- FutureWarning
       +-- ImportWarning
       +-- UnicodeWarning
       +-- BytesWarning
```
MySQL Handlers 

|項目  |説目  |
|---|---|
|Handler Write|insert 回数|
|Handler Update|update 回数|
|Handler Delete|delete 回数|
|Handler Read First  | テーブルやインデックスの全件検索（スキャン）の際には、まず最初に先頭レコードの取得を行います。その回数が Read First です。チューニング必要。|
|Handler Read Key |インデックスを使ってさらに範囲指定の効果が効いている場合の回数。少ない場合にインデックスのチューニング必要。|
|Handler Read Next  |キー値に基づいて行を特定した後、後続の行を読んだ回数です。範囲指定のインデックススキャンが発生した場合に増える。|
|Handler Read Prev  |内容としては Next  と同じ。その前の行を呼んだ回数。 |
|Handler Read Rnd  |InnoDB でプライマリキーの値を指定して1行データを読み込んだ回数。ソートが多い場合にこの値が増える。チューニング必要。 |
|Handler Read Rnd Next  | データファイルでの次のレコードを呼んだ回数。テーブルスキャンが実行されると増える。チューニング必要。 |
俺言語 その16

#概要

俺言語をやってみた。
avrにアセンブラで実装してみた。
レインボーLEDテープ光らせてみた。

#環境

avr studio 4
attiny85 1mhz
tera term
usb-serial

#動作動画
https://www.youtube.com/watch?v=OYlx4hktC14

#回路図

![image](https://qiita-image-store.s3.amazonaws.com/0/18104/d23605cb-9e2a-ca17-a61c-26d409e58580.png)

#サンプルコード

```
10 r=30
20 @=1
30 o=14
40 @=1
50 o=10
60 @=1
70 o=2
80 @=1
90 o=30
100 #=20
```

以上。
OmiseGo SDKの環境変数

# OmiseGo SDKの環境変数

OmiseGo SDKで現在利用できる環境変数。
下記を参照。
https://github.com/omisego/ewallet/blob/develop/docs/setup/env.md

## 一般

- `MIX_ENV`: どのアプリケーションの環境で走るかを指定。`prod`はプロダクション用
- `BASE_URL`: ベースURLを指定
- `PORT`: アプリケーションのリッスンPORTを指定。
- `EWALET_SECRET_KEY`:データベースのデータを暗号化する暗号鍵
- `LOCAL_LEDGER_SECRET_KEY`:データベースのデータを暗号化する暗号鍵

Elixirを使って、下記の方法で秘密鍵を生成できる。

```
$ mix run -e "IO.puts Salty.SecretBox.generate_key()"
8I_xIED7p7ruxxM1vNiWzsud3DALk0cnpcAncC2YyMs
```

## データベース

eWalletは、二つのDBにアクセス必要があり、一つは、eWallet自身、もうひとつはローカル台帳のために使われる。
下記の環境変数の設定が必要。

- `DATABASE_URL`
- `LOCAL_LEDGER_DATABASE_URL`

## エラーレポート

いまのところ、eWalletは、Sentryのみ対応している。下記の環境変数にDSNを明記することができる。
※Sentryは、Rubyで使われるエラーログ収集に使うツール

- `SENTRY_DSN`

## 残高キャッシュ


ローカル台帳は、計算スピードを高めるために、残高のキャッシュメカニズムを提供している。(100万件のトランザクションがある場合など)
この機能を有効にするために、`BALANCE_CACHING_FREQUENCY`変数を設定し、それを介して、正しいcronスケジュールを設定する。
これは、完全に任意で、この設定なしでも、アプリケーションはうまく動く。

- `BALANCE_CACHING_FREQUENCY`:正しいcronスケジュール

#### 例

- 毎分: `"* * * * *"`
- 毎日午前2時: `"0 2 * * *"`
- 毎週金曜午前5時: `"0 5 * * 5"`

この機能が有効になっている場合、キャッシュストラテジーも指定することができる。

- `BALANCE_CACHING_STRATEGY`:もし新しいキャッシュ残高計算に、前回のキャッシュを使うのか、一からすべて再計算させるかを指定。

下記の戦略が可能。

- `since_beginning`:最初の時刻から再計算。
- `since_last_cached`:最後のキャッシュ残高を利用、それから発生した残高を追加し、新しいキャッシュ残高の結果として保存。

## Eメール

パスワードを忘れまたは管理者を招待するためのEメールを有効にするため、下記の設定をする必要がある。

- `SMTP_HOST`:Eメールサーバ
- `SMTP_PORT`:Eメールサーバポート
- `SMTP_USER`:Eメールユーザ
- `SMTP_PASSWORD`:Eメールパスワード

## ファイルアップロード

- `FILE_STORAGE_ADAPTER`: (local|aws|gcs,デフォルトはローカル)


ファイルアップロード機能(プロファイルや口座のロゴ)のため、環境変数の指定が必要となる。

#### ローカルファイルストレージ

特にする必要はない、`public/upload`の中にファイルが保存される。

#### Amazon S3

- `AWS_BUCKET`: S3バケット名
- `AWS_REGION`: バケットのリージョン
- `AWS_ACCESS_KEY_ID`: AWSアクセスキー
- `AWS_SECRET_ACCESS_KEY`: AWSシークレットキー

#### Google Cloud Storage

- `GCS_BUCKET`: GCSバケット
- `GCS_CREDENTIALS`: GCS証明書を含むJSON
RIGOL DS1054Z

安いオシロスコープ RIGOL DS1054


買ったのは2017年9月。その時は5万円ちょっと。それから半年、少し値上がりしているみたい


# 選定理由

いろいろなアドバイスをいただきました

- まともなのは100万円ぐらいするので、中古でヤフオク等で数万で手に入れるのがいい
- やっぱサンプルはアナログでも100Mhzデジタルだと1G～500Mhzは欲しい
- コンパクトなものがいい
- テクトロがいい

ただ今回は電子工作入門者への共有情報をつくる前提で、
新品で入手しやすいものがいいなと考え RIGOL DS1054Z にしました。

2015年ぐらいのモデルですが、ユーザの使いこなし情報も結構蓄積されて
ファームウェアをいじってのHACKとかもできそう? という期待もあります。

## 他機種との比較

### USB接続のやつとかコンパクトなやつ

いろいろでていて、安いです。しかしながら今まで DSO Nano を持っていたのですが、いざって時にあれどこにいったかな・・・？　ということになるのですよね。

### Tektronix TBS1052B

同価格帯でテクトロが購入できます。いろんな違いがありますが、最も大きな違いは RIGOL DS1054Z が 4ch に対し、こちらは2chが大きな違いです。ブランド選ぶならこちらがいいかな。今回は、LinuxのソフトがRIGOLで公開されていたのでそちらを選びました。


# どこから買う？

国内のルートで、Webや店頭で買えるのは Amazon.jpと秋葉原の計測器ランド。
輸入で格安に出来ないかなと思ったが当時は送料を含めるとあまり変わらなかったのでAmazon.jpで国内正規品を購入。ただ国内の価格や輸入チャンネルの状況も刻々変わるのでどれがいいかは一概には言えないでしょう。

# 拡張パック
計測器ランドの2018/3末までのキャンペーンで1000Zシリーズを買うと下記がついてくるというので少し調べた。

||||
|:---|:---|:---|
| AT-DS1000Z|拡張トリガ|標準価格 28,000円 |
|SA-DS1000Z|シリアル解析|標準価格 25,800円 |
|MEM-DS1000Z|レコード長拡張|標準価格 28,900円 |
|REC-DS1000Z|波形レコード＆プレイ・バック|標準価格 21,800円 |

これらの拡張パックはどうやら解除キーを購入して解除するらしい。

また、Hackして上位機種 DS1104Z のように動かすこともできるらしい。

# 使ってみて

ファンがついていて結構音がする。
音は別にいいけど給排気でホコリが内部に貯まるのではないかな？

# Linuxとの連携

ユーティリティはメーカによって公開されているが、OSS発のソフトもちらほらある。
そのうちの１つ。


DS1054Z_screen_capture-master
LAN経由でスクリーンキャプチャを取るpythonスクリプト。
https://github.com/RoGeorge/DS1054Z_screen_capture

ダウンロードして展開、

python OscScreenGrabLAN.py png 192.168.42.12

でPNGファイルが取得できる。

![DS1054Z_DS1ZA192913288_2018-03-05_13.40.49.png](https://qiita-image-store.s3.amazonaws.com/0/139524/05005cc1-3a88-98c2-0230-b9c73de0848c.png)

Ubuntu 16.04 AMD64 で動かしたけれども python なので Linux に限らずどれでも動くはず。
Microsoft アカウント > おかえりなさい > サインイン > 無限ループ > 対処

```
Microsoft Edge 41.16299.248.0
```

### 症状

2018年3月5日現在の状況です。

www.office.com にサインインしようとしている。

一度サインインした後に以下のような画面が表示される。
サインインがもう一度必要なのだろうか？

> おかえりなさい
...
> [サインイン]


サインインボタンを押すと上記の画面に戻る (無限ループ)。

### 対処

上部メニューの「マイアカウント」をクリックする。

サインイン画面が表示される。
Microsoft Teams > UI > ファイルへの到達 | ブラウザの横幅により使いにくくなるUI | docx: 漢字変換が失敗する

```txt:動作環境
Windows 10 Pro (64bit) Fall Creators Update適用済
Google Chrome バージョン: 64.0.3282.186（Official Build） （64 ビット）
```

### 展開メニューに隠されるリンク

Microsoft TeamsのUIで使いにくかった部分。

チームのファイルへの到達方法が分からなかった。

1. 左メニューのチームを選択
2. チーム以下の項目を選択
3. 左メニューの展開をやめる
    - 例: 展開以外の部分をクリック
4. 左上の「ファイル」を選択


手順2の段階で「ファイル」が隠れている。
開発している人はdogfoodingをしていないのだろう。

「会話」「ファイル」「Wiki」「＋」の表示は右側に配置するとUIの問題は解決するだろう。

### ブラウザの横幅により使いにくくなるUI
(追記 2018/03/05)

ブラウザの横幅が960ピクセルよりも小さいときに上記のUIの問題が発生するようだ。

- 横幅が960ピクセルよりも小さいとき
    - 左メニューは右ペインの上に表示される
        - 「会話」「ファイル」「Wiki」「＋」の表示が隠れる
- 横幅が960ピクセル以上のとき
    - 左メニューと右ペインは重ならず表示される

横幅が小さい環境でどう表示すればよいUIになるだろうか。


### 他のバグ

Teamsにおいてはdocx編集時に漢字変換が失敗する(最初の文字を落とすバグ)。
前処理で精度は上がるのか？~後半～

[前半からの続き](https://qiita.com/umesaku/items/9f93973287b830a6d1b7)
前処理の目的のひとつに、精度向上があるようです。
今回は実際に試してみました。

#cancer.datasetsを使って試しみた
Pythonではじめる機械学習　P.136
cancer.datasetsの中身は[こちら](https://qiita.com/umesaku/items/9f93973287b830a6d1b7)を参照ください。

```ruby:qiita.rb
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.svm import SVC
from sklearn.metrics import accuracy_score

#わかりやすようにX,yで代替する。
X=cancer.data
y=cancer.target

#train_test_splitで分割
X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0)

svm=SVC(C=100)
svm.fit(X_train,y_train)
print("Test set accuracy:{:.2f}".format(svm.score(X_test,y_test)))
```
rawデータのTest set accuracyは0.63。

##では、MinMaxScaleから。
```ruby:qiita.rb
scaler=MinMaxScaler()
scaler.fit(X_train)
X_train_scaled=scaler.transform(X_train)
X_test_scaled=scaler.transform(X_test)
svm.fit(X_train_scaled,y_train)
print("Scaled test set accuray:{:.2f}".format(svm.score(X_test_scaled,y_test)))
```
MinMaxScaler処理でのTest set accuracyは0.97！

こんな上がるものなのか？？すごい！
ほかも同じか？たまたまMinMaxScalerだけか？

##次はStandardScalerで試しみよう！
```ruby:qiita.rb
from sklearn.preprocessing import StandardScaler
scaler=StandardScaler()
scaler.fit(X_train)
X_train_scaled=scaler.transform(X_train)
X_test_scaled=scaler.transform(X_test)
svm.fit(X_train_scaled,y_train)
print("Scaled test set accuray:{:.2f}".format(svm.score(X_test_scaled,y_test)))
```
StandardScaler処理でのTest set accuracyは0.96！

う~ん、すごいなー。やっぱり効果があるのかなぁー。

##続いて、RobustScalerを。

```ruby:qiita.rb
from sklearn.preprocessing import RobustScaler
scaler=RobustScaler()
scaler.fit(X_train)
```
ちなみにRobustScalerは中央値と四分位を取るので下記アウトプットが出てきます。
RobustScaler(copy=True, quantile_range=(25.0, 75.0), with_centering=True,
       with_scaling=True)

```ruby:qiita.rb
X_train_scaled=scaler.transform(X_train)
X_test_scaled=scaler.transform(X_test)
svm.fit(X_train_scaled,y_train)
print("Scaled test set accuray:{:.2f}".format(svm.score(X_test_scaled,y_test)))
```
RobustScaler処理でのTest set accuracyは0.95！

##最後に、Normalizerを。
やり方はこれまでと全く同じ。

```ruby:qiita.rb
from sklearn.preprocessing import Normalizer
scaler=Normalizer()
scaler.fit(X_train)
```
こんなアプトプットが出ました。Normalizer(copy=True, norm='l2')
norm＝12の意味は後で調べるとして、先に進もう。

```ruby:qiita.rb
X_train_scaled=scaler.transform(X_train)
X_test_scaled=scaler.transform(X_test)
svm.fit(X_train_scaled,y_train)
print("Scaled test set accuacy:{:.2f}".format(svm.score(X_test_scaled,y_test)))
```
Normalizer処理でのTest set accuracyは0.90！

結果の一覧：
このように、前処理を行った方が43%～54％も精度は向上するようです。特に前者3つは非常に高くなっていますね。


|test method   |test accuray|increase rate|
|:-----------  |:----------:|:----------:|
|raw data      |   0.63     |100%|
|MinMaxScale   |   0.97     |154%|
|StandardScaler|   0.96     |152%|
|RobustScaler  |   0.95     |151%|
|Normalizer    |   0.90     |143%|


でも、これってなぜなんだろう？理由がわからないから素直に喜べない（泣
もっと言えば、他のデータでも同様のことが言えるのかなー、という疑問も。
ということで、bostonデータあたりを使って特別編をやろうと思います（いつか）
【Rails5.1】ローカルのPumaが起動しない場合の対処法

# はじめに
久々に起動したローカルのPumaが起動しなかったのでメモ。

## エラー内容
```bash
$ bundle exec rails s -b 0.0.0.0
=> Booting Puma
=> Rails 5.1.1 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.9.1 (ruby 2.4.1-p111), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Exiting
/home/vagrant/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/puma-3.9.1/lib/puma/binder.rb:269:in `initialize': Address already in use - bind(2) for "0.0.0.0" port 3000 (Errno::EADDRINUSE)
```

## 対処法
- 3000ポートを使っているプロセスがないか確認します。

```bash
$ ps -aux | grep puma
vagrant   6334  3.5 21.7 1550588 445276 ?      Sl   09:48   1:44 puma 3.9.1 (tcp://0.0.0.0:3000)
vagrant   7147  0.0  0.0  15524   940 pts/19   S+   10:37   0:00 grep --color=auto puma
```

プロセスをkillします。

```bash
$ sudo kill -9 6334
$ ps -aux | grep puma
vagrant   7160  0.0  0.0  15524  1036 pts/19   S+   10:37   0:00 grep --color=auto puma
```

## puma再起動
無事に起動できました。

```bash
$ bundle exec rails s -b 0.0.0.0
=> Booting Puma
=> Rails 5.1.1 application starting in development on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
Puma starting in single mode...
* Version 3.9.1 (ruby 2.4.1-p111), codename: Private Caller
* Min threads: 5, max threads: 5
* Environment: development
* Listening on tcp://0.0.0.0:3000
Use Ctrl-C to stop
```
Webpackerで管理しているコンテンツからの参照パスにサブディレクトリを含める手順

# はじめに

デプロイ後のアプリのルートが `http://ホスト名/subdir` となっているとき `/subdir` が webpacker で管理しているファイルからの参照URLに含まれていません。

以下は、試行錯誤して対応した記録です。

# 環境

- gem
 - rails 5.1.5
 - webpacker 3.2.0

- npm
  - @rails/webpacker 3.2.0
  - webpack-dev-server 2.9.7
  - webpack 3.11.0

# どこが問題か？

- https://github.com/rails/webpacker/blob/3cd48fc74a6e12216c3644c3cb5f6d4fe46c1ac5/package/config.js#L41
で、最終的に outputPath を publicPath として上書きしているところ。ドメイン直下にデプロイする前提になっちゃってる。
- config/webpacker.yml で publicPath が考慮されていないところ。

# 対応した手順

対応と言ってもやっつけですが、デフォルトの設定 https://github.com/rails/webpacker/blob/master/package/rules/file.js を参考にしつつ、
`config/webpack/loaders/file.js` を以下の内容で作成します。

```js:config/webpack/loaders/file.js
const publicPath = {
  production:  '/subdir/packs/', // ← 本番のときだけサブディレクトリを指定
  development: '/packs/',
  test:        '/packs-test/',
}[process.env.NODE_ENV]

module.exports = {
  test: /\.(jpg|jpeg|png|gif|tiff|ico|svg|eot|otf|ttf|woff|woff2)$/i,
  use: [
    {
      loader: 'file-loader',
      options: {
        publicPath: publicPath,
        outputPath: 'files/',
        name: '[name]-[hash].[ext]',
      },
    },
  ],
}
```

もし wav ファイルなどを import している場合は test のところの正規表現に追加しておきます。
test じゃなくて exclude の形で書く方法もありますが gihtub での最近の修正 https://github.com/rails/webpacker/pull/1196/files#diff-5738d5d73471ec5cb82aa72024b3d794R5 を見ると test の形で書いた方が良いようです。

で、いちばん重要なのは production のとき publicPath を `/subdir/packs/` にしておくところです。

`/packs/` など config/webpacker.yml と内容が重複している箇所がありますが、DRY にしようとするとさらに複雑化するので気にしないことにします。

続いて、設定を有効にするため以下を `config/webpack/environment.js` の `module.exports = environment` より前に追記します。

```js:config/webpack/environment.js
const file = require('./loaders/file')
environment.loaders.append('file', file)
```
これ、 `node_modules/@rails/webpacker/package/rules/file.js` の方で定義しているのと干渉するのでは？ と心配するかもしれませんがキーの 'file' が衝突すると既存の設定を破棄するので問題ありません。

次にデプロイして確認するのはしんどいので開発環境で確認します。

確認しやすいように次のようなファイルへの参照がある**小さな**ファイルを作っておきます。

```sass:app/javascript/packs/foo.sass
body
  background-image: url(path/to/rails.png)
```

あとは `rails webpacker:compile` の出力を確認します。

1. RAILS_ENV=production rails assets:clobber webpacker:compile を実行
2. public/packs/foo-xxxxxxxx.css のなかの参照に /subdir が含まれているか確認
3. public/packs/files/rails-xxxxxxxx.png があるか確認

# 今後はもっと簡単になりそう

2018-03-05 の時点で8日前に、Rails 側が見ている環境変数 RAILS_RELATIVE_URL_ROOT の値を webpacker で参照する予定の **WEBPACKER_RELATIVE_URL_ROOT** に渡すという PR https://github.com/rails/webpacker/pull/1236 があったので、そのうちもっと簡単になりそうです。
辞書順に数を並べる


## 第１版
6m20.857s, `-fopenmp`で5m26.862sでした.

```cpp:tyama_henae22.cpp
//https://qiita.com/Nabetani/items/99e38a39165e1905b415
//http://nabetani.sakura.ne.jp/hena/orde22numord/
#pragma GCC optimize("O3")
#pragma GCC target("avx")

#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;

#if _OPENMP
#include <parallel/algorithm>
#endif

void convert(vector<pair<vector<char>,int>>&v,int i,int m,int b){
	vector<char>v0;
	int n=i+m;
	for(;n;){
		v0.push_back(n%b);
		n/=b;
	}
	reverse(v0.begin(),v0.end());
	v[i].first=v0;
	v[i].second=i+m;
}

int main(){
	int m,n,b,x;
	for(;~scanf("%d,%d,%d,%d",&m,&n,&b,&x);){
		int siz=n-m+1,i;
		vector<pair<vector<char>,int>>v(siz);
#pragma omp parallel for
		for(i=0;i<siz;i++){
			convert(v,i,m,b);
		}
#if _OPENMP
		__gnu_parallel::sort(
#else
		sort(
#endif
			v.begin(),v.end()
		);
		printf("%d\n",v[x-1].second);
		fflush(stdout);
	}
}
```

## 第２版
[angelさんの答案](https://qiita.com/Nabetani/items/99e38a39165e1905b415#comment-28ff56b472c09d325ab6)を見て、ビット並列すべきと思い直した。OpenMPで73秒。

・変数kは、左埋めにするために掛けるべき数。
・例の10:3と100:9について、100:3と読み替えてもpairでのソートであれば問題ない。

```cpp:tyama_henae22_mod.cpp
//https://qiita.com/Nabetani/items/99e38a39165e1905b415
//http://nabetani.sakura.ne.jp/hena/orde22numord/
#pragma GCC optimize("O3")
#pragma GCC target("avx")

#include <vector>
#include <algorithm>
#include <cstdio>
using namespace std;

#if _OPENMP
#include <parallel/algorithm>
#endif

void convert(vector<pair<long long,int>>&v,int i,int m,int b,long long k){
	int n=i+m;
	for(;n;n/=b)k/=b;
	v[i].first=(i+m)*k;
	v[i].second=i+m;
}

int main(){
	int m,n,b,x;
	for(;~scanf("%d,%d,%d,%d",&m,&n,&b,&x);){
		int siz=n-m+1,i;
		long long k=1;
		for(;k<=n;k*=b);
		vector<pair<long long,int>>v(siz);
#pragma omp parallel for
		for(i=0;i<siz;i++){
			convert(v,i,m,b,k);
		}
#if _OPENMP
		__gnu_parallel::sort(
#else
		sort(
#endif
			v.begin(),v.end()
		);
		printf("%d\n",v[x-1].second);
		fflush(stdout);
	}
}
```
マルチシグと秘密共有の違い

よく混同されるみたいなので書いておきます

# シャミアの秘密共有法（SSSS）

秘密そのものを分割して保管する
分割する際に分割個数と復元に必要な鍵の数を決める
指定した鍵の数が揃えば完全な秘密が手に入る
保管は分散されるので比較的安全だが、複合時に必ず誰かが完全な秘密を知る中央集権的なリスクがある

```:秘密の中身
Open Sesami
```

```:3/6で分割した秘密
1-b27dc2acc980b1b44d963e
2-4f181c26ab4c578d9a9a5a
3-c3140bdc37ce17e0ba13f9
4-7965dda0b4b7274a584d9c
5-f569ca5a2835672778c42d
6-080c14d04af9811eafc86d
```

以下のURLで実験できます
https://ebixio.com/ssss.html

秘密から分割した鍵を作成するので当然あとから持ち主を変更することはできない

# マルチシグ

前提条件として電子署名で契約を執行するための仕組で運用されることが必須

複数の秘密鍵を用意し、それぞれ公開鍵を作成する
全ての公開鍵と必要な鍵の数を事前に決定する

秘密鍵を保有する承認者には執行内容が書かれた契約書が回覧される

契約書に問題がない場合には承認者が電子署名をつけて他の承認者へ渡す。

必要な電子署名の数が揃った段階で契約書を完成とする。

承認者同士の秘密鍵を他の承認者が知る必要がないため中央集権的なリスクがない

ビットコインなどのutxoベースの場合にはスクリプトの式に公開鍵と必要な鍵の数が組み込まれる（後から承認者の変更が出来ない）

リップルなどのaccountベースの場合には公開台帳に公開鍵と必要な鍵の数が記録される（後から承認者の変更ができる）

```:マルチシグ2/3の設定
公開鍵１
公開鍵２
公開鍵３
署名は２つ
```

```:契約書
Aさんに鉛筆の代価として１００円支払う
```

```:署名済み契約書
Aさんに鉛筆の代価として１００円支払う
秘密鍵１による署名
秘密鍵３による署名
```

# 応用

マルチシグの秘密鍵の一つをssssを用いて分割するのはありうる
Node単体テスト 最初の一歩

Nodeで最低限のテストができるようにするよ。何も知らなくても15分くらいあればテストの最初の一歩をふみだせるように記事を書いたよ。

# 概要

- `npm test` でテストが走るように設定
- テストコード作成

# Step#01 初期設定

`~/letstest` をプロジェクトディレクトリにしよう。配下に`test`ディレクトリを作ってここにテストコードを置く。ディレクトリ名を`test`にすることで、テストツールがテストコードの場所を見つけることができる。テストツールは`mocha`が普通に使われているのでこれをインストールする。

```
$ mkdir -p ~/letstest/test
$ cd ~/letstest
$ npm init -y
$ npm install -save mocha
```

`npm init -y` コマンドを打つと、`package.json`が生成される。この中の`scripts.test`フィールドが、`npm test`を打つ時のコマンドになる。以下のように書き換えれば、`mocha`でテストが実行できる準備ができる。

```package.json
... (前略)
  "scripts": {
    "test": "mocha"
... (後略)
```

# Step#02: テストの作成

同期関数のテストは例外がでなければ成功とみなされる。アサーションは、当面Node標準のassertでよい。以下は典型的なコード。`describe, it`とかはどっからきてるの？みたいな疑問があるが、mochaのコンテキストから来ている（のでこのjsファイルを直接実行しようとしてもエラーとなる。`npm test`経由で実行しよう）。

```test/sync.js
const assert = require('assert')

describe('SyncTest', function() {
  it('Equality', function() {
    assert(1+1===2)
    assert.equal(1+1, 2)
  })
})
```

非同期関数のテストは二種類ある。コールバック型とPromise型。コールバック型のテストでは、コールバック`done`が無事呼び出されたらテストが成功となる。Promise型では、最終的にresolveされるPromiseがreturnされたらテストは成功となる。典型的には以下のコード。

```async.js
const assert = require('assert')

describe('AsyncTest', function() {
  it ('WithCallback', function(done) {
    const targetFunc = cb=>{cb()}
    targetFunc(done)
  })
  it ('WithPromise', function() {
    return new Promise(r=>r('OK'))
  })

  it ('A lot more test With chai-promised etc')
})
```

# 次のステップ

- もう少し複雑なテストケースをmochaのドキュメントで調べる
- アサーションを強化できる`chai`, `chai-as-promised`や、`should`、`expect` などの導入を考える
deinでsyntasticを使おうとしてUnknown function: SyntasticStatuslineFlagで詰まった話

###syntasticとは
rubycopとかeslintとかのでsyntaxエラー見つけてくるやつだと思う（多分）
便利なやつっぽいし入れてみた
https://github.com/vim-syntastic/syntastic

###入れ方と参考サイト
ここのをほぼまるコピー
https://tackeyy.com/blog/posts/introduction-of-vim-syntastic

本家のsetting方法
![Screen Shot 2018-03-05 at 12.30.54.png](https://qiita-image-store.s3.amazonaws.com/0/218546/86aefa4c-7ed8-3d16-aaf4-6cc8278da736.png)

###問題
Unknown function: SyntasticStatuslineFlagうんたらかんたら。

![Screen Shot 2018-03-05 at 12.08.03.png](https://qiita-image-store.s3.amazonaws.com/0/218546/927807c6-6f03-e23a-336f-1c876f9ebe57.png)

###解決方法
set statusline+=%#warningmsg#
set statusline+=%{SyntasticStatuslineFlag()}
set statusline+=%*

この記述を.vimrcの上部に持っていった.

前にも結構「.vimrcでの読み込み位置でのエラー」があったので闇のvimmerの方はその辺を意識した方がいいのかもしれない.

その前に.vimrcを整頓したい気がするけどめんどくさい.
CSVを取り込むときに"を除去するサンプル

```Excel:Sapmle.vba
    Open varFileName For Input As #1
    Do Until EOF(1)
        Line Input #1, buf
        buf = Replace(buf, """", "")
        tmp = Split(buf, ",")
        
        ws.Cells(i, 1).Resize(1, UBound(tmp) + 1).Value = tmp
        i = i + 1
    Loop
    Close #1
```
CSV取込を行うときにデータがダブルクォート(")で囲まれていると扱いが面倒です
取り込むときにダブルクォートを除去するには、Replace関数で置き換えてやります
macOS Sierraにhomebrewをインストールする際の落とし穴

# macOS Sierraにhomebrewをインストールしようとしてエラー

##落とし穴
自分のmacにhomebrewをインストールする必要があり、下記のサイトからスクリプトをコピーして実行したがエラーになります。

https://brew.sh/index_ja.html

/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

実行結果
curl: (1) Protocol "https" not supported or disabled in libcurl

## 調査
以下のコマンドを実行
mito-macOS:~ mito$ curl -V
curl 7.53.1 (x86_64-apple-darwin16.4.0) libcurl/7.53.1 zlib/1.2.8
Protocols: dict file ftp gopher http imap ldap ldaps pop3 rtsp smtp telnet tftp 
Features: IPv6 Largefile libz UnixSockets 

デフォルトcurlコマンドではhttpsがプロトコルに入っていないことを確認。
/usr/bin/curl -Vを実行したところhttpsがプロトコルに入っていました。

mito-macOS:~ mito$ /usr/bin/curl -V
curl 7.54.0 (x86_64-apple-darwin16.0) libcurl/7.54.0 SecureTransport zlib/1.2.8
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp 
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz UnixSockets 

##解決
上記のhomebrewインストールスクリプトを変更し、無事インストールできました。

mito-macOS:~ mito# ruby -e "$(/usr/bin/curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

##補足
デフォルトのcurlが/usr/local/bin/curlになっていたので、以下のようにしてデフォルトで/usr/bin/curlが使われるように変更しました。

mito-macOS:~ mito$ cd /usr/local/bin
mito-macOS:bin mito$ ls -l
total 992
lrwxr-xr-x  1 mito  admin      28  3  5 12:14 brew -> /usr/local/Homebrew/bin/brew
-rwxr-xr-x  1 root  wheel     224  2 27 15:51 chardetect
-rwxr-xr-x  1 root  wheel  189388  3 30  2017 curl
-rwxr-xr-x  1 root  wheel    4787  3 30  2017 curl-config
-rwxr-xr-x  1 mito  wheel  273936  4  7  2017 exiftool
lrwxr-xr-x  1 root  wheel      24  6 12  2017 jamf -> /usr/local/jamf/bin/jamf
lrwxr-xr-x  1 root  wheel      29  3  8  2017 jamfAgent -> /usr/local/jamf/bin/jamfAgent
drwxr-xr-x  4 mito  wheel     136  4 10  2017 lib
-rwxr-xr-x  1 root  wheel     281  2 26 17:13 pip
-rwxr-xr-x  1 root  wheel     283  2 26 17:13 pip2
-rwxr-xr-x  1 root  wheel     287  2 26 17:13 pip2.7
-rwxr-xr-x  1 root  wheel     158  2 26 17:47 s3cmd
mito-macOS:bin mito$ mv curl curl.old
mito-macOS:bin mito$ ln -s /usr/bin/curl .
mito-macOS:bin mito$ ls -l
total 1000
lrwxr-xr-x  1 mito  admin      28  3  5 12:14 brew -> /usr/local/Homebrew/bin/brew
-rwxr-xr-x  1 root  wheel     224  2 27 15:51 chardetect
lrwxr-xr-x  1 mito  admin      13  3  5 13:03 curl -> /usr/bin/curl
-rwxr-xr-x  1 root  wheel    4787  3 30  2017 curl-config
-rwxr-xr-x  1 root  wheel  189388  3 30  2017 curl.old
-rwxr-xr-x  1 mito  wheel  273936  4  7  2017 exiftool
lrwxr-xr-x  1 root  wheel      24  6 12  2017 jamf -> /usr/local/jamf/bin/jamf
lrwxr-xr-x  1 root  wheel      29  3  8  2017 jamfAgent -> /usr/local/jamf/bin/jamfAgent
drwxr-xr-x  4 mito  wheel     136  4 10  2017 lib
-rwxr-xr-x  1 root  wheel     281  2 26 17:13 pip
-rwxr-xr-x  1 root  wheel     283  2 26 17:13 pip2
-rwxr-xr-x  1 root  wheel     287  2 26 17:13 pip2.7
-rwxr-xr-x  1 root  wheel     158  2 26 17:47 s3cmd
Rubyで整数の切り捨てをしたい



```ruby:floor.rb
#引数にマイナスを取ればOK
222.floor(-2)
```

###もし下のようなエラーが出たら
`wrong number of arguments (1 for 0)`
Rubyのバージョンが低いかもしれません。

```
# 自分の環境
$ ruby -v
ruby 2.3.3p222 (2016-11-21 revision 56859) [universal.x86_64-darwin17]
```

どうやらfloorが引数をとれるのは2.4.0からみたいです。
https://docs.ruby-lang.org/ja/search/query:Float%23floor/type:instance-method/