OmniAICreator/Qiita-1.07M huggingface dataset:
[ブロックチェーン] 分散型アプリケーション(DApps)は何がすごいのか？

数年前初めてBlockChainを見たときは、単なる分散型合意形成アルゴリズムであって分散型合意形成なんてそんなに需要ないだろう程度の認識でいました。
しかし今さらになって調べていくうちに、BlockChainを使った分散型アプリケーション(DApps)は確かに既存のサービスを駆逐しうる技術なんじゃないかと感じ始めました。
まだまだ調べ始めたばかりではありますが、今の考えについてまとめて行きます。

# 分散型アプリケーションのモデル
一側面のみを切り出してものすごく簡単に説明すると、まずPublicなサービスを不特定多数の有志でネットワークを築き運用(コンセンサス)します。
そして運用する見返りとしてサービス内通貨(トークン)を得たりサービスを利用することができる、という仕組みが分散型アプリケーションのモデルとなります。

<img width="394" alt="Screen Shot 2018-02-02 at 16.48.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/74964/bb7f88f2-84c9-74a0-786f-8ac3ab9cc3c8.png">

つまり見返りにサービス内通貨あげるから有志で運用しよう！っていうことですね。

そしてソシャゲのカードが金銭で売買されていたように、サービス内通貨の価値が上がると自然と現金と変えてでも欲しいという人が生まれてきます。
そうして初期から抱えたサービス内通貨に価値を持たせることが実装者としての利益となります。

逆に言えばサービス内通貨の価値が生まれないことには実装者としても運用者としても利益はないため、あくまでサービス先行の仕組みとなります。
したがって現在は投資対象として暴走していますが、本質的にはあくまでサービスありきで価値が生まれ、その価値をもとに成り立つサービスとなります。

# 分散型アプリケーションは何が優れているの？
中央集権型サービスはサーバ代がかかる以上運用費用をペイするためにサービス上のどこかで利益をあげる必要があります。したがって、どこかで法定通貨を得る必要性があります。
しかし分散型アプリケーションはサービス内通貨の価値を担保に成り立っているため、それで法定通貨を得る必要はありません。

たとえば分散型フリマサービスOpenBazaarはサービス利用料がかかりません。
一方Amazonやメルカリなどは企業としてサービスを運用している限りどこかで法定通貨を得る必要があります。Facebookなどの無料サービスも結局のところ広告や個人情報売買などでサービスが歪められています。
もちろんサービスとしてのUI/UXや認知度含めての優劣ですが、この差は仕組み上覆すことのできない壁として立ちはだかってくるのではないでしょうか。

つまり利益を度外視した純粋なサービスを作れることが分散型アプリケーションの強みになります。

<img width="883" alt="Screen Shot 2018-02-02 at 17.01.50.png" src="https://qiita-image-store.s3.amazonaws.com/0/74964/84ca9003-1f7d-37f0-d227-d1015e7e28a5.png">
https://www.openbazaar.org/

# 報酬設定による行動の規定
何をするのにサービス内通貨が必要で、何をすればサービス内通貨を得ることができるのかを適切に設定できれば自然とユーザの行動も促すことができます。

例えば分散型レビューサイトを作りレビューを乗せ「参考になった」が押されるたびに報酬を得られるようにしたとします。
そうすれば良いレビューをすれば報酬が得られるようになり、自然と良いレビューが集まるようになるでしょう。

そして良いレビューを書いて報酬を得るために集まってくる人も出てきて、それで生計を立てるYoutuberのような人も生まれるかもしれません。
実際にCryptoKittiesという猫育成ゲームが話題になりましたが、ゲーム性というよりは猫を売って金を儲けるられるから流行った側面もあると思います。

<img width="1081" alt="Screen Shot 2018-02-02 at 17.04.34.png" src="https://qiita-image-store.s3.amazonaws.com/0/74964/e6c42800-d066-3e79-0f1a-b113f36ab75b.png">
https://www.cryptokitties.co/

一方で繰り返しますがサービス内通貨に価値があることが全ての根底にあるため、価値が崩れてしまったら全てが成り立たなくなってしまいます。
サクラを使うなどで無限にお金が得られるといったようなイカサマが行われないようにしないといけないし、純粋にお金を擦りすぎてインフレしてしまってもいけません。

またサービスの運用者に通貨を供給しているため、通貨の価値を維持するためにはどこかで通貨を消費させる必要があります。
そのためサービス内通貨の価値が変化することで適切なFeeにならなくなってしまいサービスが成り立たなくなってしまうケースもあります。
例えばBitCoinは送金に手数料が取られるわけですが、今はBitCoinの価値が上がりすぎて銀行振込手数料の方が安いじゃんってなっており、送金手段としては優位性が失われてしまいました。
同じようにフリマサービスを作っても実質メルカリより手数料高ければ使う理由はなくなってしまいます。

このように適切に通貨の価値を維持した上でユーザの行動を規定し、サービスとしての優位性も保ち続けるルール作りが根幹であり、一番難しいところになるかと思います。

# 既存のサービスは勝てるのか
では仮に最適な分散型フリマサービスが生まれたらメルカリは勝てないのでしょうか？
その場合でもサービスでお金を取っているからこそサービスの成長にお金を投資することができる面もあるため、結局サービスの質が覆せない可能性もあります。

特にサービスに価値が生まれない限りサービス内通貨の価値も生まれないため、結果としてサービス拡充やマーケティングに投資する資金を得ることはできません。
結局分散型アプリケーションはダメだったよねって話も十分にあるとは思います。

とはいえ中抜きを多く取っているサービスほど覆せない明確な差が生まれてくるため、そういったサービスを今後分散型アプリケーションがReplaceしていく可能性は高いでしょう。

# まとめ
BlockChainは単なる分散型合意形成の仕組みではなく、利益を度外視したサービスを作ることを可能にする技術とも言えます。
一方でサービス内通貨の価値がそれを成り立たせており、価値を作り、それを上手くコントロールすることが課題となります。
それを適切に設計できたサービスが生まれたとき、Uberがタクシー会社をぶち壊したような変革が生まれる可能性を持ったものなのではないでしょうか。
Windowsでcodeceptionをbuildする際は改行コードに注意

# 問題

## buildで

