OmniAICreator/Qiita-1.07M huggingface dataset:
Railsでhamlを使うために最低限必要なこと

# 

## gem
- haml-rails
    - railsでhamlがかけるようになる(ただhamlを書くだけであればこのgemを入れるだけでOK)
    - [https://github.com/indirect/haml-rails](https://github.com/indirect/haml-rails)
- erb2haml(途中からhamlにしたい場合などに入れる)
    - erbをhamlに変換する
    - [https://github.com/dhl/erb2haml](https://github.com/dhl/erb2haml)


#### Gemfileに必要なgemを記載してbunle install

```rb:Gemfile
gem 'haml-rails'
gem 'erb2haml'
```

## 既存のerbをhamlに変換(erb2hamlを入れた場合のみ)
```console
$ rake haml:replace_erbs
```
実行するとこんな感じでerbがhamlに変換される
![](https://gyazo.com/a9772f6a1cb096cd1192ee121757acc0.png)


ちなみに、下記のコマンドを叩くと他のhamlに関するrakeコマンドがあることが分かります。

```console
$ rake -T | grep haml
```
(小さくてすいません)
<img width="1095" alt="haml.png" src="https://qiita-image-store.s3.amazonaws.com/0/137894/16058cb2-e754-e15d-f04e-952a607cddda.png">


## hamlがよくわからない方は。。。
[https://html2haml.herokuapp.com/](https://html2haml.herokuapp.com/)
このサイトでhtmlからhamlへの変換を確認できます。
ドキュメントを見ながらこちらのサイトで気軽に動作確認すればhamlもすぐ理解できると思います！
[Firebase Push通知 iOS] アプリバックグラウンド時に didreceiveRemoteNotification が呼ばれない

#はじめに

FirebaseのPush通知を実装する際に、少しはまってしまい、記事にもそこまでされてなかったようなのでメモ程度に書きます。

#内容
アプリのバックグラウンド時に、push通知を受けた時に、以下のメソッドを呼び出そうとしたのですが呼べませんでした。

```swift:AppDelegate.swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    switch application.applicationState {
    case .inactive:
         print(userInfo)
    case .active:
         print(userInfo)
    case .background:
         print(userInfo)
    }
}
```

push通知は受信できるのですが、`didReceiveRemoteNotification`メソッドが呼ばれず、
アプリがアクティブな時は上記のメソッドを呼べました。

#解決方法
[Firebase Cloud Messaging の HTTP プロトコル](https://firebase.google.com/docs/cloud-messaging/http-server-ref?hl=ja)
こちらの記事を参考に解決しました。

push通知を送信する際に、送信側でリクエストボディに

```
 "content_available" : true
```

を追加しておく必要があるようで、デフォルトではアプリがバックグラウンドにある場合、アプリがスリープ状態にあります。上記のキーバリューを送信してあげないと、スリープ状態のままなのでアプリバックグラウンド時に`didreceiveremotenotification`が呼ばれません。

※ Firebaseドキュメントの引用
<img width="778" alt="スクリーンショット 2017-12-30 9.23.38.png" src="https://qiita-image-store.s3.amazonaws.com/0/195288/0b2bf89e-2b7d-def0-2ccd-2884a23936ee.png">


push通知自体はきているのでクライアント側で制御できるものかと思っていたんですが、送信側も意識する必要があるみたいだったので、忘れないうちに書きました。

何かアドバイスや不足点などありましたら、コメントいただければ幸いです。m(_ _)m
%o 便利

Node.js Advent Calendar が埋まってなかったので、代わりに細かすぎて伝わりにくいTips入れていきます。

# util.format

あんまり単体では使ってないかもしれませんが、所謂`%s` や `%d` といった formatter を渡して文字列を出力する、 `printf` のような振る舞いをする関数です。

```javascript
const util = require('util')
const foo = 'Hello World'

const str = util.format('Test String %s', foo)　// Test String Hello World
```

「単体では」と銘打ったのは理由があって、 `console.log` や `console.warn` といった `console` のメソッドが内部的に利用しているのがこの `util.format` だからです。 Template String Literal ができて文字列埋め込みが簡単になったとはいえ、僕個人的にはまだ `console` で表記するのにこの `%d` や `%s` を使うことが多いです。

おさらい：
 
- %s - 文字列
- %d - 浮動小数もしくは整数の数字
- %i - 整数
- %f - 浮動小数
- %j - JSON, もしも再帰の値を含む場合は例外を投げるわけじゃなく、 `[Circular]` として表示する。

# 本題の `%o`

で、 `%o` ですが、これは `object` を文字列化するのに使います。 `%j` は内部的に `JSON.stringify` できるかを試した後に再帰が含まれている例外だったら  `[Circular]` にしますが、 `%o` の場合は `object` の `property` を一つ一つ表示します。

**ちなみに v8.4.0 からの新機能です。**

`object` の中身をちらっと確認するのにわざわざ `console.log(JSON.stringify(obj))` してるのであれば `%o` のフォーマッターを覚えたほうが良いです。

```javascript
const obj = {
  foo: 'bar'
}

console.log(`Hello ${obj}`) // Hello [object Object]
console.log(`Hello ${JSON.stringify(obj)}`) // Hello {"foo":"bar"}
console.log('Hello %j', obj) // Hello {"foo":"bar"}
console.log('Hello %o', obj) // Hello { foo: 'bar' }

const circularObj = {
  foo: 'bar',
}
circularObj.bar = circularObj

console.log(`Hello ${circularObj}`) // Hello [object Object]
console.log(`Hello ${JSON.stringify(circularObj)}`) // 例外が投げられる
console.log('Hello %j', circularObj) // Hello [Circular]
console.log('Hello %o', circularObj) // Hello { foo: 'bar', bar: [Circular] }

// 適当に表示するだけなら %o でイナフ
console.log('Hello %o', 'aaaa') // Hello 'aaaa'
console.log('Hello %o', 122) // Hello 122
console.log('Hello %o', Symbol('aaa')) // Hello Symbol(aaa)

// Enumerableじゃないものは表示したくなければ %O を覚えると良い。

console.log('Hello %o', [1,2,3]) // Hello [ 1, 2, 3, [length]: 3 ]
console.log('Hello %O', [1,2,3]) // Hello [ 1, 2, 3 ]
```

でまぁ、中身的には `util.inspect` を実行しています。余談ですが、 `util.inspect` も便利です。

[util.inspect API](https://nodejs.org/docs/latest/api/util.html#util_util_inspect_object_options)

`%o` はかなり雑に表示できるので、一番使い勝手が良いです。 `%j` は今後はあまり使われないものになると思います。
[Mac]自作アプリの配布用ディスクイメージの作り方

[dmgbuild](https://pypi.python.org/pypi/dmgbuild)というツールを使って、PythonやElectronなどで作成したアプリ(それ以外でも可)を配布するためのディスクイメージファイルの作成方法を紹介します。

Macの野良アプリはdmgという拡張子のディスクイメージファイルで配布するのが一般的です。通常dmgファイルを開くと中にアプリが入っていて、Applicationフォルダにコピーすることでインストールが完了します。dmgbuildはそのようなdmgファイルを作ることができます。


# インストール

dmgbuild自体はPythonで書かれたツールです。次のようにしてインストールします。

```
pip install dmgbuild
```

# 設定
dmgbuildのソースにそのまま使えるサンプルがありますので、それを利用します。

```
wget https://raw.githubusercontent.com/al45tair/dmgbuild/master/examples/settings.py
```

settings.pyを編集すれば、ライセンスや、アイコンなどをカスタマイズすることができますが、取り急ぎデフォルトのまま使います。

# 実行

ここでは[この記事](https://qiita.com/gollowars/items/387d5fecd29c26cace99)にあるPythonのQt5アプリの配布ディスクを作ってみます。記事に従って`qt.app`作成後、次のコマンドを実行します。

```
dmgbuild -s settings.py -D app=qt.app "My Application" MyApp.dmg 
```

ファインダーでみると見慣れたdmgのアイコンが出来上がっています。

![Screen Shot 2017-12-29 at 3.31.39 PM.png](https://qiita-image-store.s3.amazonaws.com/0/13775/185e2a2c-56c8-6606-7d1f-2da11db60470.png)

# インストールしてみる

MyApp.dmgをダブルクリックすると、ディスクイメージがマウントされ、インストール画面になります。

![Screen Shot 2017-12-29 at 3.33.21 PM.png](https://qiita-image-store.s3.amazonaws.com/0/13775/0d645edd-0d5c-8f8b-bcf8-398d6aa794d3.png)

アプリのアイコンをApplicationsにドラッグ＆ドロップして完了です。


# Electronアプリの配布
[Electron](https://electronjs.org/)で作ったアプリの配布イメージも作ってみました。次のアプリを例にやってみます。

https://github.com/bradtraversy/electronshoppinglist

```
git clone https://github.com/bradtraversy/electronshoppinglist
cd electronshoppinglist
npm install
npm run package-mac
cd release-builds/shoppinglist-darwin-x64
wget https://raw.githubusercontent.com/al45tair/dmgbuild/master/examples/settings.py
dmgbuild -s settings.py -D app=shoppinglist.app "shopping list" shopping.dmg
```

インストーラを起動してみたところ、アイコンがすでに正しくセットされています。
![Screen Shot 2017-12-29 at 3.51.51 PM.png](https://qiita-image-store.s3.amazonaws.com/0/13775/66105817-0393-5fe3-eaac-4f7ca6adef68.png)

アプリの作成も配布も従来の方法よりかなり手軽になりますね！
[JavaScript] slickで作ったカルーセルの自動再生がユーザー操作によって止まるのを防ぐ

slick
http://kenwheeler.github.io/slick/

ここ3年くらいずっと使っているカルーセルの定番ライブラリ。
ホバー中にautoplayが止まってしまうという現象があり調べているとどうやら仕様だった。

"slick autoplay not work" で検索したところ出てきたstackoverflow
https://github.com/kenwheeler/slick/issues/1021

`pauseOnHover` というオプションがあったのでこれで解決

他に、 `pauseOnFocus`, `pauseOnDotsHover` というオプションもあるので合わせて
ユーザー操作によって自動再生が止まるのは防げそうだ。

```js
$('#target').slick({
  autoplay: true,
  pauseOnFocus: false,
  pauseOnHover: false,
  pauseOnDotsHover: false
});
```
Pythonのプロファイリングと可視化

プロファイラは今まで何度も投稿されたネタですが、cProfileの出力をKCacheGrindとpyprof2calltreeとで可視化する方法の紹介です。 

KCacheGrindはプロファイリング結果を可視化するツールで、元々はC言語のValgrindプロファイラの可視化ツールとして開発されたようです。pyprof2calltreeはcProfileの結果をKCacheGrindで読み込めるようにする変換ツールです。


# 用意するもの
- KCacheGrind https://github.com/KDE/kcachegrind
- GraphViz http://www.graphviz.org/download/
- pyprof2calltree https://pypi.python.org/pypi/pyprof2calltree

# 実験環境
OS: macOS High Sierra 10.13.2
Python3.6: Homebrewでインストールしたもの

# インストール

```
# MacではQtでコンパイルされたqcachegrindを使う。
brew install qcachegrind
brew install graphviz
```

```
mkvirtualenv prof -p $(which python3)
pip install pyprof2calltree
```

そのほかテスト用

```
pip install numpy
```


# 実行例

例題としてマンデルブロ集合計算の計算をm.pyというファイル名で保存します。

```py
import numpy as np

def mandel(z):
    maxiter = 80
    c = z
    for n in range(maxiter):
        if abs(z) > 2:
            return n
        z = z*z + c
    return maxiter
def mandelperf():
    r1 = np.linspace(-2.0, 0.5, 26)
    r2 = np.linspace(-1.0, 1.0, 21)
    return [mandel(complex(r, i)) for r in r1 for i in r2]

assert sum(mandelperf()) == 14791
```

cProfileを使って実行し、プロファイルの結果をm.cprofファイルに保存します。

```bash
python -m cProfile -o m.cprof m.py
```

pyprof2calltreeを-kオプションで立ち上げるとkcachegrindが起動します。

```bash
pyprof2calltree -k -i m.cprof
```

# 実行画面

Call Graphを選択するとグラフィカルに呼び出し順、実行回数、実行時間、全実行時間に占める割合が表示されます。

<img width="1140" alt="Screen Shot 2017-12-29 at 2.36.32 PM.png" src="https://qiita-image-store.s3.amazonaws.com/0/13775/14073ee7-bbfd-12ad-d216-8b1a31484a4a.png">

Call Graphの他にも分析に便利な機能がいくつもありますので試してみてください。
GLSL ES 3.0で型変換はどうやればいいのか？

む、ところで、GLSLにはキャスト（型変換）に相当する演算子が見当たらない。uintをfloatに変えるにはどうしたらいいのか。。

[リファレンス・ガイド](https://www.khronos.org/files/webgl20-reference-guide.pdf)を見ると、`floatBitsToUint`,`uintBitsToFloat`というのがある。しかしこれはビット配列を同じなまま、型変換をするというものである。

むむう。どうしたらよいのか。。と思ったら簡単だった。。**コンストラクタを使えばよい**のだった。。

```glsl
float floatval = 1.0;

uint a = uint(floatval);//コンストラクタで型変換

```

これで小一時間悩んでしまった。。

以上
homeパーティションを維持したまま再インストールの方法

# やりたいこと
　ubuntuインストール時に、ディレクトリごと（例えば/boot,/,/home,/tmp,/var)にパーティションを分割してインストールした際に、一部のパーティションのデータを残して、残りパーティションは初期化＆インストールする方法
　ubuntuの再インストールなんて、普通はやらないと思うのですが、いざ、システムだけを再インストールしたいって思ったとき、バックアップからやり直すのは大変なので、やり方を残しておくことにしました。

# 最初にインストールしたときのパーティション
　（インストール方法は[ここ][link-1]を参考に。最初にパーティションを分けて、かつ、lvmを使ってインストールするときには、とても手間取った。。。）

- 物理パーティション（っていうのか？）

|Pri/Ext|partion|filesystem|mount position|
|----|---|---|---|
|プライマリ|/dev/sda1|ext4|/boot|
|プライマリ|/dev/sda2|ext4|/|
|プライマリ|/dev/sda3|ext4|/用の予備|
|拡張|/dev/sda5?|lvm||

- LVM設定(/dev/sda5の一つでVolumeGroupとしてます）

|VolumeGroup|LogicalVolume|filesystem|mount position|
|----|----|---|---|
|vg_int|LV_home|ext4|/home|
|vg_int|LV_tmp|ext4|/tmp|
|vg_int|LV_var|ext4|/var|

# partitioner開始後
　日本語でのインストール時の選択肢に注意
1. 「手動」を選択
2. 「ガイドによるパーティショニング」を選択
3. 「reuse partition, SCSI1 (,0,0,) パーティション 2。(sda)」を選択
4. これでlvm以外は、マウントポジションまで復活（しているはず）
5. 4で情報の復活したパーティションのうち、初期化したいパーティションを選択して、パーティションの初期化：「既存のデータをそのまま使う」→「初期化」に変更（僕の場合は全部）
6. lvmのマウントポジションは自動で設定してくれないので、各LV毎に再設定。初期化or既存のまま を選択（僕の場合は/homeだけを、既存データのデータをそのまま使うに設定）
7. 「パーティショニングの終了とディスクへの変更の書き込み」を実施。この際に初期化されるパーティションに、残しておきたいパーティションが入っていないことを確認
8. あとは、いつものようにインストール

で、いけるはず。

　一部のパーティションを残すことによる副作用の可能性は否定できませんが、/homeを残せるのは個人的にはうれしいので。

[link-1]:https://qiita.com/TsutomuNakamura/items/1b7928b3595a6ca2a304
MariaDBをインストール

#前提条件
rootの権限を実行できるユーザーでSSHでサーバーに接続後


#remi用の設定パッケージをインストール

```
# rpm -Uvh http://rpms.famillecollet.com/enterprise/remi-release-7.rpm
```

#phpをインストール
データベースを管理するのにphpmyadminを使用する場合は以下のコマンドを実行

```
yum install --enablerepo=remi,remi-php71 php php-devel php-mbstring php-mysqlnd php-pdo php-gd
```

# MariaDBをインストール

```
# yum install mariadb-server
```

インストールしてOKかどうか聞かれますので、’y’キーとEnterキーを押して確定させてください。

```
・
・
・
Is this ok [y/d/N]: y

```

表示メッセージの最後に’Complete!‘と表示されれば成功です。

# 起動
DBの起動とサーバー再起動時に自動的に起動する設定を行います。

```
# systemctl enable mariadb
# systemctl start mariadb
```

# 初期設定

**mysql_secure_installation**でデータベースのパスワードの設定や初期設定を簡単に行ってくれます。

```
# mysql_secure_installation
```

```
・
・
・
Enter current password for root (enter for none):
```

最初の質問でパスワードを聞かれますが、設定してないので、空白のまま「Enter」。


```
・
・
・
Set root password? [Y/n]
```
次に、「rootのパスワードを設定しますか？」と聞かれますので、’Y‘を入力してEnterキーを押します。


```
・
・
・
New password:
```

New passwordを聞かれますので、新しいMySQL rootのパスワードを設定。
そしてパスワードを入力すると、

```
・
・
・
Re-enter new password:
```
再度パスワード入力を求められるので、先ほどと同じパスワードを入力してEnterキーを押します。
あとの質問は「yes」でOK。

**Thanks for using MariaDB!**が表示されたら、設定完了です。

MariaDBにログインできるかどうかを確認します。

```
# mysql -u root -p
```
パスワードの入力を求められるので、さっき設定したパスワードを入力。
入力画面が以下に変わったらログイン成功。

```
MariaDB [(none)]>
```

ログアウトは「exit」と入力してEnterキーを押します。

```
MariaDB [(none)]> exit
```

ログインできたらOK！
Nginx のインストール

よくやるのでメモ

## 前提条件
|OS・ミドルウェア|バージョン|
|:-----------|:-------|
|CentOS|CentOS Linux release 7.9.2009 (Core)|
|Ubuntu|20.04.3 LTS (Focal Fossa)|
|Nginx|nginx/1.21.4|

## CentOS の場合
### 手順

1. 必要なパッケージをインストールする

    ```
    # yum install yum-utils
    ```

2. Nginxのリポジトリ情報を登録する

    ```shell
    # vi /etc/yum.repos.d/nginx.repo
    ```
    
    ```nginx.repo
    [nginx-stable]
    name=nginx stable repo
    baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
    gpgcheck=1
    enabled=1
    gpgkey=https://nginx.org/keys/nginx_signing.key
    module_hotfixes=true
    
    [nginx-mainline]
    name=nginx mainline repo
    baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
    gpgcheck=1
    enabled=0
    gpgkey=https://nginx.org/keys/nginx_signing.key
    module_hotfixes=true
    ```

3. 使用するリポジトリを設定する

    ```
    # yum-config-manager --enable nginx-mainline
    ```

4. yum でインストール

    ```shell
    # yum -y install nginx
    ```

### 補足
以下のコマンドを入力することでリポジトリを登録することも可能

```sh
# rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
```
しかしながら上記コマンドの場合、登録されるのはstable版のリポジトリ情報となる。
Nginx公式としてはmainline版の利用を推奨しているようなので、今回はリポジトリ情報を自身で作成する方法を採用。

詳細は参考のリンクに記載されている。

## Ubuntu の場合
### 手順
1. 必要なパッケージをインストールする

    ```shell
    $ sudo apt install curl gnupg2 ca-certificates lsb-release ubuntu-keyring
    ```

2. Nginx リポジトリ認証用のキーを取得し、そのキーを追加する

    ```shell
    $ curl https://nginx.org/keys/nginx_signing.key | gpg --dearmor \
    | sudo tee /usr/share/keyrings/nginx-archive-keyring.gpg >/dev/null
    ```

3. キーが正しく設定されているか確認する

    ```shell
    $ gpg --dry-run --quiet --import --import-options import-show /usr/share/keyrings/nginx-archive-keyring.gpg
    
    # 次のような出力がされる
    pub   rsa2048 2011-08-19 [SC] [expires: 2024-06-14]                                                   
          573BFD6B3D8FBC641079A6ABABF5BD827BD9BF62                                                        
    uid                      nginx signing key <signing-key@nginx.com>
    ```

4. `/etc/apt/sources.list`ファイルにリポジトリ情報を追記する

    ```shell
    $ echo "deb [signed-by=/usr/share/keyrings/nginx-archive-keyring.gpg] \
http://nginx.org/packages/mainline/ubuntu `lsb_release -cs` nginx" \
    | sudo tee /etc/apt/sources.list.d/nginx.list
    ```

5. リポジトリの pinning を設定する

    ```
    $ echo -e "Package: *\nPin: origin nginx.org\nPin: release o=nginx\nPin-Priority: 900\n" \
    | sudo tee /etc/apt/preferences.d/99nginx
    ```

6. リポジトリ情報を更新してインストール

    ```shell
    $ sudo apt -y update
    $ sudo apt -y install nginx
    ```

## 参考
- [ディストリビューションのコードネーム](http://nginx.org/en/linux_packages.html#distributions)
- [NGINX 1.6 and 1.7 Released](https://www.nginx.com/blog/nginx-1-6-1-7-released/)
- [Installation instructions](http://nginx.org/en/linux_packages.html#instructions)
PHPで画像をアップロードする際のサイズ上限について

#PHPで画像アップロードをする時の注意
PHPで画像アップロード機能を作っている時こんなエラーが

>POST Content-Length of 8804460 bytes exceeds the limit of 8388608 bytes in Unknown on line 0

見たことないエラーで戸惑いました
調べてみると、**画像ファイルのアップロード上限を超えている**ことが判明

そこで、php.iniの以下の部分の値を変更してみた。（サイズは好みの値で）

- upload_max_filesize=1024M
- post_max_size=1024M
- memory_limit=1024M

そしてphp.iniを上書き保存し、もう一度アップロードを試してみるが、エラーが出る

あれっ　と一瞬焦りましたが、XAMPPを再起動させることで値が適用されました。
PHP自体の設定変更をした際は、サーバーの再起動が必要のようです:relaxed:
form要素からファイルダウンロードが発生する際にsendされているデータをchrome devtoolで確認する

普通だとNetworkタブを使えば通信内容は見られますが、ニッチなケースではそうもいかない場合があります。その場合の対処法です

## 別タブのファイルダウンロードの通信内容

form要素がsubmitされる場合、違う画面に遷移するような処理だと通信内容がNetworkタブに残りますが、submitされた時に別タブでファイルダウンロードするような処理では別タブでの通信内容が元のタブのコンソールには表示されません。
そういった場合にform要素がどういったデータを送信しようとしているのかをデバッグ表示する方法を紹介します。


## やり方

ブレイクポイントを仕掛けて下記の式をwatchしてjsonとしてデータを取得しました (実際にはform-urlencodedなはず)

たまたまjQueryがロードされているページでよかったですね

```
$(fooBarForm).serializeArray()
```


### 別解

- [Chrome の devtools でファイルダウンロードするときの通信を見たい](http://var.blog.jp/archives/71134230.html)

ただ、こちらの方法はaタグの場合に使うもので、formで遷移するような場合には違う方法が必要でした
cocoparのRaspberry Piケースがプロトタイピング用にいい感じ

cocoparのRaspberry Pi3用アルミ合金ケースがいい感じでしたのでご紹介します。
GPIOピンとカメラ端子、ディスプレイ端子の部分が開いています。
![IMG_1328.JPG](https://qiita-image-store.s3.amazonaws.com/0/222969/7b809534-a1f2-03b0-3cf6-6c9d6e7ad563.jpeg)
側面の端子部分は薄めに削り込まれているので大体のケーブルが問題なく挿せると思います。
![IMG_1329.JPG](https://qiita-image-store.s3.amazonaws.com/0/222969/ca6d2173-aa6a-f52f-efc6-8d8bed90edd0.jpeg)
microSDカードスロット部分も開いており、ケース装着状態で交換が可能。
![IMG_1330.JPG](https://qiita-image-store.s3.amazonaws.com/0/222969/c35beb6e-63ee-84b5-ed35-ce8ad0c98340.jpeg)
電源オンのインジケーターは黒いアクリル板越しに確認できます。
![IMG_1340.JPG](https://qiita-image-store.s3.amazonaws.com/0/222969/90ec9fd1-391f-28df-fad3-f180ea249b80.jpeg)
サンハヤトのRaspberry Pi用拡張ユニバーサル基板を付けたところです。隙間は3.5mmくらいなので、そのぐらいのスペーサを付ければグラつきません。
![IMG_1331.JPG](https://qiita-image-store.s3.amazonaws.com/0/222969/bc85c269-6da2-16e0-b82a-6766a47847d8.jpeg)
公式ケースと並べた感じ、直線的なのでスリムに見えます。
![IMG_1333.JPG](https://qiita-image-store.s3.amazonaws.com/0/222969/8449d9c4-ce56-f444-f296-cf87fdd10373.jpeg)
つーわけで以下から購入できます。
<a href="https://www.amazon.co.jp/gp/product/B01LYIT7BJ">Amazon | cocopar®Raspberry pi　3B/2B/B+CNC放熱超薄いアルミニウム合金保護ケース | cocopar | PCケース 通販</a>
【React】Linkが使えない！

以下のエラーが出た。Linkがどうしても使えない。。

```
Warning: Failed context type: The context `router` is marked as required in `Link`, but its value is `undefined`.
```
どなたかが書いていたのですが、

>Found it -- my bad! I had the component appearing outside the Router component!
https://github.com/ReactTraining/react-router/issues/4639

とあり、Linkの場所をよくみてみると、BrowserRouterコンポーネントの外に出てしまっていた。
BrowserRouterコンポーネントの中に入れてあげたらちゃんと画面が表示されるようになった。
Remix OS for PCをUSBブート起動で使ったみたがwi-fiが使えないのでイーサネットアダプターを使って接続してみた

# はじめに

2in1タブレットPCを購入したことによりAndroidも利用できるようにならないかと辿り着いたのがRemixOS
USBブート可能ということと仮想環境での動作ではないことでだいぶ前にインストールしてみたのですが
**wi-fiが正常に認識せず動作せずに断念・・・そして再び挑戦を行ってみた覚書です。**

# wi-fiを使えるようにしてみる

結論から書くとドライバー関係、設定の変更等いろいろ試してみたのですがどうにもなりませんでした。
**wi-fiが使用できない場合は直接Lanケーブル接続ができるパソコンでないと無理かなという感じです。**

# それならイーサネットアダプターをUSB接続してLANケーブルを接続したらどうなるか？

旅行用に購入して使用していた「**ちびファイ2**」を試しにUSB接続しLNケーブルをつないてみたところ
Internetランプがピカピカ点滅！！

![mzk-ue150n.jpg](https://qiita-image-store.s3.amazonaws.com/0/223901/472553e9-9a63-7f1d-eed9-5da794b5de39.jpeg)

https://www.planex.co.jp/products/mzk-ue150n/spec.shtml

[設定]->[Ethernet]でipを確認してみると正常に割り振られていました・・・・
こんな簡単につながる方法があったのに数ヶ月たどり着けませんでした



**ipは固定で設定したほうが安定する気がするので今はこんな感じになっています。**

![Screenshot_20171230-011719.png](https://qiita-image-store.s3.amazonaws.com/0/223901/fbb4ce07-a1e7-1786-2022-ae03997bc9ec.png)





# 初期設定

・日本語表示/入力をできるようにする
・セーフモードにならないようにする
・GooglePlayを使用できるようにする
※このあたりの設定はQiitaでも記事が確認できたので省略します

上記設定を行ってあとは好きなアプリを入れて普通に使用できています。

# まとめ

こちらの記事についてもRemixOSで作成してみたのですがなんの問題もなく使用できてます。
RemixOSを使ってみたいがネットに繋がらなかったという人は手持ちのEthernetアダプターを接続してみるとつながるかもしれませんよ

タッチパネルが使用できるPCでRemixOSを使うと本当にAndroidタブレットのような使い方ができます。


# 使用している環境

Remix OS for PC
http://www.jide.com/remixos-for-pc

Lenovo Yoga 710
https://www3.lenovo.com/jp/ja/notebooks/yoga/yoga-700-series/Lenovo-YOGA-710-11ISK/p/88YG7000723

ちびファイ2
https://www.planex.co.jp/products/mzk-ue150n/spec.shtml

あとはusbハブとusbマウスを接続しています

# 参考

Remix OS v3.0.207 の初期設定 (意外とできてない項目があるでしょう！)
https://qiita.com/javacommons/items/295f6443057d053a2d11
IFTTTを使ってAmazon echoで流れた音楽のタイトルと歌手名をslackとspreadsheetに連携する

Amazon echoが届いたので早速遊んで見ました。

![61THuMn02BL._SY355_.jpg](https://qiita-image-store.s3.amazonaws.com/0/104424/9085340e-dbab-8d94-402e-9cbc457551d5.jpeg)

# Amazon musicでかかっている曲をリスト化する

IFTTTがalexaと連携可能なため、googlespreadsheetに書き出します。

[IFTTT](https://ifttt.com/)へ行って会員登録後、「alexa spreadsheet」で検索
![alexa_keep_spreadsheet_Search_services_and_Applets_on_IFTTT_by_category_-_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/104424/1c450127-e15b-6b86-a72e-e5354ad263f4.png)

「Keep a Google spreadsheet of the songs you listen to on Alexa」を探す。
amazonさんが既に便利なレシピを作成済み。

![1alexa_keep_spreadsheet_Search_services_and_Applets_on_IFTTT_by_category_-_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/104424/34ba3f7b-5b35-8feb-73a4-a5ce025a88c7.png)

こちらをTurn Onにする。設定は下図参照。

![Keep_a_Google_spreadsheet_of_the_songs_you_listen_to_on_Alexa_-_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/104424/64528ab1-3b5e-1e29-a84a-6bb490b8df0f.png)

実際に、alexaでamazon musicを流してみると。。。
![Songs_played_-_Google_スプレッドシート.png](https://qiita-image-store.s3.amazonaws.com/0/104424/62ce134d-0e98-9843-088a-258c5fdd1a95.png)

簡単に、一覧化されていきます。

# Amazon musicでかかっている曲をslackに流す
こっちは、レシピがなかったので作って見ました。シェアするのにお金がかかるようなので、以下参考に作って見てはいかがでしょうか。

My Appletsから、New Appletをクリック。
![Manage_Applets_-_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/104424/546a8f10-d2c7-8810-eb14-1a2ce3356225.png)

＋thisをクリック。　
これが起点となるアクション。今回はamazon prime musicが流れたらアクションをする。
![Make_an_Applet_-_IFTTT.png](https://qiita-image-store.s3.amazonaws.com/0/104424/dda4c770-107c-a6a5-70b4-ee4c2b858fd6.png)

alexaを探す。
![Make_an_Applet_-_IFTTT1.png](https://qiita-image-store.s3.amazonaws.com/0/104424/a7d5fb21-dfb7-7d0f-2207-43670e209258.png)

New song playedを選択。
![Make_an_Applet_-_IFTTT2.png](https://qiita-image-store.s3.amazonaws.com/0/104424/75e8af1e-1e4f-b692-6ecf-a98491d60331.png)

+thatを選択。amazon prime musicが流れたらslackへ通知する設定。
![Make_an_Applet_-_IFTTT3.png](https://qiita-image-store.s3.amazonaws.com/0/104424/525c5bc8-af82-cb57-5157-0389e0819aa6.png)

slackアイコンを探す。
![4.png](https://qiita-image-store.s3.amazonaws.com/0/104424/44a8e861-d056-ca9d-dcb0-578d2c1f918f.png)

post to channelを選択
![Make_an_Applet_-_IFTTT5.png](https://qiita-image-store.s3.amazonaws.com/0/104424/c191b7cb-768b-210c-4f89-d41b6a18d264.png)

投稿先と投稿内容を記載する。（デフォルトで設定されているままでOK）
![Make_an_Applet_-_IFTTT６.png](https://qiita-image-store.s3.amazonaws.com/0/104424/e5e6e8f0-5fd5-492d-e57f-ad444bf92fda.png)

うまくいけば、こんな感じで投稿されます。
![Franz_と_Songs_played_-_Google_スプレッドシート.png](https://qiita-image-store.s3.amazonaws.com/0/104424/8cc20167-5d98-e094-9aba-36e43caeb43d.png)
Ethereum testnet (Ropsten)のアカウントを作成して1 ETH取得する手順

EthereumのRopstenというテストネットにアカウントを作成し、1ETHを取得する方法です。Windows7です。

Chrome Extensionの、MetaMask をインストールします。
Chromeで以下のURLにアクセスし、「Chromeに追加」をクリックします。
https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?hl=ja
![WS000267.JPG](https://qiita-image-store.s3.amazonaws.com/0/113316/080c9a09-c1bc-5c4a-d587-c7de22709f06.jpeg)

インストールできたら、MetaMaskの接続ネットワークをRopstenに変更します。
![WS000271-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/141c724c-25e8-65ee-8d93-c086ebe19bd1.jpeg)

規約の確認が２つ出てくるので同意します。
２つめの同意は、規約を下までスクロールしないと押せません。    

パスワードを２回入力してCREATEを押すとテストネットにアカウントが作成されます。
![WS000277-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/4e8b7412-97b0-b243-82f2-0a2c7f2f948a.jpeg)

Seed Wordsが表示されます。
あとで必要になるので、保存しておきます。
![WS000278-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/4f4a7e91-cdfe-f682-f887-f4cc0a1e4813.jpeg)

作成されたアカウントのアドレスが確認できます（灰色で塗りつぶしている部分）
![WS000280-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/5b13c16b-f66e-5c4d-8865-98aa6b0a8d7f.jpeg)

ここからは、テストネット用のETHを取得する手順です。有志のアカウントから無料で送金してもらう方法です。

「BUY」をクリックします。
![WS000281-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/0dca91c5-b559-f1e6-c4ac-4b0ef40fe2e6.jpeg)

「ROPSTEN TEST FAUCET」をクリックします。
![WS000282-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/55143300-40c6-ae55-3bd8-e70c76e6f8fa.jpeg)

送金画面が表示されます。
request 1 eth...をクリックすると、有志アカウントから自分のアカウントへ1ETHを送金するトランザクションが発行されます。
![WS000283-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/8a013f7a-0518-a9f8-9dfd-f4005f76d642.jpeg)

transactionsのところに、発行されたトランザクションのidが表示されます。
これをクリックすると、トランザクションの詳細画面に飛びます。
![WS000284-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/43fac285-7841-5cf6-14cc-bfcdc9c85898.jpeg)

トランザクションが承認される前の画面です。blockheightがまだ未確定（Pending）です。
![WS000286-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/4fbd4f42-c827-0b7d-cc12-f9e65d0e7f92.jpeg)

30秒から1分ほど待つと、無事に承認されました。
![WS000287-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/4c86f72f-13d1-2785-cada-b628835492c5.jpeg)

MetaMaskでアカウントの残高に「1ETH」が表示されているのが確認できます。
![WS000289-1.jpg](https://qiita-image-store.s3.amazonaws.com/0/113316/ca26a2e6-5744-cc86-6cb8-1435d98cb202.jpeg)

この方法で、Ethereum testnet (Ropsten)のアカウントを作成して1 ETHを取得することができました。
hyperappとparcelで作るお手軽フロントエンド環境

## hyperappとは
軽量でシンプルなビューライブラリ
https://qiita.com/JorgeBucaran/items/ac7d54d862dcb33673f1

## parcelとは
お手軽に使える新しいバンドルツール
https://qiita.com/bitrinjani/items/b08876e0a2618745f54a

## hyperappをparcelで使う
hyperappをインストール

```sh
npm i --save hyperapp
```

parcelをインストール

```sh
npm i -D parcel-bundler
```

グローバルにインストールしてもOK

```sh
npm i -g parcel-bundler
```

hyperappでjsxを使うのでbabelのプリセットをインストール

```sh
npm i -D babel-preset-hyperapp
```

.babelrcでプリセットを指定

```json
{
  "presets": ["hyperapp"]
}
```

index.htmlで読み込むjsを指定

```html
<script src="./index.js" />
```

jsはgithubの[readme](https://github.com/hyperapp/hyperapp/tree/c9aed6efdf6735683db71ebf7b7b6eae7e0c2cad)のサンプルから拝借

```js
import { h, app } from "hyperapp"

const state = {
  count: 0
}

const actions = {
  down: () => state => ({ count: state.count - 1 }),
  up: () => state => ({ count: state.count + 1 })
}

const view = (state, actions) => (
  <main>
    <h1>{state.count}</h1>
    <button onclick={actions.down}>-</button>
    <button onclick={actions.up}>+</button>
  </main>
)

export const main = app(state, actions, view, document.body)
```

起動

```sh
./node_modules/.bin/parcel index.html
```

parcelもhyperappもお手軽に使えるので、サクッと何か作りたい時に重宝しそう。

## サンプルコード
作成したサンプルをgithubに置いておきました。
https://github.com/SatoshiKawabata/hyperapp-parcel-example/tree/master
UITextFieldに最大文字数をStoryboardから設定させたい

# 実装イメージ
パスワードの入力欄など、ある文字数以上入力させたくないケースって多いと思います。
でも、各画面でdelegateを設定して...とか面倒極まりない。

以下のように、storyboardから設定できたらいいですよね。

![storyboard.png](https://qiita-image-store.s3.amazonaws.com/0/116677/f220b5e6-07cd-522b-fa9d-876a7d3e46a6.png)

# 拡張しましょう
UITextFieldを拡張します。

```UITextField+maxLength.swift
import UIKit

private var maxLengths = [UITextField: Int]()

extension UITextField {

    @IBInspectable var maxLength: Int {
        get {
            guard let length = maxLengths[self] else {
                return Int.max
            }

            return length
        }
        set {
            maxLengths[self] = newValue
            addTarget(self, action: #selector(limitLength), for: .editingChanged)
        }
    }

    @objc func limitLength(textField: UITextField) {
        guard let prospectiveText = textField.text, prospectiveText.count > maxLength else {
            return
        }

        let selection = selectedTextRange
        let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength)

        #if swift(>=4.0)
            text = String(prospectiveText[..<maxCharIndex])
        #else
            text = prospectiveText.substring(to: maxCharIndex)
        #endif

        selectedTextRange = selection
    }

}
```

# おわりに
便利なExtensionを見つけては試して、気に入ったら取り入れていくスタイルで勉強を進めています。
どなたかの参考になれば幸いです。
Unityローポリゴン水面表現アセットが急に使えなくなった時のメモ

自分用メモ

Unity2017.2.0fから、Unity2017.2.1f1にアップデートして、
有料のローポリゴン水面表現のアセットが急に使えなくなり下記シェーダーのエラーがでた。

```

Shader error in 'LowPolyWater/Lite': failed to open source file: 'LPWLite.cginc' at line 65

```

### 解決策

アセットをアップデートしたら無事解決ｗ
さすが有料
gitでログを確認しつつ変更差分を確認する

## tigを使う

```bash
tig log develop...topic #=> `...`でつなぐことで両方のブランチに共通するコミットが除かれる
```

## pecoを使う

```bash
$ git log develop...topic --no-merges --pretty="%h - %ar, %an: %s" | peco --exec 'awk '"'"'{print $1}'"'"' | xargs git show --patch '
```

こちらの方法は、スクリプト化した方が使いやすそうです。
Cloud9でHerokuが使えない時の対処法

###環境
・CLoud9

#Cloud9でHerokuを使おうとしたらエラーが出た
Cloud9のターミナルで

```
$ heroku -v
```

と打つと

```
heroku: command not found
```

と帰ってきた。

ネットで調べると、[似たような症状の解決策](https://forums.aws.amazon.com/thread.jspa?threadID=270118&tstart=0)があったので実行。

##以下のコマンドを順に実行した
```
$ sudo yum -y update
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.0/install.sh | bash
$ export NVM_DIR=”/home/ec2-user/.nvm”
$ [ -s “$NVM_DIR/nvm.sh” ] && \. “$NVM_DIR/nvm.sh”
$ nvm install node --reinstall-packages-from=node
$ npm install -g cli-engine-command@8.0.0
$ npm install -g heroku-cli
```

途中までうまくいっていたが、最後のコマンドで下記のようなエラーが出た。

```
npm WARN cli-engine-heroku@4.1.1 requires a peer of cli-engine-command@^8.0.0 but none was installed.
```

一旦無視してheroku使えるかどうか試してみた。

```
$ heroku -v
WARNING
WARNING Node version must be >=8.3.0 to use the Heroku CLI
WARNING
/home/ec2-user/.nvm/versions/node/v6.11.4/lib/node_modules/heroku-cli/node_modules/cli-engine/lib/cli.js:68
  async run() {
        ^^^
```
node.jsのバージョンを8.3.0にしろと言っている。（現状は6.11.4）
[この記事](http://soudan.hatenablog.jp/entry/cloud9-nodejs0)を参考にnodeのアップデートを行なった。

##node.jsのアップデート
###バージョン確認
```
$ node -v
v6.11.4
```
###8.3.0にアップデート
```
$ nvm install v8.3.0
Downloading https://nodejs.org/dist/v8.3.0/node-v8.3.0-linux-x64.tar.xz...
######################################################################## 100.0%
nvm is not compatible with the npm config "prefix" option: currently set to "/home/ec2-user/environment/”/home/ec2-user/.nvm”/versions/node/v8.3.0"
Run `npm config delete prefix` or `nvm use --delete-prefix v8.3.0` to unset it.
```
「npm config delete prefix」か「nvm use --delete-prefix v8.3.0」しろと言われる。
###nvm use --delete-prefix v8.3.0する
```
$ nvm use --delete-prefix v8.3.0
Now using node v8.3.0 (npm v5.3.0)
```
nodeの8.3.0が使えるようになったみたい。
###念のためバージョン確認
```
$ node -v
v8.3.0
```
よし。
###そしてHerokuチャレンジ
```
$ heroku -v
heroku-cli/6.14.43 (linux-x64) node-v8.3.0
```
よっしゃ。使えるようになった！
マイクロサービスのテスト

# 第7章
## テストの種類
- [実践アジャイルテスト](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%83%86%E3%82%B9%E3%83%88-%E3%83%86%E3%82%B9%E3%82%BF%E3%83%BC%E3%81%A8%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%83%81%E3%83%BC%E3%83%A0%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E5%AE%9F%E8%B7%B5%E3%82%AC%E3%82%A4%E3%83%89-Architects-Archive%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E9%96%8B%E7%99%BA%E3%81%AE%E5%AE%9F%E8%B7%B5-Gregory/dp/4798119970/ref=sr_1_1?s=books&ie=UTF8&qid=1514559558&sr=1-1&keywords=%E5%AE%9F%E8%B7%B5%E3%82%A2%E3%82%B8%E3%83%A3%E3%82%A4%E3%83%AB%E3%83%86%E3%82%B9%E3%83%88)
- 技術-ビジネス、プログラミング-製品の2軸で4象限にわけられる
    - 単体テスト
    - 性質テスト
    - 受け入れテスト
    - 探索的テスト
- テストピラミッド
    - 単体テスト
    - サービステスト
    - エンドツーエンドテスト
- アンチパターン：テストスノーコーン

## サービステスト
- サービスの機能テスト
- 下流の連携先はモック/スタブ化する
    - スタブ
        - 既知のリクエストに対して決められたレスポンスを返す
    - モック
        - スタブの動作に加え、呼び出しが行われたことを確認する
    - モックかスタブか
        - 著者はサービステストではスタブをより多く使う
    - [実践テスト駆動開発](https://www.amazon.co.jp/%E5%AE%9F%E8%B7%B5%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA-Object-Oriented-SELECTION-Freeman/dp/4798124583/ref=sr_1_1?s=books&ie=UTF8&qid=1514559922&sr=1-1&keywords=%E5%AE%9F%E8%B7%B5%E3%83%86%E3%82%B9%E3%83%88%E9%A7%86%E5%8B%95%E9%96%8B%E7%99%BA)
    - [テストダブル](http://bliki-ja.github.io/TestDouble/)
- スタブサーバは基本は自分で作る
- こういうサービスも使える
    - http://www.mbtest.org/

## エンドツーエンドテスト
- やるべきか
    - 欠点が多い
        - 遅い
        - テストが脆弱になりやすい
        - 「誰が書くか」が問題になりやすい
            - 任意のチームの開発者が書く
                - サービスを結合したテストなのでエラーになったときに誰の責任なのか曖昧になる
                - 自分の担当のサービス以外が原因で落ちたとき
            - 専任のチームで書く
                - チームをまたぐためコード作成からテストの結果が見られるまでが遅くなる
                - 開発者がテストから離れると、テストが落ちたときに直し方がわからなくなる
            - どちらにせよ解決が難しくなりがち
- コンシューマ駆動契約
    - 呼び出し側（コンシューマ）視点でサービステストを実行する
    - Pact
        - https://www.gitbook.com/book/pact-foundation/pact/details
    - エンドツーエンドテストへの依存を薄めるのに活用できる

## デプロイとリリースの分離
- スモークテスト
    - 新たにデプロイする環境に対し、本番環境へのリクエストを使って試験を行う
- カナリアリリース
    - 新たなバージョンを一時的に旧バージョンと並行稼動させ、期待道理に機能することを確認する

## まとめ
- すばやいフィードバックのために、前提として単体テストは充実させる
- サービステストによってサービスの振る舞いを守る
- エンドツーエンドテストは最低限にする
- テストにより保証することも重要だが、デプロイ後にコードが正しく機能していることを確認する方法を把握しておく必要がある
CloudFormationのテンプレートの各名称の呼び方

CloudFormationのテンプレートのノードが、ドキュメント内でどのように呼び方をされているのかまとめました。 
単語が出てくるとドキュメント解読や調査もしやすくなりまし、新しく言葉を生み出す事が減るかと思います。

## この記事で得られること　
- CloudFormationのテンプレート内の要素の呼び方がわかる。

## イントロダクション
### 参考資料
- [CloudFormation|テンプレートの分析](http://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/resources-section-structure.html)

## 解説
見出し等で名言されているものと、文章の中で命名されているものがありました。
ドキュメントを読み進めていて、自分なりに統合していくと下記のような名称で呼ばれているようです。

``` text:テンプレートの階層構造
テンプレート  
  ->セクション(section)
    -> セクションの単数形。Resourcesの場合はリソース(resource)
      ->属性(attribute)
        ->プロパティ(property)
          ->サブプロパティ(subproperty)
```

### 日本語例
``` json:テンプレート
{
    "Resources": {     <--Resourcesセクション
        "S3Bucket": {     <--S3Bucketリソース
            "Type": "AWS::S3::Bucket",     　<--Type属性
            "Properties": {      <--Properties属性
                "AccessControl": "PublicRead",      <--AccessControlプロパティ
                "WebsiteConfiguration": {     <--WebsiteConfigurationプロパティ
                    "IndexDocument": "index.html",      <--IndexDocumentサブプロパティ
                    "ErrorDocument": "error.html"      <--ErrorDocumentサブプロパティ
                },
            },
        },
}
```

### 英語例
英語版のドキュメントに沿って書くと下記になります

``` json:Template
{
    "Resources": {     <--Resources section
        "S3Bucket": {　     <--S3Bucket resource
            "Type": "AWS::S3::Bucket",　     <--Type attribute
            "Properties": {      <--Properties attribute
                "AccessControl": "PublicRead",      <--AccessControl property
                "WebsiteConfiguration": {      <--WebsiteConfiguration property
                    "IndexDocument": "index.html",      <--IndexDocument subproperty
                    "ErrorDocument": "error.html"      <--ErrorDocument subproperty
                },
            },
        },
}
```
サイトのデータ整形メモ

# スマホゲー FEH(ファイアーエムブレムヒーロズ) のキャラ一覧データ整形するためのjQuery
https://altema.jp/fe-heroes/charalist
事前にソートした後実行が望ましい

```javascript
$('table tr').each(function() {
  $(this).children(':last-child').text($(this).children(':last-child').data('value'));
  $(this).children(':first-child').replaceWith("<td>" + $(this).children(':first-child').find('img').attr('alt') + "</td>");
  $(this).children(':nth-child(2)').replaceWith("<td>" + $(this).children(':nth-child(2)').find('img').attr('alt') + "</td>");
  $(this).children(':nth-child(3)').remove();
  $(this).children(':nth-child(5)').remove();
});
```

↑がいつの間にかフォーマット変わってて動かないー。


こっちで代用 https://game8.jp/fe-heroes/116312 tdの `/10` を削除するだけのjQuery

```javascript
$('td').each(function(){
	var txt = $(this).html();
	$(this).html(
		txt.replace(/\/10/g,'')
	);
});
```

# evernoteで左側のリストのタイトルと日付をコンソールに表示する
```javascript
$(".focus-NotesView-Note-snippetContent").each(function(index, element){
	console.log($(element).children().eq(1).text() + '\t' + $(element).children().eq(0).text());
})
```

# なろう系小説を縦書き用ブックマークレット
```javascript
javascript:$('#novel_header').remove();$('.box_announce_bookmark').remove();$('.contents1').remove();$('.toaster').remove();$('div[class^="koukoku"]').remove();$('.novel_bn').remove();$('#pageBottom').remove();$('.wrap_menu_novelview_after').remove();$('#novel_hyouka').remove();$('.center').remove();$('.narou_modal').remove();$('#impression').remove();$('#novel_attention').remove();$('#novel_footer').remove();$('#pageTop').remove();$('#footer').remove();$('#recommend').remove();$('#review').remove();$('#container').css('margin','10px auto 0');$('body').css('writing-mode','vertical-rl');$('p').last().css('padding-left','60px');
```

# 画像で特定URL始まりの抽出（CDNの画像抽出とか）
```javascript

// srcの始まりで検索
domArray = $$('img[src^="https://cdn.hoge"]')
for (let i in domArray) {
    console.log(domArray[i].getAttribute('src'))
}
```
電車の運行情報を教えてくれるAlexa Skillを作ってみた

この記事はGoogle Home向けに作った [電車の運行情報を教えてくれるAssistant対応アプリを作ってみた](https://qiita.com/radiocat/items/b483c360adcd1a0c5f79) のAlexa Skill版です。

# 構成

Alexa Skillの基本構成は以下のようになります。Lambdaの部分はHerokuなどを使って自前で準備したサービスを使うこともできます。今回はそのままLambdaを使いました。

<img width="920" alt="スクリーンショット 2017-12-29 16.34.25.png" src="https://qiita-image-store.s3.amazonaws.com/0/3324/2a7e75d7-65e1-5c7a-c016-b4201fb8e4f9.png">

これらの基本構成は会社の同僚が作った [嫁をなだめるSkill](https://qiita.com/moomooya/items/294597a8519361ba337c) を参考にすれば大枠は完成します。今回はそれ以外の部分を中心にまとめます。

# Alexa Skill Kit

Amazon Echoに向かって「○○を開いて」と言ったら起動し、様々な音声コマンドに反応する仕組みを自前で作ることができるプラットフォームがAlexa Skillです。

## Skill Builder

Skill BuilderはまだBETA機能ですが、Google HomeのDialog Flowのように複雑な音声コマンドに対応するSkillを開発できるようになります。まずは以下のように運行情報を問い合わせるカスタムIntentを作成します。

<img width="1434" alt="スクリーンショット 2017-12-29 23.27.00.png" src="https://qiita-image-store.s3.amazonaws.com/0/3324/1ffd9087-0f79-1f59-a182-6d2dd872cd73.png">

`Train` の部分はカスタムスロットで以下のようにSynonyms（同義語）の設定ができます。

<img width="1431" alt="スクリーンショット 2017-12-28 19.08.36.png" src="https://qiita-image-store.s3.amazonaws.com/0/3324/e43f9780-992c-ff6d-0a41-0ac7b8c4f77f.png">

Synonymsを設定することで異なるワードも同じ意味として解釈してハンドリングすることができるようになります。

# Lambda

Synonyms（同義語）で設定した `id` をチェックして鉄道会社ごとのサイトにアクセスし運行情報をチェックします。以下はNode.jsで実装した例です。

```Js
// 省略
  'TrainStatusIntent': function () {
    var train = this.event.request.intent.slots.Train;
    var speechOutput = train.value + 'の運行情報を取得できませんでした。';
    // SlotにSynonymが設定されているかをチェックして鉄道会社ごとにサイトをチェックする
    
    if ('resolutions' in train) {
      if (train.resolutions["resolutionsPerAuthority"][0]["status"]["code"] == 'ER_SUCCESS_MATCH') {
        var slotId = train.resolutions["resolutionsPerAuthority"][0]["values"][0]["value"]["id"];
        
        if ( slotId==='HANKYU' ) {
          // 阪急のサイトで運行情報を取得する
        } else if ( slotId==='HANSHIN' ) {
          // 阪神のサイトで運行情報を取得する
        }
      }
    }

    console.log(speechOutput);
    this.emit(':tell', speechOutput);
  },
// 省略
```

Skill BuilderでSynonymsを設定した場合は上記のように `resolutions` 配下をチェックすることで同義語の `id` を取得することができます。詳細は別記事にまとめました。

[IntentRequest内でCustom Slot Typeの同義語の情報を取得する](https://qiita.com/radiocat/items/faaae92990bf34015a29)

また、運行情報を取得する時に外部アクセスすると応答までに少し時間がかかるためタイムアウトの設定をデフォルトより少し長くしておくほうが良いでしょう。

<img width="658" alt="スクリーンショット 2017-12-29 23.53.56.png" src="https://qiita-image-store.s3.amazonaws.com/0/3324/a087adbc-7649-7d9c-155e-c3d96b4790a2.png">


# まとめ

Alexa Skill KitとLambdaを設定することでSkillのテストが可能になりますが、上記別記事にも書きましたがSynonymの設定はサービスシミュレーターではテストできないのでご注意ください。構成はGoogle Assinstant対応アプリよりシンプルでわかりやすいように思いますがBeta機能で開発途上なところは若干わかりにくいかもしれません。Test SimulatorというBeta機能もありますが今回はまともに使いこなせなかったので説明は省きます。これらBeta機能が正式に使えるようになるともっと開発しやすくなるかもしれません。ただ、基本的な仕組みを理解しておけば開発の手順はそれほど難易度は高くないと思います。

今回サンプルとして作ったLambdaのスクリプトは下記に置きました。

[AlexaSkilll-TrainStatus](https://github.com/radiocat/AlexaSkilll-TrainStatus)
rails 4.2.10とruby 2.4.3 で `key must be 32 bytes`の例外が発生する

## 現象
railsとrubyのバージョンをあげたところ`key must be 32 bytes`の例外が発生するようになりました。

例外は、暗号化に利用していた`ActiveSupport::MessageEncryptor`から発生していました。

どうやら、rubyのopenssl周りで変更があり、暗号化キーには正しく32byteのキーを渡すことが必要になったようです(aes-256-cbc方式を利用する場合)。
+ https://qiita.com/KTakata/items/7bc8057b3b0ca6759b12
+ https://github.com/rails/rails/issues/25185

また、これまで、32byte以上のキーを渡して場合はキーの32byte以降のデータが利用されないようになっていたようです。
+ https://gist.github.com/rhenium/b81355fe816dcfae459cc5eadfc4f6f9

## 対応
もし、暗号化キーを文字列で渡しているのであれば、以下のようにすることで問題を回避できるようです。

```ruby
secret = "0123456789abcdef" * 8
encryptor = ActiveSupport::MessageEncryptor.new(secret[0..31], "salt-salt-salt")
# 暗号化処理
encrypt_data = encryptor.encrypt_and_sign(private_data)
# 復号処理
decrypt_data = encryptor.decrypt_and_verify(encrypt_data)
```

## :construction: 注意
この対応のセキュリティー的な正しさについては、分からない部分があるので参考にとどめてください。

## 参考
+ http://nisshiee.hatenablog.jp/entry/2017/04/17/192703
+ https://github.com/rails/rails/blob/master/activesupport/test/message_encryptor_test.rb#L54-L62
デプロイ

# 第6章　デプロイ
## CI,CD
- [継続的デリバリー](https://www.amazon.co.jp/%E7%B6%99%E7%B6%9A%E7%9A%84%E3%83%87%E3%83%AA%E3%83%90%E3%83%AA%E3%83%BC-%E4%BF%A1%E9%A0%BC%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%81%AE%E3%81%9F%E3%82%81%E3%81%AE%E3%83%93%E3%83%AB%E3%83%89%E3%83%BB%E3%83%86%E3%82%B9%E3%83%88%E3%83%BB%E3%83%87%E3%83%97%E3%83%AD%E3%82%A4%E3%83%A1%E3%83%B3%E3%83%88%E3%81%AE%E8%87%AA%E5%8B%95%E5%8C%96-Jez-Humble/dp/4048930583/ref=pd_lpo_sbs_14_t_0?_encoding=UTF8&psc=1&refRID=S4W4R0YT9Q81X0NZV4F3)
- CDにはCDを第一級の概念として採用していツールが必要
- ビルドパイプラインを構築する
    - コンパイルと高速テスト
    - 低速テスト
    - UAT
    - 性能テスト
    - 本番環境

## Docker
- 軽量コンテナ上に構築されたプラットフォーム
- 「アプリ」を作成してデプロイする
- サービスのビルドにDockerアプリケーションを作成され、Dockerレジストリに格納して使う
- Dockerを1台のマシン上で動くPaaSと考える
- IaaSとPaaSの間

## まとめ
- 管理するサービスが増えるため、デプロイ時に考慮すべきことは多くなる
- CI,CDを導入し、デプロイの自動化に取り組むことが重要になる
2017年秋季セキュリティスペシャリスト 午前2に出てきた単語の頻度を調べてみた

#始めに
[JavaでPDFファイルをOCR処理してみた](https://qiita.com/triple4649/items/9f2839144c68df11cc41)を元に、セキュリティスペシャリスト　午前2の頻出単語を分析しました

#参照ページ
- [JavaでPDFファイルをOCR処理してみた](https://qiita.com/triple4649/items/9f2839144c68df11cc41)
- [Listに含まれる単語の数をカウントするプログラム](https://qiita.com/triple4649/items/bdd02c2d2413871906fe)

#解析用のソース
```JapaneseAnalyser.java
package jpn;

import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.List;
import java.util.stream.Collectors;

import org.atilika.kuromoji.Token;
import org.atilika.kuromoji.Tokenizer;



public class JapaneseAnalyser {
    public static void main(String[] args) throws Exception{
    	//parse_1.txtにセキュリティスペシャリスト　午前2の問題用紙をOCR読み取りした結果が格納されている
        String input = Files.lines(Paths.get("parse_1.txt"), Charset.forName("MS932"))
        .reduce((s,v)->s+v.replaceAll("\\r\\n", "").trim()).get();
        analysis(input);
    }	
    public static void analysis(String s){
        Tokenizer tokenizer = Tokenizer.builder().build();
        List<Token> tokens = tokenizer.tokenize(s);
        tokens
            .stream()
            .filter(a ->(a.getPartOfSpeech().indexOf("名詞")>=0))
            .map(e -> e.getSurfaceForm())
            .sorted()
            .collect(
    				Collectors.groupingBy(b->b,
    						Collectors.summingInt(b->1))
    				)
            .forEach((m1,m2)->System.out.println(String.format(" 出現頻度 %d    出現単語 : %s",m2,m1)));
    }
}
```

#解析結果
[自分のブログに載せたよ](http://blog.goo.ne.jp/evergreen_1978/e/1211beccbe40ca3ea1aaa6cd4ed3b691)

#感想
- 相変わらず、DNSに関する問題が多い。セキュリティの穴としてよく狙われるから？
- 機械学習に関する語句が出ているのが目新しい。これから情報処理技術者試験を勉強する人にとってはＡＩの分野も薄くでもいいから勉強する必要があるかもね
- JavaのStreamAPIがあればちょっとした日本語解析をするのにpython使う必要ないですね。というか、pythonは2系と3系で使えるライブラリがバラバラで、正直イライラする。pythonが使いやすいって言っている人、どうやって開発しているんだろう・・・。
TypeScript版のDocBaseAPIクライアントのサンプルプロジェクトを作成してみた

先日、[TypeScript対応のDocBaseAPIライブラリをnpmで公開してみた](https://qiita.com/ffggss/items/e8387d69d39d90e1bf45)の記事を書いてみたので、今度は、DocBaseAPIライブラリのサンプルプロジェクトを作成してみました。

nvmのinstallから記載してあるので、ゼロからでも動作確認できるようになっています。

## サンプルプロジェクト
[node-docbase-sdk-sample](https://github.com/YukiFujisawa/node-docbase-sdk-sample)

## DocBaseAPIライブラリ
[node-docbase-sdk](https://www.npmjs.com/package/node-docbase-sdk)
create-elm-appで作成したプロジェクトで"proxy"機能を使う

# はじめに

Haskell向けに重めの記事を書いたりしたので、ちょっと箸休め。

elm-package.jsonには、"proxy"、という項目が設定できますが、使い方についてはまとまった記事が見当たらないので、メモとして書きます。

# 課題

本記事は、create-elm-appで作成したプロジェクトをベースにしています。`elm-app eject`した後でもする前でも、どちらでも大丈夫です。本番稼働ではapache等のWebサーバで「/api」へのアクセスをバックエンドのAPIサーバにリバースプロキシするとして、開発ビルドではローカルPCで「elm-app start」あるいは「npm start」で動いてくれるWebサーバでも、同等のリバースプロキシ相当が働いてくれると便利なんですが、というのがテーマです。

# elm-package.jsonの"proxy"設定

create-elm-appのドキュメント内の記述（[Setting up API Proxy](https://github.com/halfzebra/create-elm-app/blob/master/template/README.md#setting-up-api-proxy)）を見ると、elm-package.jsonに、`proxy" : "http://localhost:3004"`などと記述すると、APIコールを指定したURLに転送する、とのことです。

# アクセス転送の条件は？

上記のドキュメントには、

> Make sure the XHR requests set the Content-type: application/json and Accept: application/json.

と書いているのですが、そもそも何をもって「APIコール」とみなすのか？という書き方はしてくれないので、ちょっとわかりづらいです。

試行錯誤した結果は下記の通りです。

- アクセス転送は「開発ビルド時のみ」（elm-app eject前なら、elm-app start, 後ならnpm start）。本番ビルドでは適用されない
- アクセス転送する条件は、開発用ビルドで稼働するWebサーバへのhttpアクセスで、ヘッダに「Content-type: application/json」と「Accept: application/json」が含まれる場合。URLのパスは無関係。URL中のパスは変更されず、そのまま設定値のURLに転送される

# Elmコードでの対応

APIアクセスをJSONで行う場合、「Content-type: application/json」は自動的に含まれるため、あとは「Accept: application/json」を明示的に含めてやればOKです。コードのサンプルはこんな感じになるかと思います。

```elm
apiHeader : List Http.Header
apiHeader = [Http.header "Accept" "application/json"]

apiGet : String -> Decode.Decoder a -> Http.Request a
apiGet url decoder =
    let request =
            { method = "GET"
            , headers = apiHeader
            , url = "/api" ++ url
            , body = Http.emptyBody
            , expect = Http.expectJson decoder
            , timeout = Nothing
            , withCredentials = False
            }
    in Http.request request
```

上記の例のapiGetの引数decoderには、受け取りたい型のJSONデコーダを指定します。apiGet関数は、Http.sendの引数にセットして、APIコールを実行します。

# 注意点

elm-package.jsonに"proxy"を追加した後に、elm-package install等で、elm-package.jsonを変更する操作をした場合、この"proxy"の項目は消えてしまいます。ちょっと（？）不便ですね。

[create-elm-appのissues](https://github.com/halfzebra/create-elm-app/issues/160)にて議論されていていたりしますが、今はどうしようもない模様です。
Rからgoogle driveのデータにアクセスする

[本記事の内容は最新版のGoogle drive api v3 (2019年１１月時点)には対応していません。]

Rに[googledrive](http://googledrive.tidyverse.org)というパッケージがあります。
これを使えば、ローカル（分析環境上）に保存してなくgoogle drive上のみにあるデータを一時的にダウンロードしてRで分析し、最終的にgoogle driveにアップロードすることが可能です。まあなにがいいかというとローカル（分析環境上）にインプット／アウトプットデータを保持しなくていいということですね。

##Google driveのアクセス権を取得
###Rを起動している環境からweb browserが使用可能な場合
```
library(googledrive)

##まずはgoogledrive上のデータリストを取得してみる
drive_find(n_max = 50)

##この際にアクセス権の取得プロセスが起動する
Use a local file ('.httr-oauth'), to cache OAuth access credentials between R sessions?

1: Yes
2: No

Selection: 1

```
あとはweb browserが起動し、そのまま進めていけばOK

###Rを起動している環境からweb browserが使用できない場合（クラウドマシーンやサーバーなど）
```
options(httr_oob_default=TRUE) ##このオプションが必要


Please point your browser to the following url: 

  https://accounts.google.com/o/oauth2/auth?client_id=XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

##上記のようにurlが与えられるので、ローカルのweb browserからアクセスし、コードを取得
Enter authorization code: XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

```


##Google drive上のデータをダウンロードする

```

#データ名のリストを取得
drive_find( n_max=50)

#まずはマニュアルどおり（ここはマニュアルそのまんま）
##名前で検索
drive_find(pattern = "chicken") ##なんでchickenなんだろ

##ファイル属性で検索
drive_find(type = "spreadsheet")     ## Google Sheets!
drive_find(type = "csv")             ## MIME type = "text/csv"
drive_find(type = "application/pdf") ## MIME type = "application/pdf"

#データをダウンロードする
##例としてAAAAA.tifというgoogle driveにあるtifファイルをダウンロードしてみる
##Google drive上からほしいデータを検索&特定する
inputname <- drive_find(pattern = "AAAAA.tif") 
drive_download(file = inputname, type = "tif", path = here(inputname), overwrite = TRUE) #この例ではhereパッケージ（カレントディレクトリの管理に便利）を利用している.pathはDLする場所を指定

```
これでhere(inputname)にinputnameのデータがDLされる


##データをアップロードする
```
##outnameはローカルデータ
drive_upload(media = outname, name = outname)

```
sublimeText3でPHPの構文チェックを行うのも、かなり曲者だった。

軽さが売りのsublimeText3もデフォルトではPHPに対するlinter機能は搭載していない。よって、拡張機能からインストールして自分で設定する必要があるのだが、けっこうハマりやすい落とし穴がいくつかあったので、それをまとめてみました。

- 作業環境のphp.exeにPATHを通す必要がある。
- sublimeLinter-PHPを動かすためには、sublimeLinterがないと動かない。
- sublimeLineterのuser設定に、追加で書き加える部分がある。

この3点に注意しつつ、手順を紹介（ツールバーなどはjapanizeなどで日本語対応させています。また、package controllerは既にインストールした状態で解説します）

1. 作業環境のphp.exeにPATHを通して、PCを再起動。
2. ツールバーの基本設定→Package ControlでInstall Packageを選択して、sublimeLinterをインストール。
3. ツールバーの基本設定→Package ControlでInstall Packageを選択して、sublimeLinter-phpをインストール。
4. ツールバーの基本設定→Package Settings→Sublime Linter→Settingを選択して、settings画面を開く。
5. settings画面（json形式）で行末に以下の構文を書き加える（php.exeのパスルートは任意）

```json:settings
        "sublimelinter_executable_map": {
            "php": "C:\\xampp\\php\\php.exe"
        },
```
![sublime_linter_json.png](https://qiita-image-store.s3.amazonaws.com/0/227291/e1c9b47e-be89-7f96-8704-05c545134ae6.png)

6.保存して、元のページに戻れば、linterが機能するようになる。

#動作確認

うまく機能すれば、こんな感じになります。

構文エラーが発見されると、行に赤いポイントとエラー箇所に赤い括弧が現れ…
![sublime_lint1.png](https://qiita-image-store.s3.amazonaws.com/0/227291/3d5a82d0-f2a7-d2d0-2932-1efab7ab2c8a.png)

その行を選択すると、真下のナビゲーションバーにエラーの詳細が表示されます。
![sublime_phplint2.png](https://qiita-image-store.s3.amazonaws.com/0/227291/80b97270-6f1e-71a2-37b2-5023b311ef97.png)