[EC-CUBEのcodeception](https://github.com/EC-CUBE/eccube-codeception)をWindowsでbuildすると以下のようなエラーが発生した。

```shell
$ sudo docker-compose -f docker-compose.yml -f docker-compose.chrome.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml build --pull --no-cache
mailcatcher uses an image, skipping
db uses an image, skipping
Building eccube3
Step 1/28 : FROM eccube/php-ext-apache
latest: Pulling from eccube/php-ext-apache
.
.
.
Step 17/28 : ADD clone-${DIRTYPE}.sh /clone.sh
 ---> 7a670b8c8cb4
Step 18/28 : RUN /clone.sh
 ---> Running in 2cf290854ce7
/bin/sh: 1: /clone.sh: Permission denied
ERROR: Service 'eccube3' failed to build: The command '/bin/sh -c /clone.sh' returned a non-zero code: 126
```

## runで

また、[EC-CUBEのcodeception](https://github.com/EC-CUBE/eccube-codeception)をWindowsでrunすると以下のようなエラーが発生した。

```
$ docker-compose -f docker-compose.yml -f docker-compose.chrome.yml -f docker-compose.pgsql.yml -f docker-compose.dev.yml run --rm codecept run -d --env chrome,pgsql --coverage --coverage-html --coverage-xml --html report.html acceptance EF02ProductCest
Creating eccubecodeceptionlocal_mailcatcher_1
Creating eccubecodeceptionlocal_db_1
Creating eccubecodeceptionlocal_browser_1
Creating eccubecodeceptionlocal_eccube3_1
No such file or directory
```

`No such file or directory` 以外情報がなく困ってしまった。

# 原因

改行コードがCRLFになっていると実行できなくなるファイルがあるようです。

# 解決

windowsのgitが勝手に改行コードを変えてしまっていたので設定を変えます。

```shell
$ git config --global -l | grep core.autocrlf
core.autocrlf=true

$ git config --global core.autocrlf false

$ git config --global -l | grep core.autocrlf
core.autocrlf=false
```

もう一度リポジトリをcloneしましょう。

ソース自体がCRLFになってしまっていた場合は改行コードを置換してしまいましょう。

```shell
find . -name \*.sh -type f | xargs -n 10 nkf -Lu --overwrite
```

[こちら](https://qiita.com/kouchi67/items/958e74ef792eed0c157d)を参考にさせていただきました。
HDP 2.6.3をAWSにインストール　乞食版

# ゴール
AWSの超安いインスタンスに、HDPをインストールして遊ぶ。

# インスタンス初期化
## Ambari
t2.nano

```
[ec2-user@ip-172-31 ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:            990          80         731          12         179         739
Swap:             0           0           0
```

AWS Amazon Linux スワップファイル作成によりSwap領域のサイズを増やす
https://qiita.com/na0AaooQ/items/278a11ed905995bd16af

現在は1GBあるので、8GBのSwapメモリを追加

```
grep Mem /proc/meminfo
grep Swap /proc/meminfo
free
uname -a
# /swapfile1 に保存
sudo dd if=/dev/zero of=/swapfile1 bs=1M count=8192
grep Swap /proc/meminfo

ll /swapfile1
sudo chmod 600 /swapfile1
sudo mkswap /swapfile1
ll /swapfile1
swapon -s
free
sudo swapon /swapfile1
free
grep Swap /proc/meminfo
```

メモリ追加しました。

```
[ec2-user@ip-172-31 ~]$ free -m
              total        used        free      shared  buff/cache   available
Mem:            990          77          64          12         848         731
Swap:          3083           0        3083
[ec2-user@ip-172-31 ~]$
```

# t2.micro instance作成
Ambari：１台
Master：１台
Slave：３台

<img width="1228" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/133516/d516aee9-eb70-4e3f-b41d-bf6e22120556.png">

# 注意事項
## RHEL 7.4
Red Hat Enterprise Linux 7.4 (HVM), SSD Volume Type - ami-26ebbc5c

## AWS setting
t2.micro instance
### Storage setups -- 
Ambari: EBS 15G
NN/DN: EBS 20G

<img width="937" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/133516/c43aaf1c-0147-332e-0e59-0f5e3b44c2e8.png">

<img width="748" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/133516/1fcc9771-76b3-48c4-6a95-c07a97758cf5.png">



### セキュリティ設定
All Traffic, Allow, HDPのセキュリティグループID指定（内部通信を全部許可）
All Traffic, Allow, MyIP (管理者のIPを許可)
これでOK

### ssh private key

```
scp -i amuisekey.pem amuisekey.pem ec2-user@ec2-54-234-94-128.compute-1.amazonaws.com:~/.ssh/id_rsa
# 全部サーバーにアップロード
```

### hosts
#### 自分のMBP ``/etc/hosts``

```
    127.0.0.1 localhost.localdomain localhost
    ::1 localhost6.localdomain6 localhost6

#外部IP
    10.110.35.23 hdpmaster1.hdp.hadoop hdpmaster1
    10.191.45.41 hdpmaster2.hdp.hadoop hdpmaster2
    10.151.94.30 hdpslave1.hdp.hadoop hdpslave1
    10.151.87.239 hdpslave2.hdp.hadoop hdpslave2
    10.70.78.233 hdpslave3.hdp.hadoop hdpslave3
    10.151.22.30 ambarimaster.hdp.hadoop ambarimaster
```

#### AWSサーバーの ``/etc/hosts``

```
    127.0.0.1 localhost.localdomain localhost
    ::1 localhost6.localdomain6 localhost6

#外部IP
    10.110.35.23 hdpmaster1.hdp.hadoop hdpmaster1
    10.191.45.41 hdpmaster2.hdp.hadoop hdpmaster2
    10.151.94.30 hdpslave1.hdp.hadoop hdpslave1
    10.151.87.239 hdpslave2.hdp.hadoop hdpslave2
    10.70.78.233 hdpslave3.hdp.hadoop hdpslave3
    10.151.22.30 ambarimaster.hdp.hadoop ambarimaster
```

# Install

https://community.hortonworks.com/articles/14512/ambari-on-ec2.html


<img width="1211" alt="image.png" src="https://qiita-image-store.s3.amazonaws.com/0/133516/2a236662-bb73-8bc7-26ca-6254441ccf95.png">
AppleScriptで写真(Photos)の選択項目を取得できない

```applescript:コード
tell application "Photos"
	set photo to item 1 of selection
end tell
```

```applescript:結果
error "Photosでエラーが起きました: item 1 of selectionのタイプをspecifierに変換できません。" number -1700 from item 1 of selection to specifier
```

写真(Photos)アプリで選択している写真を処理するAppleScriptを書こうとしたが、`selection`の要素を変数に代入しようとするとエラーになる。選択する写真の数を変えてから`count`を調べるとちゃんと変化しているので、選択自体はされている模様。

> selection (list of media item, r/o) : The currently selected media items in the application

リファレンスによると`selection`には`media item`が入っているはずだが、代入時の型変換に失敗している?

ネットで検索しても、アルバムに含まれる写真全てに対して処理を行うサンプルしか見つからない。
tar/gzで圧縮しながらS3に転送する



```
tar cf - ディレクトリ名 | gzip --best | aws s3 cp - s3://バケット/ファイル名.tar.gz
```
でローカルにtar.gzファイルを置かずにS3に転送できます

参考になったページ
https://dev.classmethod.jp/cloud/aws/aws-cli-s3-streaming/
Xcode9でcmd+clickが効かない時（?が表示されて遷移しない）の解消方法

わたしのパターンでは下記で解決できました。

# 解決方法

1. Xcodeを終了する
2. 下記に移動
/Users/[ユーザー名]/Library/Developer/Xcode/DerivedData

3. DerivedData以下を全て削除
4. 対象のXcodeプロジェクト（xcworkspace or xcodeproj）をコンテキストメニュー[パッケージの内容を表示]をクリック
5. xcuserdata以下を全て削除
6. Xcode再起動

# Links
古いstackoverflowですが参考になりました。
https://stackoverflow.com/questions/10306539/xcode-code-sense-and-cmdclick-to-symbol-doesnt-work-for-1-of-my-projects
[AWS] サインイン画面が重すぎたので、その対処

# 何があった？
AWSマネジメントコンソール（以下「マネコン」）のサインイン画面が重すぎ（遅すぎ）る。
ブラウザのアイコンがくるくる回り続け、数十秒かかって結局画面が開かず中断されることもある。
別ネットワークに切り替えたらそこまで遅いわけでもなかったので、単にプロバイダの問題かもしれない。でもやっぱりちょっと遅い。

# ふと気づいた
https://us-east-1.console.aws.amazon.com/ 　　　　→ 遅い
https://ap-northeast-1.console.aws.amazon.com/ 　　→ 速い

当方、日本からの利用です。
わざわざアメリカまで行ってるから遅かったんですね。
というかマネコンって CloudFront で近場のエッジ使ってるものだと思ってた。サインイン画面は例外なのかな。

# でもIAMユーザーでサインインするときって

「どのアカウントに」を毎回入力するのが面倒なので、IAM画面のダッシュボードに表示されている下記のサインインリンクを使ってます。

```
https://<Account-Alias>.signin.aws.amazon.com/console
```

しかしこれだと `us-east-1` のサインイン画面に飛ばされてしまう。


# 対処法
```
https://<Account-Alias>.signin.aws.amazon.com/console?region=ap-northeast-1
```
後ろにリージョン情報 `?region=ap-northeast-1` をくっつけてみたら、そのリージョンのサインイン画面に飛ぶようになりました。
これで快適。

# ちなみに
今回の件とはあまり関係なく考慮すべきことなんですが。
CloudTrail で `ConsoleSignin` のログを取る場合、リージョン別に出力されることに注意。
CloudWatch Events も各リージョンでイベントが発生します。
`ConsoleSignin` を検知して何かしようと思ったら、全リージョンにCloudTrailの設定が必要です。
CloudTrail は 全リージョン設定が一発で出来るようになってますが、CloudWatch Events のほうは各リージョンで個別に設定する必要があります。
【Swift4】UITableViewのミニマムサンプル【iOS】

とりあえず下のコードをコピペしてビルドするだけで、図のようなテーブルが表示できます。

*for Xcode version 9.2 beta / Swift4*
<img width="395" alt="iPhone_8_Plus_-_11_2.png" src="https://qiita-image-store.s3.amazonaws.com/0/151314/69bf4dfc-a2f8-1458-cdde-96ea4855f0c4.png">

ViewController.swift

```Swift
//
//  ViewController.swift
//

import UIKit

class ViewController: UIViewController {

    var tableView:UITableView!
    
    let data = [
        ["ピカチュウ", "コラッタ", "イーブイ", "カビゴン", "ポッポ"],
        ["シナモロール", "モカ"]
    ]

    let sectionName = ["ポケモン","サンリオ"]
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // テーブルのインスタンス
        tableView = UITableView()
        
        // テーブルサイズを画面いっぱいに
        tableView.frame = view.frame
        
        // デリゲート
        tableView.delegate = self
        tableView.dataSource = self
        
        // セルをテーブルに紐付ける
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
        
        // データのないセルを表示しないようにするハック
        tableView.tableFooterView = UIView(frame: .zero)

        // テーブルを表示
        view.addSubview(tableView)
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
}

// データ・ソース
extension ViewController: UITableViewDataSource {
    
    // セクションごとにデータ要素数
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return data[section].count
    }
    
    // セクション数
    func numberOfSections(in tableView: UITableView) -> Int {
        return sectionName.count
    }
    
    // セクションヘッダ
    func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?  {
        return sectionName[section]
    }

    // セルの高さ
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 40
    }
    
    // セル生成
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        
        cell.textLabel?.text = data[indexPath.section][indexPath.row]
        cell.accessoryType = .disclosureIndicator
        //cell.accessoryView = UISwitch() // スィッチ
        
        return cell
    }
}

// セルタップ時の動作定義など
extension ViewController: UITableViewDelegate {
    
    // セクションヘッダの高さ
    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 50
    }
    
    // セルタップ時の挙動
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print(indexPath)
    }
}
```

**その他のミニマムサンプルシリーズ**
[【Swift4】WKWebViewのミニマムサンプル【iOS】](https://qiita.com/fromage-blanc/items/079bc8d6da34ac90fecf)
[【Swift4】UIProgressViewのミニマムサンプル【iOS】](https://qiita.com/fromage-blanc/items/2ec7c89c3484765acf8f)
Delphi がおしゃれになった件

#IDE Theme Manager
Delphi / C++Builder / RADStudio (以下 Delphi) 10.2.2 Tokyo から、IDE テーママネージャという機能が追加されました。

[IDE テーマ マネージャ](http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/IDE_%E3%83%86%E3%83%BC%E3%83%9E_%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3)

IDE テーママネージャを使うと今までデフォルト色だったり[謎の薄ら青い表示](https://ht-deko.com/ft1505.html)だった IDE がなんだか黒く精悍な感じになったりします。

具体的には↓「オプション」ウィンドウで

![theme.png](https://qiita-image-store.s3.amazonaws.com/0/12977/98c7ffe5-3352-0f21-b92e-97d93ca95ad2.png)

「Enable IDE テーマ」にチェックを入れて「淡色」「濃色」または「カスタム」を選ぶだけです。
この画像では「濃色」テーマを選んでいます。
また、この「濃色」テーマは DocWiki にも書いてありますが IDE のために特別に [DelphiStyles.com] (http://www.delphistyles.com/)が作ってくれた物です。

なお、「Enable IDE テーマ」を外すと今まで通りの見た目になります。
IDE テーマは [VCL スタイル](http://docwiki.embarcadero.com/RADStudio/Tokyo/ja/VCL_%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AE%E6%A6%82%E8%A6%81)と同等だと思われるので、[若干速度が遅くなったり](https://twitter.com/ht_deko/statuses/940835446355054592)もします。
ですので、まあ今までの色で何の問題もないよ！という場合は、IDE テーマはオフにした方が良いかも知れません！

##初回起動時
ちなみに、初回起動時は↓こんな感じで積極的にテーマを選ばせられます！
(画像は英語版)

![10.2.2_-_welcome_dialog_page_1.PNG](https://qiita-image-store.s3.amazonaws.com/0/12977/d4ef33cb-191d-920c-e6b7-b74fbc184b37.png)

#まとめ
今っぽくなった。
has_many などで親の付替えをして削除した時にハマったこと


Rails で has_many や has_one などのリレーションがあるモデルで、子が参照している親を付け替えるコードを書いていたらハマってしまったことがあったので備忘録を残しておきます。

### やりたかったこと

- 子レコードが参照している親レコードを別の親レコードへ変更する
- 元々参照されていた親レコードは削除する

とあるユーザを削除する際に、所持しているデータを、別のユーザに所有権を渡して消さないようにする的なノリです。

### 現象

簡単に言うと、親レコードを削除した際に参照していた子レコードも一緒に削除されてしまいました。コードは以下のとおりです。

#### モデル

```ruby
class User < ApplicationRecord
  has_many :books, dependent: :destroy
end

class Book < ApplicationRecord
  belongs_to :user
end
```

#### 処理コード

事前にデータを用意しておきます。

```ruby
r = User.new
r.name = 'zaru'
r.save

r = User.new
r.name = 'tofu'
r.save

r = Book.new
r.name = 'book 1'
r.user = User.first
r.save
```

二人の User がいて、一つの Book レコードがある状況です。ここから、Book を所持している User を削除します。削除する前に Book を別の User に託しておきます。

```ruby
user1 = User.first
user2 = User.last

user1.books.each do |book|
  book.user = nil
  user2.books << book
end

user1.destroy
```

これを実行すると、 `user2.books << book` の時点でちゃんと `UPDATE` SQL が実行されて Book レコードの参照先は二人目の User になります。

ただし、その後の `user1.destroy` を実行すると Book も一緒に `DELETE` されてしまいます。これは `user1` オブジェクトが Book を参照している状態のままなので、 `destroy` すると関連している Book レコードも一緒に削除しようと良い感じに働いてくれるからです。

#### 対処法

オブジェクトの情報が古いだけなので慌てず騒がず `reload` して最新の情報に変更します。

```ruby
user1 = User.first
user2 = User.last

user1.books.each do |book|
  book.user = nil
  user2.books << book
end

user1.reload # 追加
user1.destroy
```

これだけで user1 だけが削除されて、Book は user2 の方に付け替えられて無事生き残ることができました。良かったです。
bash 補完 メモ

## 基本骨格

```Bash
hoge() {
    echo $1
}
hoge_completion() {
    local cur prev cword opts
    _get_comp_words_by_ref -n : cur prev cword
    opts="foo bar baz"
    COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
}
complete -F hoge_completion hoge
```

`$cur`は現在のワード、
`$prev`は直前のワード、
`$cword`は現在のワードのインデックスを意味します。

`compgen`関数は、`-f`でファイルの補完、`-d`でディレクトリの補完、`-c`でコマンドの補完ができます。

## 小技

### COMP_WORDSのインデックスアクセス

`COMP_WORDS`という変数にワードリストが格納されているため、

```Bash
set ${COMP_WORDS[@]}
```

とすると、`$1`のようにして各ワードにアクセスできます。

### 動的ファイルパス補完（カレントディレクトリ）

```Bash
hoge_completion() {
    local cur prev cword opts
    _get_comp_words_by_ref -n : cur prev cword
    dir="$(echo ${cur} | grep -o ".*/")"
    if test "${dir}" ;then
        COMPREPLY=( $(compgen -W "$(ls -F ${dir} | sed -E "s@(.*)@${dir}\1@g")" -- "${cur}") )
    else 
        COMPREPLY=( $(compgen -W "$(ls -F)" -- "${cur}") )
    fi
}
complete -o nospace -F hoge_completion hoge
```

### 動的ファイルパス補完（ベースディレクトリ指定）

```Bash
hoge_completion() {
    local cur prev cword opts
    _get_comp_words_by_ref -n : cur prev cword
    dir="$(echo ${cur} | grep -o ".*/")"
    if test "${dir}" ;then
        COMPREPLY=( $(compgen -W "$(ls -F $HOME/events/${dir} | sed -E "s@(.*)@${dir}\1@g")" -- "${cur}") )
    else 
        COMPREPLY=( $(compgen -W "$(ls -F $HOME/events/)" -- "${cur}") )
    fi
}
complete -o nospace -F hoge_completion hoge
```

### 動的ファイルパス補完（ディレクトリのみ）

```Bash
r() {
    cd $HOME/repos/$1
}
r_completion() {
    local cur prev cword opts
    _get_comp_words_by_ref -n : cur prev cword
    dir="$(echo ${cur} | grep -o ".*/")"
    if test "${dir}" ;then
        COMPREPLY=( $(compgen -W "$(ls -F $HOME/repos/${dir} | sed -E "s@(.*)@${dir}\1@g" | grep -o ".*/$")" -- "${cur}") )
    else 
        COMPREPLY=( $(compgen -W "$(ls -F $HOME/repos/ | grep -o ".*/$")" -- "${cur}") )
    fi
}
complete -o nospace -F r_completion r
```
OpenCVのWindowをスナップさせたくない

OpenCVでWindowを作成し、画面の端に近づけると、勝手にスナップします。
微妙な位置に配置したい時など困りますので、この余計な機能を消してしまいましょう。

# ソースを修正する
問題の個所は、「sources/modules/highgui/src/window_w32.cpp」にあります。

```window_w32.cpp
    case WM_WINDOWPOSCHANGING:
       {
          // Snap window to screen edges with multi-monitor support. // Adi Shavit
          LPWINDOWPOS pos = (LPWINDOWPOS)lParam;

          RECT rect;
          GetWindowRect(window->frame, &rect);

          HMONITOR hMonitor;
          hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);

          MONITORINFO mi;
          mi.cbSize = sizeof(mi);
          GetMonitorInfo(hMonitor, &mi);

          const int SNAP_DISTANCE = 15;

          if (abs(pos->x - mi.rcMonitor.left) <= SNAP_DISTANCE)
             pos->x = mi.rcMonitor.left;               // snap to left edge
          else
             if (abs(pos->x + pos->cx - mi.rcMonitor.right) <= SNAP_DISTANCE)
                pos->x = mi.rcMonitor.right - pos->cx; // snap to right edge

          if (abs(pos->y - mi.rcMonitor.top) <= SNAP_DISTANCE)
             pos->y = mi.rcMonitor.top;                 // snap to top edge
          else
             if (abs(pos->y + pos->cy - mi.rcMonitor.bottom) <= SNAP_DISTANCE)
                pos->y = mi.rcMonitor.bottom - pos->cy; // snap to bottom edge
       }

```

画面の上下左右15pixel以内になると「0」にしてしまうという力技を見せてくれています。
こんな処理は、さくっとコメントアウトしてしまいましょう。

```window_w32.cpp
    case WM_WINDOWPOSCHANGING:
//       {
//          // Snap window to screen edges with multi-monitor support. // Adi Shavit
//          LPWINDOWPOS pos = (LPWINDOWPOS)lParam;
//
//          RECT rect;
//          GetWindowRect(window->frame, &rect);
//
//          HMONITOR hMonitor;
//          hMonitor = MonitorFromRect(&rect, MONITOR_DEFAULTTONEAREST);
//
//          MONITORINFO mi;
//          mi.cbSize = sizeof(mi);
//          GetMonitorInfo(hMonitor, &mi);
//
//          const int SNAP_DISTANCE = 15;
//
//          if (abs(pos->x - mi.rcMonitor.left) <= SNAP_DISTANCE)
//             pos->x = mi.rcMonitor.left;               // snap to left edge
//          else
//             if (abs(pos->x + pos->cx - mi.rcMonitor.right) <= SNAP_DISTANCE)
//                pos->x = mi.rcMonitor.right - pos->cx; // snap to right edge
//
//          if (abs(pos->y - mi.rcMonitor.top) <= SNAP_DISTANCE)
//             pos->y = mi.rcMonitor.top;                 // snap to top edge
//          else
//             if (abs(pos->y + pos->cy - mi.rcMonitor.bottom) <= SNAP_DISTANCE)
//                pos->y = mi.rcMonitor.bottom - pos->cy; // snap to bottom edge
//       }
```

※一応イベントは受け取り、下の処理（アクティブならフォーカスを当てる）を実行出来るよう、breakしたりはしません

# 余談
Windows10ではOSが[余計なこと](https://thinkit.co.jp/story/2015/07/27/6248)をしてくれるそうですが、そちらは設定で変更できるようです。

# まとめ
「小さな親切、大きなお世話」ということで、将来のバージョンでは削除されていることを祈ります。
FuelPHP1.8がPHP7.2で使えなかった

自分用のメモです。
既出の場合は消しますが、見当たらなかったので。

# エラー

```
Warning - get_class() expects parameter 1 to be object, null given in ***\fuel\core\classes\security.php on line 241
```


# 問題
fuelPHP1.8が、PHP7.2で変更された修正に対応されていないためにでる表示。
PHP7.1であれば、表示されないため、7.2以上使う場合は、注意が必要になる。

参照URL： https://qiita.com/rana_kualu/items/40ebed78742bfdbd1065#get_class-disallow-null-parameter

# 対策
* coreのクラスをappで、オーバーライドして、修正を行う
 * https://qiita.com/ichi_404/items/d5b656d4142b1e19d97e に詳細が載っています。
* PHPのバージョンを下げる

オーバーライドで修正を行う場合は、補足を確認するとよいかもしれない。

# 補足
fuelphp develop/1.9 では、修正を行っている模様。
https://github.com/fuel/core/commit/8a44a112c7a9a7eee54f6990a9913daf96a230a1

（1.9も2もいつでるのか。）
シェルスクリプト

#変数の設定方法と使い方
```shell:variable.sh
#!/bin/sh

# シェル変数をセット
VARIABLE=variable

#シェル編数を使う
echo $VARIABLE
=> variable # 変数に設定された値が出力される

# シェル変数の設定失敗　設定時にスペースがあってはダメ
VARIABLE = space
=> VARIABLE: command not found

#シェル編数を使う
echo $VARIABLE 
=> variable # 変数の再設定がされていないので、variableのまま

echo VARIABLE
=> VARIABLE # 変数呼び出し時には 「$」が必要。付いていないため、そのまま VARIABLEが出力される
```

# クオーテーションの使い分け
復習したのでまとめておく

```shell:quote.sh
#!/bin/sh

FOO="date"

# シングル
echo '$FOO'
# => $FOO

# ダブル
echo "$FOO"
# => date

# バッククオート
echo `$FOO`
=> 2018年 2月 2日 金曜日 15時59分57秒 JST
```

- シングル
変数は展開されない

- ダブル
変数は展開される

- バッククオート
コマンドが解釈される。
コマンドとして解釈できない場合は、エラーが発生する。
command not found

# ファイルディスクリプタ
- 0 標準入力
- 1 標準出力
- 2 標準エラー

# uniqコマンドの結果

```text:sample.txt
sample text a
sample text line3
sample text line2
sample text line3
sample text line4
sample text line5
sample text line7
sample text line6
sample text line7
```

このテキストに対して uniqを使った時の結果
<pre># 重複を取り除いて表示
cat a.txt | sort | uniq 

sample text a
sample text line2
sample text line3
sample text line4
sample text line5
sample text line6
sample text line7
</pre>


<pre># 重複している行のみを表示
cat a.txt | sort | uniq　-d

sample text line3
sample text line7
</pre>

<pre># 重複している行以外を表示
cat a.txt | sort | uniq　-u

sample text a
sample text line2
sample text line4
sample text line5
sample text line6
</pre>
【Rails】S3からファイルをダウンロードするやり方

## 記事を書こうと思った理由
 - ある日、RailsでS3からダウンロードの処理を書こうとした際、「あれ？そういえば、S3からのダウンロードってどうやってやるだっけ？」って調べたところ、**S3へのアップロードの記事は多く**見つけたけど、**S3からダウンロードの記事が少ない**と思い、せっかくなら記事にしちゃえ！と思いました。

## 準備するもの
 - 前提として、S3へのアップロードができるアプリ
   - S3へのアップロードのやり方が書かれてある記事は多くあるので、詳しい設定などは省きます。
 - 開発環境
   - Ruby 2.4.3
   - Ruby on Rails 5.1.4 
   - Amazon S3にすでにアップロードされている画像

## 開発手順
それでは、コードを書いていきます。

### 1. downloadアクションのルート定義
プライマリーキーが必要になるので、 `collection` ではなく`member` ですね。

```routes.rb
resources :shared_files,  only: %i(create destroy) do
  member do
    get :download
  end
end
```

```
$ bundle exec rake routes | grep download
```

下のように、pathが生成されていることを確認したら、次に行きましょう。

```
download_shared_file GET /shared_files/:id/download(.:format) shared_files#download
```

### 2. view
`button_to` は、 `method` オプションがデフォルトで `post` になるので、 しっかりと `{ method: :get }` と`method`オプションの値を定義しましょう。 

```shared_files/index.html.slim
.shared-files__file-buttons
    button.shared-files__file-download-button
      = button_to 'ダウンロード', download_shared_file_path(shared_file), { method: :get }
```

### 3. モデル
モデルに少々メソッドを定義しましょう。環境変数は適宜定義していただけると幸いです。

```shared_file.rb
class SharedFile < ApplicationRecord

  AMAZON_S3_DOMAIN = "https://#{ENV['AWS_HOST_NAME']}"

  mount_uploader :name, SharedFileUploader

  def file_url
    "#{AMAZON_S3_DOMAIN}/#{ENV['AWS_S3_DEV_BUCKET']}/#{self.file_name}"
  end
 
  def file_name
    self.name.file.filename
  end

  def content_type
    self.name.content_type
  end
end

```

### 4.controller
- いよいよコントローラーの実装に入ります。
- この `data.read` の処理を探すのに、結構時間がかかりました。
- 仕様を読んだり、プロダクトマネージャーに確認をとったところ、日本語がリンクに含まれることから、 `URI.encode` でエンコードします。
- ポイントは、 `disposition: 'attachment'` と、 ファイルの種類を `type:` オプションで指定すること。`disposition` キーにはデフォルトで`attachment`設定されていますが、明記しました。 `type` でしっかりファイルの種類を指定してあげないと、全部 `jpeg` としてダウンロードされてしまいます。
- `send_data`のドキュメント ↓
- http://railsdoc.com/references/send_data


```shared_files_controller.rb
class SharedFilesController < ApplicationController
  def index 
    @shared_files = SharedFile.all
  end

  def download
    @shared_file = SharedFile.find(params[:id)
    data = open(URI.encode(@shared_file.file_url))
    send_data data.read, disposition: 'attachment',
              filename: @shared_file.file_name, type: @shared_file.content_type 
  end
end
```

これでダウンロード処理の完成です！お疲れ様でした。

## まとめ
 - 今回のような「あれ？この処理ってどうやって書くんだっけ？」と思うことは、すぐ記事にまとめてアウトプットしていきます！
 - 自分は上のように書きましたが、もっといいやり方があればコメントに残していただけると幸いです。

## 参考にした記事
https://stackoverflow.com/questions/12277971/using-send-file-to-download-a-file-from-amazon-s3/15028162#15028162
[Ruby]配列の要素ごとに別々のブロック変数で扱う

# はじめに
ブロック変数の配列について、配列の添字で指定する方法はこう

```ruby
people = {
#  name  => data
  '太郎' => ['東京', 30, 'プログラマー'],
  '花子' => ['大阪', 20, '学生']
}

# dataに添字で指定
people.each do |name, data|
  puts "#{name}は#{data[0]}に住む#{data[1]}才の#{data[2]}です."
end
#=> 太郎は東京に住む30才のプログラマーです.
#   花子は大阪に住む20才の学生です.
```
何を表しているのか、添字だとわかりづらいです。


なので配列の要素ごとに異なるブロック変数で扱いたいです。
でも要素数だけ変数をならべても、配列が展開されないのでうまくできません。

```ruby
# これだとダメ
people.each do |name, place, age, job|
  puts "#{name}は#{place}に住む#{age}才の#{job}です."
end
#=> 太郎は["東京", 30, "プログラマー"]に住む才のです.
#   花子は["大阪", 20, "学生"]に住む才のです.
```

# 解決法
配列の要素を`()`で囲むことで、別々のブロック変数で扱えます

```ruby
# (place, age, job)とする
people.each do |name, (place, age, job)|
  puts "#{name}は#{place}に住む#{age}才の#{job}です."
end
#=> 太郎は東京に住む30才のプログラマーです.
#   花子は大阪に住む20才の学生です.
```

レシーバが配列でも同様にできます。

```ruby
people = [
# [ name  , [place, age, job] ]
  ['太郎' , ['東京', 30, 'プログラマー'] ],
  ['花子' , ['大阪', 20, '学生'] ]
]

# レシーバが配列でもOK 
people.each do |name, (place, age, job)|
  puts "#{name}は#{place}に住む#{age}才の#{job}です."
end
#=> 太郎は東京に住む30才のプログラマーです.
#   花子は大阪に住む20才の学生です.
```
レゴ ブースト　01. 中身など

#やっと発売
　ようやく日本でも「#17101 レゴ ブースト クリエィティブ・ボックス（以降BOOST、boostタグを荒らしたくないのでタグはLego_Boostにしますね）」が発売になりました。店頭販売は2月7日からっぽいですが、運よくトイザらスの先行予約販売で買うことができました。[税込21,598円](https://www.toysrus.co.jp/s/dsg-604182500 "トイザらスの販売ページ")ですね、WeDo2.0よりもずいぶん安くてうれしいです。
　WeDo2.0もなかなか良い教材だったのですが、何せ標準でモーターが1個しかないというところに随分僕的には泣かされました。1個は1個なりに色々工夫し甲斐はあったのですけれど、やっぱ自由に走らせたいですからね、やっぱ、やっぱね…。
　そんな訳でせっかくなので、BOOST関連のことはここにつらつらと書いて残しておくことにしました。頑張ると長く続かないのでかなりいい加減に残していくと思いますけど、色々調べたり翻訳したりする手間がはぶけたらリアクション頂けると調子に乗って続けられるんじゃないかな～とか思ってますので、何かありましたらよろしくお願いします。

#BOOSTって？
##パッケージ
　なんかこんなんです。
![IMG_2930.JPG](https://qiita-image-store.s3.amazonaws.com/0/151581/f5f06e7f-f321-7aaa-5692-b2700951d00f.jpeg)
　MindstormsやWeDoと違ってリテール版のみです。英語のサイトは[ここ](https://www.lego.com/en-us/boost)、日本語ページないみたいですけど、[開発環境のダウンロードページ](https://www.lego.com/ja-jp/service/device-guide/boost)だけは用意されています。5in1モデルってことでロボットとかギターとかインストあるみたいですけど、冊子版のインストは入っていません。その代りびっくりドンキーのメニューみたいなミッションシートっぽい厚紙が入っていて、そこにパーツリストの記載もあります。
![IMG_2932.JPG](https://qiita-image-store.s3.amazonaws.com/0/151581/10811e37-f42b-99c2-ba56-8f36c8a62767.jpeg)
　パーツは11番までナンバリングされた小袋に入ってるので、インストで組み立て順の指示があるんでしょう（インストみちゃいない）。それプラスモーター・センサーと大物が入った袋と、本体（「**ムーブハブ**」っていいます）の入った箱が入ってます。
##BOOSTムーブハブとWeDo2.0スマートハブ
![IMG_2934.JPG](https://qiita-image-store.s3.amazonaws.com/0/151581/d9074084-9fec-01a5-4174-da74e4f9240c.jpeg)
　んで、写真左のグループがBOOST、右のグループがWeDo2.0です。WeDo2.0スマートハブは8x6x3ブリックサイズですが、ムーブハブは16x6x4ブリックサイズ、まぁ2倍ちょいです。上面にボタンとフルカラーLEDを備えているのも一緒、ただムーブハブには圧電サウンダがないので「ぴょれりっぺぺっぺぺっ」って言ってくれないのがちょっとさみしい？
　ただし、ムーブハブにはその名の通り、A・Bポートとしてサーボモーターが内蔵されています。やったぜ！　ついでに6軸チルトセンサーも内蔵。付属のデバイスは4x2x2のカラー＆距離センサー（WeDo2.0の距離/チルトセンサーは4x2x1）、6x4x3のインタラクティブサーボモーター（WeDo2.0のDCモーターは6x3x(2+1/3)）がついてます。
　ムーブハブにC・Dポートとして2つあるインターフェイスは俗に言うPowerFunction2.0(以降PF2)で、さっそく試してみましたがWeDo2.0のデバイスもそのまま繋いで読めましたし、WeDo2.0からもBOOSTのモーターを回せました（もちろん回転角は読めない）。ただ、カラー＆距離センサーは認識するのみでまともな値が返ってこない、まぁ、[WeDo2.0 SDK](https://education.lego.com/en-us/support/wedo-2/developer-kits)みたいなのをBOOSTでも出してほしいところですね…。待ちきれない人たちは[解析を進めていたり](https://github.com/JorgePe/BOOSTreveng)とか[Pythonでとりあえず書いてみたり](https://github.com/undera/pylgbst)もしているみたいです。
![IMG_2933.JPG](https://qiita-image-store.s3.amazonaws.com/0/151581/247f105e-4761-5976-9208-5c3a729bec14.jpeg)
　そして、キター、バッテリーは単四6本、PFらしく9Vっす！　これで勝つる！　あ、なのでWeDo2.0のモーターをBOOSTにつけるとだいぶ不安になるぐらいの速さで回ります。この子電源電圧3Vを昇圧して回していたらしいので、試したら燃える前に外した方がいいかも、もしかしたらね。
　とりあえず今日はここまでにしておきます～
Docker on ARM64でknowledgeを構築してみた

## 事の始まり
先日Raspberry pi zeroの供給が安定しやっと当方もzero W入手することができて喜びに浸っていたとき、シングルボードコンピュータで遊びたいと思い立った。しかしRaspberry pi zeroは性能的にdocker動かしたりサーバ構築したりするにはかなり厳しく、その代わり去年買ったROCK64で[knowledge](https://information-knowledge.support-project.org/ja/)を構築したいと考えた。(zero wはピンヘッダつけてGPIO関連でなんか遊ぶかな...)
幸いknowledgeはdocker版も存在していてそこに手を加えれば比較的簡単に実装できそうだったので行った。


## やったこと
主にimageの差し替えと一部のパッケージの変更をした。
ベースのimageに関しては公式で色々イメージが公開されているのでそれを用いた。
https://hub.docker.com/u/arm64v8/

殆どのパッケージはデフォルトでarm64版が存在したので流用できたが、oracle-jdkがlaunchpadから拾ってこれなかったためopenjdkにした。


## 結果
できた。
できたのでdocker hubに登録した
https://hub.docker.com/r/khrom/docker-knowledge-arm64/
![docker.PNG](https://qiita-image-store.s3.amazonaws.com/0/104928/6759c716-6d10-4777-ba73-3072fda65091.png)

## 実行方法 
公式と実行imageを変えるだけです。
一応公式のタグ全てに変更を加えたのでイメージは`khrom/docker-knowledge-arm64:japanese`等でも動きます。

```
docker pull khrom/docker-knowledge-arm64
mkdir /home/hoge/knowledge
chmod a+w /home/hoge/knowledge
docker run -d -p 80:8080 -v /home/hoge/knowledge:/root/.knowledge --name knowledge khrom/docker-knowledge-arm64
```

## 終わりに
今回手元にあったROCK64で構築しましたが、Raspberry pi3でも64bitのOSを導入すれば動くと思います。
32bit版もベースimageを変えれば作れると思いますが、今回当方で実行環境が無いためパス。
[Raspberry pi3が手に入ったら作るかも。](http://amzn.asia/7vjgJSI )ってか欲しいです。

進路どうしようかな...
Linux上でPC上に搭載されてあるCPU使用率を高める

## htopコマンドでCPU使用率を見た時のたまにある現象
<img width="1680" alt="スクリーンショット 2018-01-27 16.54.32.png" src="https://qiita-image-store.s3.amazonaws.com/0/109134/dab29417-f855-dcca-b72c-cea41f20cb01.png">

* 6-Coreのみが使用されていて他のCoreが使用されていない
* GPU環境とかで他のプロセスも使用したい時に困る

①　CPUを100%使用したい時に打つコマンド

```
openssl speed -multi `grep processor /proc/cpuinfo|wc -l`
```

* openssl speed : アルゴリズム速度の測定
* grep processor /proc/cpuinfo|wc -l　: cpuの情報をgrepしてその行数を`wc -l`で数えている

②１つのCPUに負荷をかけたい場合

```
yes > /dev/null
```

③CPU負荷状況を確認したい時

```
ps aux | grep yes | grep -v grep
```

* かけたい数だけこのコマンドを押せばいい

* 最後に`kill`コマンドを使用して、プロセスを落とすことが出来る

## 参考文献
* http://x68000.q-e-d.net/~68user/unix/pickup?openssl#prgmemo-openssl-speed
* http://d.hatena.ne.jp/tmatsuu/20140101/1388586426
* http://d.hatena.ne.jp/yohei-a/20141007/1412690972
{AWS(CloudFront+S3)+Node.js} 署名付きURLを使用したプライベートコンテンツの配信

## はじめに

短期間のみ有効な署名付き URL を使用してプライベートコンテンツを配信するにあたり、Node.js環境下での情報が公式にはのっていなかったので、その対応方法をメモとして残します。

公式ガイド
https://docs.aws.amazon.com/ja_jp/AmazonCloudFront/latest/DeveloperGuide/private-content-signed-urls.html

## 環境準備

1. プライベートコンテンツを格納するS3のバケットを作成する
1. 上記バケットを非公開とする
1. CloudFrontのディストリビューションを作成する
 - CloudFront経由に限り上記S3バケットにアクセス出来る用に設定する
1. 署名付きURL生成のためにCloudFront のキーペアを作成する
 - この処理だけはAWSアカウント（ルートアカウント）が必要

〇参考URL
https://dev.classmethod.jp/cloud/aws/cf-s3-deliveries-use-signurl/
http://blog.mekachan.net/?p=105

## コード実装

現在JavaScriptのaws-sdkライブラリではCloudfrontの署名付きURL生成がサポートされていないため、「aws-cloudfront-sign」ライブラリを活用して対応する

## aws-cloudfront-sign

https://www.npmjs.com/package/aws-cloudfront-sign

サンプルコード

```js
// 30分だけ有効な署名付きURLを生成するコード
var cf = require('aws-cloudfront-sign')
var options = {
  keypairId: 'XXXXXX',
  privateKeyPath: 'XXXX/XXXXXX-private-pk-XXXXX.pem',
  expireTime: (new Date().getTime() + 30 * 60 * 1000)
}
// CloudFrontの「Domain Name」を指定する
// https://${Domain Name}/${Origin path(S3バケット内のパス)}
var signedUrl = cf.getSignedUrl('https://dXXX.cloudfront.net/example.mp4', options);
console.log('Signed URL: ' + signedUrl);
```

options(オプション)の説明

| 項目 | 内容 |
|---|---|
| expireTime |有効期限（任意設定：省略時は30秒）指定する際はミリ秒で指定する |
| keypairId |作成したクラウドフロントキーペアのアクセスキー ID |
| privateKeyString<br>または<br>privateKeyPath|作成したクラウドフロントキーペアの秘密鍵ファイルパス  |

## 参考 S3上で署名付きURLを利用するの場合
このケースではクラウドフロントを介しません。
S3上で生成した署名付きURL経由で非公開バケット中のリソースへアクセスする方式です。
特別なライブラリは不要でaws-sdkで対応可能です。

```js
const AWS = require('aws-sdk')

AWS.config.update({
  accessKeyId: 'XXXXXX',
  secretAccessKey: 'XXXXXX'
  // ,
  // region: 'ap-northeast-1'
})
const s3 = new AWS.S3()

const url = s3.getSignedUrl('getObject', {
    Bucket: 'private-bucket',
    Key: 'example.mp4',
    Expires: 60 // 単位は秒
})

console.log(url)
```

## 参考（AWS-CLI)の場合

```shell
aws cloudfront sign
 --url http://dXXX.cloudfront.net/example.mp4
 --key-pair-id XXXXXX
 --private-key file://C:/XXX-private-pk-XXXXX.pem
 --date-less-than YYYY-mm-dd
```
amazonlinuxのdockerイメージにテスト環境を作る話

書いてたらけっこうな分量になってしまったのでgithubにした。

https://github.com/arc279/docker_ami_ansible_sample


開発用

* amazonlinux の dockerイメージに
* `ansible` で `rbenv` を入れて
* `sinatra` を動かす

ところまで。


ほんとは EC2 に `capistrano` でデプロイする際の、`capistrano` を手元でテストできる環境を作りたかったのが出発点だけど、
一度に色々やるととっ散らかるのでとりあえずここまで。

_deploy_ と _provisioning_ は粒度が違うというか、別レイヤーだし。
jsで配列を条件分岐で複数要素を削除したい

ちょっと悩んだ。ただ、こんなものあまり使わないでしょう。

# filterを上手く使おう

```js.js
var array = ['hoge','hogehoge','foo','hogege','foo','hogehoge'];
var index_array = [];
var target = 'hogehoge';

array.forEach(function(value,index){
	if(value == target){ 
		// 該当する場合
		index_array.push(index);
	};
});


var newArray = array.filter((value,index) => {
	return !index_array.includes(index);
});

console.log(newArray); // ['hoge','foo','hogege','foo']
```

forEachで該当するものは、index保存しておいて、後からfilterで処理。

filterはfalseのものを自動でどっかやってくれるので便利りり

## 追記：もっと楽にできた

index_arrayなんかいらんから、もっと早く書けた。

```
 var array = ['hoge','hogehoge','foo','hogege','foo','hogehoge'];
 var target = 'hogehoge';
 var newArray = array.filter((value, index) => {
    return value != target;
 });
 console.log(newArray);
```

@le_panda_noir さんありがとうございます。


```
const array = ['hoge','hogehoge','foo','hogege','foo','hogehoge'];
const target = 'hogehoge';
const newArray = array.filter(value => value !== target);
console.log(newArray); //  ["hoge", "foo", "hogege", "foo"]
```

@RikutoYamaguchi さんありがとうございます。
外部SVGスプライトのsvgxuse.jsによるIE11対応

# 背景

インラインSVGの`<use>`による外部SVGファイルの参照は、SVGファイルの一元化やコード軽量化などに一役買っている。
しかし、そのままではIE11では表示されない。IE11では`<use>`タグの外部参照は対応していないのだ。

そのため、泣く泣く`<img>`タグに変更したり、インラインSVGの`<defs>`に書き換えた方も多くいらっしゃるのではないだろうか。

しかし、インラインSVGの`<defs>`に書き換えると、そもそも外部SVGファイルとして一元管理ができなくなる上、html内のコード量も増える。
その他の手法として`<img>`に置き換える手法もあるが、この場合はスプライトできなくなってしまう。しかも、CSSによるfillの調整もできないので、「ロゴをスクロール時に白抜き・デフォルトカラーに切り替えたい」等には対応できない。

そこで今回、[IcoMoon](https://icomoon.io/)でのファイルであればIE11でも正常に表示がされていたので何が違うか探ってみると、「[svgxuse.js](https://github.com/Keyamoon/svgxuse)」というJSが読み込まれていた。

この、[IcoMoon](https://icomoon.io/)で使用している[svgxuse.js](https://github.com/Keyamoon/svgxuse)を読み込むことで、IE11でもインラインSVGの`<use>`による外部SVGファイルの参照が可能となった。

以下はその手順の覚書である。
（なお、svgxuse.jsで何をどうしているのかは割愛させて頂く。あくまで「こうしたら出来た」の共有のつもりなので。）

#基本的な手順

- AIでロゴを作成する
- SVG形式で保存
- SVGファイルをエディタで開き、グルーピングしたいパスを`<g>`タグ等で囲む（`<symbol>`タグ等でも可）
- `<g id="baseColor”>` のようにIDを付与

HTML内で下記のように`<use>`タグによりSVGファイルへのパスを記述
※外部参照になるため、元のSVGファイルのviewBox属性は必須

```HTML
<header>
    <h1>
        <a href="/">
            <svg viewBox="0 0 928 240">
                <use xlink:href='/_assets/img/common/logo.svg#baseColor' class="baseColor"></use>
                <use xlink:href='/_assets/img/common/logo.svg#subColor' class="subColor"></use>
            </svg>
        </a>
    </h1>
</header>
```

# IE11への対応
このままの状態では<use>タグの外部参照はIE11では対応していないため、表示されない。

SVGの元データのコードをインラインSVGで記述し`<defs>`でwrap（その場合はCSSで非表示に）する方法もあるが、コードが冗長になってしまうためJSによる外部参照を行う。

```HTML
<script defer src="/_assets/js/svgxuse.js"></script>
```

[svgxuse.js](https://github.com/Keyamoon/svgxuse)
html内でdeferにより参照する。
※Webサーバー上でホストされている必要があるため、ローカルでのプレビュー時はlocalhost等、ホストが存在している状態で確認を。
【Android】smoothScrollToPositionの移動速度を変えたい

## アイテムを移動させる時に移動速度も変えたい

<img src="https://qiita-image-store.s3.amazonaws.com/0/223159/e1dcc6c8-2277-4e35-7464-73f984718474.gif" width=40%>

```Kotlin:SpeedyGridLayoutManager.kt
class SpeedyGridLayoutManager : GridLayoutManager {
    var MILLIS = 155f

    constructor(context: Context, spanCount: Int, orientation: Int, reverseLayout: Boolean) : super(context, spanCount, orientation, reverseLayout) {}

    override fun smoothScrollToPosition(recyclerView: RecyclerView, state: RecyclerView.State?, position: Int) {

        val linearSmoothScroller = object: LinearSmoothScroller(recyclerView.context) {

            override fun computeScrollVectorForPosition(targetPosition: Int): PointF? {
                return this@SpeedyGridLayoutManager.computeScrollVectorForPosition(targetPosition)
            }

            override fun calculateSpeedPerPixel(displayMetrics: DisplayMetrics): Float {
                return MILLIS / displayMetrics.densityDpi
            }
        }

        linearSmoothScroller.targetPosition = position
        startSmoothScroll(linearSmoothScroller)
    }
}
```

MILLSを変えれば移動速度も変わります。
あとは、#setLayoutManagerしてあげれば使えます。
naming > 進数の対応英語 > numeration systems | numeral system | number systems

2進数、10進数、16進数などの「進数」。
これを英語のタグとして付ける時にどういう名前を使うのがいいだろうか。

- Numeration system(s)
    - どこかで見た記憶がある
        - 「基礎からわかる数・数式と図形の英語―豊富な用語と用例」だろうか？
    - それをもとにタグ付けしていた
- Numeral system(s)
    - https://en.wikipedia.org/wiki/Numeral_system
- Number system(s)
    - https://code.tutsplus.com/articles/number-systems-an-introduction-to-binary-hexadecimal-and-more--active-10848

### Stack Overflow

Tags検索で見つかったのは以下。

- numeration-system: 0記事
- [number-systems](https://stackoverflow.com/questions/tagged/number-systems): 65記事
- [numeral-system](https://stackoverflow.com/questions/tagged/numeral-system): 1記事

Stack Overflowのタグに準じておくと、[Stack Overflowのタグ検索機能](https://stackoverflow.com/tags)でタグ名の確認ができる。

"-"表記をcamelケースにするかどうかは、生成済タグとの兼ね合いもある。

GitHubでの使用率も検討に入るが、こちらはタグの部分検索を使ったことがない。
" docker: Error response from daemon: Get https://registry-1.docker.io/v2/library/nginx/manifests/latest: unauthorized: incorrect username or password." とでたら


```
docker: Error response from daemon: Get https://registry-1.docker.io/v2/library/nginx/manifests/latest: unauthorized: incorrect username or password.
```


とでたら

```
$ docker logout
```

を試してみて
[React Native]ReactNativeとWebViewのデータ連携

## 概要

- ReactNativeのアプリでWebViewを使う時に、Reactの世界とWebViewの世界でデータのやり取りをする方法を調べたのでそれの紹介

## 本題

### WebViewとは

- スマホアプリの中にWebページを表示する仕組み

### ReactNativeのWebView

- ReactNativeでは`WebView`というコンポーネントが用意されている
- `WebView`コンポーネントにURLを属性で渡すとアプリでWebページを表示できるようになる
- ViewとかTextとかのコンポーネントと同じ感覚で配置するだけで使える

### 何をやりたいのか

- アプリの中にWebViewを埋め込む時に相互にデータのやりとりをしたい
    - WebView内で入力した情報をアプリ側で使用したいとか
    - アプリ側で持っている情報をWebView内に埋め込みたいとか

### アプリ->WebView

- アプリからWebViewに情報を渡す方法

#### やり方

- アプリからWebViewへJavaScriptのコードを渡して実行できる
- 以下の2パターンがある

##### WebView作成時に渡すパターン

- WebViewに`injectedjavascript`という属性でJavaScriptのコードを渡す
    - https://facebook.github.io/react-native/docs/webview.html#injectedjavascript

```js
const jsCode = `
const inputName = document.getElementById('input-name');
inputName.value = 'ozaki';
`
class xxx extends Components {
  render() {
    return(
      <WebView
        source={'http://localhost:8080/'}
        injectedJavaScript={jsCode}
      />
    )
  }
}
```

- 渡したコードはWebView生成後に画面内に埋め込まれる
    - 上記の例では画面の描画直後に実行されて、入力域に`ozaki`と入った状態で画面が表示される
- JavaScriptのコードはStringで渡さなければいけないのでちょっと扱いづらい

##### WebView作成後に実行するパターン

- WebViewのrefに対して`injectjavascript`を実行すると引数で渡したJavaScriptが実行される
    - https://facebook.github.io/react-native/docs/webview.html#injectjavascript

```js
const jsCode = `
const inputName = document.getElementById('input-name');
inputName.value = 'ozaki';
`
class xxx extends Component {
  someFunc() {
    this.webview.injectjavascript(jsCode)
  }
  render() {
    return(
      <WebView
        ref={ref => this.webview = ref}
        source={'http://localhost:8080/'}
      />
    )
  }
}
```

- このパターンでは`injectjavascript`の引数に渡したJavaScriptが実行される
    - 上記の例では、`someFunc`を呼ぶと、入力域に`ozaki`と値が入ることになる
- こちらもJavaScriptのコードはStringで渡さないといけない

### WebView->アプリ

- WebViewからアプリに情報を渡す方法

#### postMessageとonMessage

- Webページにはwindowに対して`postMessage`という関数が紐付けられている
- この`postMessage`を実行するとWebViewからアプリにデータの送信ができる
- アプリ側は`onMessage`メソッドを定義することで`postMessage`の送信内容を受信することができる
    - https://facebook.github.io/react-native/docs/webview.html#onmessage

```js
// ReactNative側
class xxx extends Component {
  onMessage = (event) => {
    const { data } = event.nativeEvent;
    if (data === 'OK') {
      alert('OK!');
    } else if (data === 'NG') {
      alert('NG');
    }
  };
}

// WebView側
window.postMessage('OK');
```

- `postMessage`の引数は`event.nativeEvent.data`で取得できる
- `postMessage`の引数はStringしか渡すことができない

## まとめ

- アプリとWebViewのデータ連携はあまり柔軟性がない
    - セキュリティ的な要因とかなのかな？
- とはいえ、最低限の連携はできるので大抵のケースはこれだけできれば十分だと思う

## 追記

- バージョンが上がっていつの間にかドキュメントにSecurityWarningが追加されていました

> Security Warning: Currently, onMessage and postMessage do not allow specifying an origin. This can lead to cross-site scripting attacks if an unexpected document is loaded within a WebView instance. Please refer to the MDN documentation for Window.postMessage() for more details on the security implications of this.

- https://facebook.github.io/react-native/docs/webview.html
- https://github.com/facebook/react-native-website/pull/113
Linuxで標準出力とファイルの両方に「リアルタイムで」出力する

# したいこと
何らかのプログラムで実行途中のログが標準出力へと出力されるが，実行に時間がかかるので，途中経過を「リアルタイムで」確認しながら動かしたいし，同時にその記録をファイルに残しておきたい．

# パイプでteeコマンドへ流してみる → 少々もやもや
そういえばteeコマンドというのがあったな，ということで，
```
$ ./myprogram | tee output.log
```
ところが，Ubuntu 16.04.03 LTS で試したところ（2018.02.01) 出力がバッファされてしまうようで，しばらく時間が経ってから標準出力にバサッと書き出され，しばらくまた時間が経ってから…というのを繰り返す．ちゃんと標準出力にもファイルにも出力されるが，「リアルタイムで」ないところがモヤモヤする．

# 解決方法
調べてみると，[Stack Overflow の記事](https://stackoverflow.com/questions/11337041/force-line-buffering-of-stdout-when-piping-to-tee) で，こういうのがあって，試してみると成功し，「リアルタイムで」出力されるようになった．
```
$ script -c ./myprogram /dev/null | tee output.log 
```
## 検証環境 (2018.02.02)
|OS              |バージョン|
|---             |---:     |
|Linux Ubuntu    |16.04.03 LTS |

なお，Ubuntuにはほとんど手を入れていない状態．
How to Delete ESXi 6.5 datastore with .locker ScratchLocation

### Error

 When deleting the datastore with .locker directory = ScratchConfigDir, it cannot be deleted - busy


### How to fix

```shell-session
vim-cmd hostsvc/advopt/update UserVars.SuppressShellWarning long 1
```

```shell-session
vim-cmd hostsvc/advopt/view ScratchConfig.ConfiguredScratchLocation

(vim.option.OptionValue) [
   (vim.option.OptionValue) {
      key = "ScratchConfig.ConfiguredScratchLocation", 
      value = "/vmfs/volumes/5a5d8564-a4e94afa-2926-901b0e6e4600/.locker"
   }
]
```

- Now change **ScratchConfig.ConfiguredScratchLocation** -> /tmp

```shell-session
vim-cmd hostsvc/advopt/update ScratchConfig.ConfiguredScratchLocation string /tmp

cat /etc/vmware/locker.conf
/tmp/.scratch 0
```

- Remove **.locker**

```shell-session
rm -rf /vmfs/volumes/5a5d8564-a4e94afa-2926-901b0e6e4600/.locker
```

- Reboot
![2018-02-02_141712.jpg](https://qiita-image-store.s3.amazonaws.com/0/114634/7979cb00-8da2-a897-1fb7-99dbb12c5689.jpeg)

- Remove the datastore - Done :relieved: 


### Reference

cf. http://adis.ca/entry/2016/partition-esxi-disks-cli/
Unity 5.6.3 + SteamVR Plugin 1.2.3 でViveのコントローラが表示されない問題

# Unity 5.6.3 + SteamVR Plugin 1.2.3 でViveのコントローラが表示されない問題

Unity 2017を使えって話はさておき、これから何度もはまりそうなので忘備録です。

## 1.【SteamVR_UpdatePoses】を更新

deprecatedということで、コンポーネントを入れれない状態（DestroyImmediate(this)でAddした瞬間、自分を殺す状態）になってるのでソースを書き変え

```csharp:SteamVR_UpdatePoses.cs
//======= Copyright (c) Valve Corporation, All rights reserved. ===============
//
// Purpose: Helper to update poses when using native OpenVR integration.
//
//=============================================================================

using UnityEngine;
using Valve.VR;

[ExecuteInEditMode]
public class SteamVR_UpdatePoses : MonoBehaviour
{
#if !(UNITY_5_6)
    void Awake()
    {
        var camera = GetComponent<Camera>();
        camera.stereoTargetEye = StereoTargetEyeMask.None;
        camera.clearFlags = CameraClearFlags.Nothing;
        camera.useOcclusionCulling = false;
        camera.cullingMask = 0;
        camera.depth = -9999;
    }
#endif
    void OnPreCull()
    {
        var compositor = OpenVR.Compositor;
        if (compositor != null)
        {
            var render = SteamVR_Render.instance;
            compositor.GetLastPoses(render.poses, render.gamePoses);
            SteamVR_Events.NewPoses.Send(render.poses);
            SteamVR_Events.NewPosesApplied.Send();
        }
    }
}
```
※SteamVR Plugin 1.2.0のパクリ

## 2.【Camera(eye)】に作成したコンポーネントを入れる

![image.png](https://qiita-image-store.s3.amazonaws.com/0/79067/d70d7782-1377-d384-28e6-3dafe32a1972.png)

これでコントローラが表示されます
Androidアプリ制作で、strings.xmlに代入したい

## string.xmlとは
アプリ内で使う文字列を定義する。
別にファイル名は`strings`である必要性は無い。何でもよい。
でも、変える方が分かりづらい。

例えば、

```xml
<resources>
    <string name="app_name">Application Name</string>
<resources>
```

としておく。すると、画面デザインのxmlで

```xml
<TextView  
    android:id="@+id/title"  
    android:layout_width="wrap_content"  
    android:layout_height="wrap_content"  
    android:text="@string/app_name"  
    />  
```

みたいにしておけば全て同じ`Application Name`が表示される。
一括での変更が楽。
もちろん、Java内でも使える。

```java
String title = getString(R.string.app_name);
```

## 例えば、「ようこそ、〇〇さん！」の場合
流石に、

```java
String title = getString(R.string.youkoso) + name + getString(R.string.san);
```

みたいなのは無しだというのはご理解いただけると思う。
「〇〇さん、ようこそ！」に変更したい、となった時に変更する箇所が多いし。

こういう場合は、strings.xml内に

```xml
<string name="message">ようこそ、%1$dさん！</string>
```

としておくと、後で代入することができる。
こんな感じに。

```java
String str = getString(R.string.message, name);
```

更には、複数の場合も対応している。
`%n`の所で順番を示しているので、

```xml
<string name="message">あなたは%2$s人目のお客様です！ようこそ、%1$dさん！</string>
```

みたいに定義しておけば、

```java
String str = getString(R.string.message, name, count);
```

という具合に使える。
urfave/cliのグローバルオプションへのアクセス方法

[urfave/cli: A simple, fast, and fun package for building command line apps in Go](https://github.com/urfave/cli)

# 結論

Actionでは`c.String`などで取得できる。
Commandでは`c.GlobalString`と`Global`を付ける。


# 事象

```
USAGE:
   mycommand [global options] command [command options] [arguments...]
```

の`global options`を渡しているのにcommandアクションから`c.フラグ`で参照できなかった。


# コード

```go
package main

import (
        "fmt"
        "github.com/codegangsta/cli"
        "os"
)

func main() {
        app := cli.NewApp()
        app.Name = "test"
        app.Usage = "test"
        app.Version = "1.0.0"

        app.Flags = []cli.Flag{
                cli.BoolFlag{
                        Name: "b",
                },
                cli.StringFlag{
                        Name: "s",
                },
        }

        app.Commands = []cli.Command{
                {
                        Name:   "test",
                        Action: testAction,
                },
        }

        app.Action = func(c *cli.Context) {
                fmt.Printf("c.GlobalFlagNames()  : %+v\n", c.GlobalFlagNames())
                fmt.Printf("c.String(\"s\")        : %+v\n", c.String("s"))
                fmt.Printf("c.Bool(\"b\")          : %+v\n", c.Bool("b"))
                fmt.Printf("c.GlobalString(\"s\")  : %+v\n", c.GlobalString("s"))
                fmt.Printf("c.GlobalBool(\"b\")    : %+v\n", c.GlobalBool("b"))
        }

        app.Run(os.Args)
}

func testAction(c *cli.Context) {
        fmt.Printf("c.GlobalFlagNames()  : %+v\n", c.GlobalFlagNames())
        fmt.Printf("c.String(\"s\")        : %+v\n", c.String("s"))
        fmt.Printf("c.Bool(\"b\")          : %+v\n", c.Bool("b"))
        fmt.Printf("c.GlobalString(\"s\")  : %+v\n", c.GlobalString("s"))
        fmt.Printf("c.GlobalBool(\"b\")    : %+v\n", c.GlobalBool("b"))
}
```

# 結果

```
> ./testgo -h
NAME:
   test - test

USAGE:
   testgo [global options] command [command options] [arguments...]

VERSION:
   1.0.0

COMMANDS:
     test
     help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   -b
   -s value
   --help, -h     show help
   --version, -v  print the version
> ./testgo -b -s text
c.GlobalFlagNames()  : [b s]
c.String("s")        : text
c.Bool("b")          : true
c.GlobalString("s")  : text
c.GlobalBool("b")    : true
> ./testgo -b -s text test
c.GlobalFlagNames()  : [b s]
c.String("s")        :
c.Bool("b")          : false
c.GlobalString("s")  : text
c.GlobalBool("b")    : true
```

***

commandオプションとの住み分けのためだろう。
オプションの取得方法がわからず、(コマンドなしのfuncなら)`c.フラグ`形式で取れると判明。軽く調べた範囲でコマンドからグローバルオプションを参照するコードがなくこっち原因とハマリ。



# 参考

[Go言語でサクッとコマンドラインツールをつくる | eureka tech blog](https://developers.eure.jp/tech/golang_commandlinetool/)

グローバルオプションを扱うときは`Global`なしで動くところであっても`Global`を必ずつけるようにすると、初心者のうちは混乱しないかも。