OmniAICreator/Qiita-1.07M huggingface dataset:
Bluemix Infrastructure API(Accountサービス)

Accountデータ型 <dict型>
https://softlayer.github.io/reference/datatypes/SoftLayer_Account/

Accountサービス・メゾッド
https://softlayer.github.io/reference/services/SoftLayer_Account/
 
(1) チケット情報の取得
getTickets  http://sldn.softlayer.com/reference/services/softlayer_account/getTickets

コード

```py
# SoftLayerモジュールを読み込む
import SoftLayer

# ppritモジュールからpprint関数を読み込む
from pprint import pprint

# ポータルのアカウント > ユーザ > ユーザー・プロファイルの編集でAPIアクセス情報を確認し入力
username = 'xxxxxxxx'
key = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'

# 認証情報を渡すことで他のメゾッドで要求されるauthenticate引数は不要に
client = SoftLayer.Client(username=username, api_key=key)

tickets = client['Account'].getTickets(mask = 'assignedAgentCount, \
assignedAgents,\
attachedAdditionalEmailCount,\
attachedAdditionalEmails,\
attachedDedicatedHostCount,\
attachedDedicatedHosts,\
attachedFileCount,\
attachedFiles,\
attachedHardware,\
attachedResourceCount,\
attachedVirtualGuestCount,\
attachedVirtualGuests,\
awaitingUserResponseFlag,\
cancellationRequest,\
employeeAttachments,\
employeeAttachmentCount,\
group,\
invoiceItems,\
lastActivity,\
serverAdministrationRefundInvoice,\
stateCount')

# 1つのチケット情報を表示
pprint(tickets[0])
```

アカウント登録(1ヶ月間無料トライアル付き: 要クレジット登録) 
https://ibm.biz/Bdji5q
レンタルサーバー上のファイルシステムをより便利にマウントする

#ssh-fs と autofs を組み合わせてリモートストレージを必要な時だけマウントする
某VPSサービスがそこそこの容量を貸してくれるので、ひ弱な RaspberyPi のセカンドストレージとして使おうと思ったが、ネットワークが不安定なのか ssh-fs ではしょっちゅう応答がなくなってしまうので、使うときだけマウントして、使わないときは自動でアンマウントするようにした。もうだいぶ忘れかけているけど完全に忘れないうちにメモを残しておく。

##ssh-fs を使ってリモートのファイルシステムをローカルシステムにマウントする
別のサーバーのファイルシステムをマウントするならnfsが有名だが、インターネット上のサーバーのストレージをマウントする場合にはssh-fsが簡単で便利。
Debian 系列の場合なら

```
sudo aptitude install sshfs
```

でインストールできるはず。

http://tech.ckme.co.jp/ssh_sshfs.shtml とかで書かれているように

```
$ sshfs username@example.com: /home/foo /mnt/point
```

などとすれば簡単にマウントできる。

しかしながら、この状態で長時間放置していると、アンマウントしていないのに ssh が切断されて、運が悪ければシステムが応答しなくなてしまう。安定した接続が確保できない環境では、使うときだけマウントして、使わなくなったらアンマウントするのが安心。

##そこでautofs の出番
autofs は所定のディレクトリにアクセスしに行った時だけファイルシステムをマウントしてしばらく使わないでいると勝手にアンマウントしてくれる仕組み。サーバーの再起動の際にアンマウントが必要だけでつい忘れてしまうとか、USB メモリみたいにしょっちゅう抜き差しするのにアンマウントを忘れてしまうようなときに設定しておくととても便利。
autofs のインストールについては http://kaede.blog.abk.nu/nfs-on-autofs あたりを参考にする。大雑把に書くと以下のような感じ

```
$ sudo atitude install autofs
```

でプログラムをインストールした後、 /etc/auto.master を編集して自動マウント・アンマウントの設定をしてゆく。

##ssh-fs と autofs の組み合わせ方
autofs と ssh-fs の組み合わせ方がなかなか見つからなかったので記録しておく。

/etc/auto.master に、以下を追加

```txt:/etc/auto.master
/media/sakura /etc/auto.sakura.data --timeout=30,--ghost
```

パスフレーズを空にした公開鍵・秘密鍵を作成して秘密鍵を

```
/home/localuser/.ssh/keys/sshfs2sakura
```

に置くと想定する。公開鍵はリモートの /home/remoteuser/.ssh/autofs 内に追記することを想定。この時にローカル側の設定として以下を作成。uid=1000 の権限でマウントする。

```txt:/etc/auto.sakura.data
music           -fstype=fuse,allow_other,uid=1000,gid=1000,reconnect,IdentityFile=/home/localuser/.ssh/keys/sshfs2sakura sshfs\#remoteuser@remotehost:/home/remoteuser/data
```

使用するユーザーがリモートサーバーにログインしたことがあれば問題はないが、一度も ssh でログインしたことがない場合、 knownhosts の設定についても注意が必要。

この記事を書いていたら以下のようなサイトで詳しく解説してくれているので参考にどうぞ
http://blog.fusic.co.jp/archives/2086/
Azureの日本語化とテンプレートして再利用する! (OS日本語)

---
Azureの仮想マシンは初期状態だと英語状態になります。
ここではAzureで作成したVMを日本語化してイメージファイルにして再利用できるようにします！

---

■準備する物
　－　Azureアカウント
　－　AzureVM

■ルール
　－　RDP接続
　－　インターネット接続

---
###■日本語化

１）作成したAzureのVMにログインします
※この時点では英語の状態

![JPN01.png](https://qiita-image-store.s3.amazonaws.com/0/150678/08a36b71-71f7-3e33-6405-3fe2f78bf351.png)

2)｢start｣ ⇒　｢Control panel｣　を開き　｢Add a language｣を展開する

![JPN03.png](https://qiita-image-store.s3.amazonaws.com/0/150678/cbfde712-f49a-7b82-1da8-30f1f62da54b.png)

3)｢Langage｣画面で｢Add a language｣をクリックする
![JPN04.png](https://qiita-image-store.s3.amazonaws.com/0/150678/d4c37655-3e76-474a-1192-a0a7e0211e08.png)

4)｢Add a language｣で下図のエリアから｢日本語｣を選択し｢Add｣をクリックする
![JPN05.png](https://qiita-image-store.s3.amazonaws.com/0/150678/795a0b77-5c78-70bf-e8a9-6f28a41a23e6.png)

5)｢Langage｣画面で｢日本語｣を選択し｢Move Up｣をクリックし｢Option｣をクリックする
![JPN06.png](https://qiita-image-store.s3.amazonaws.com/0/150678/fb072d7c-93c8-0996-3fbb-d065ad487dd6.png)

6)｢Download and install language pack｣をクリックしてMSから言語パックをダウンロードしインストールする
※このタイミングでインターネットに接続する
![JPN07.png](https://qiita-image-store.s3.amazonaws.com/0/150678/f1c181dd-0b1d-b33a-f3dc-ac1569073354.png)

7)インストール終了後｢Change date ,time, or number formats｣をクリックする
![JPN08.png](https://qiita-image-store.s3.amazonaws.com/0/150678/e14c130c-2b7b-5881-3f72-66e44a79222a.png)

8)｢Region｣の｢Home location｣より｢Japan｣を選択
![JPN09.png](https://qiita-image-store.s3.amazonaws.com/0/150678/8b3b616e-3a84-445a-afaa-08f658e2997d.png)

9)｢Adminisrative｣より｢Copy settings｣を選択
![JPN10.png](https://qiita-image-store.s3.amazonaws.com/0/150678/64f7b082-9df2-18ba-a342-a3e9a216a988.png)

10)｢Welcom・・・｣の画面より以下の二つにチェックを入れ｢OK｣を押す
　　・「Welcome screen and system accounts」
　　・「New user accounts」
※この後再起動が入ります
![JPN11.png](https://qiita-image-store.s3.amazonaws.com/0/150678/d3cf95b0-362c-9ee1-4b1f-1b4dd4b97c63.png)

11)｢Restart Now｣で再起動を行う
※継続して作業する場合は｢Cancel｣(※本手順では｢Cancel｣します)
![JPN12.png](https://qiita-image-store.s3.amazonaws.com/0/150678/95112251-705b-5e3e-f715-db57c0f86212.png)

12)｢時間表記部分｣を右クリックし｢Adjust date/time｣を選択
![JPN13.png](https://qiita-image-store.s3.amazonaws.com/0/150678/0b997fac-09e3-b881-d3e2-995571937be6.png)

13)｢Date and time｣にて以下の作業を行い、作業後画面を閉じて再起動を行う
　　・「Set time zone automatically」　off から on　
　　・「Time zone」より以下を選択
　　　　→　(UTC+09:00) Osaka,Sapporo,Tokyo
![JPN14.png](https://qiita-image-store.s3.amazonaws.com/0/150678/d4107ec4-4fe0-953c-d8cb-baae16768b49.png)

14)再起動後ログインし日本語表記になっていることを確認し終了。
![JPN15.png](https://qiita-image-store.s3.amazonaws.com/0/150678/7c6d60b0-ff1a-f197-fa04-af1c2ecd5d44.png)

ちょっと長くなったのでパート２へ・・・

[Azureの日本語化とテンプレートして再利用する（テンプレート）](http://qiita.com/yo_dazy/items/53efe552c336df53577a)
Azureの日本語化とテンプレートして再利用する!（テンプレート）

---

初期状態からカスタマイズしたOSのイメージを取得し、再利用できるようにします！
｢Azureの日本語化とテンプレートして再利用する（日本語化）｣で日本語化したOSをイメージファイルに変換！
⇒[Azureの日本語化とテンプレートして再利用する（日本語化）](http://qiita.com/yo_dazy/items/2155d199a376d49b54c2)

---


■準備する物
　－　Azureアカウント
　－　AzureVM
　－　イメージ化するOS
　－　Azure Portal

■注意
　・　イメージ取得後対象VMは削除されます。
　　　イメージを取るだけのVMと考えて下さい

■ルール
　－　RDP接続
　－　インターネット接続

---

###■テンプレートやり方

１）イメージ化するOSにログインする
２）ログイン後「コマンドプロンプト」を起動させる
３）以下のコマンドを実行する

```ruby:コマンド1
cd c:\Windows\System32\Sysprep
```

```ruby:コマンド2
sysprep /generalize /oobe /mode:vm /shutdown
※コマンド実行後対象のVMはシャットダウンされます。
```
![TEMP01.png](https://qiita-image-store.s3.amazonaws.com/0/150678/522c68ae-c1cb-7dca-0b8a-1f127113a784.png)

４) VMシャットダウン後｢AzurePortal｣へログインする
５) 手順３）でログインしたサーバのリソース情報を表示させる
６) 「キャプチャー」をクリックする
![TEMP02.png](https://qiita-image-store.s3.amazonaws.com/0/150678/61e5895b-ec6d-f4ab-496c-0bee5b18a3ec.png)

７) 以下情報を入力後、「OK」を押す。

| No | 項目 | 意味 | 今回入れた値 |
|:-:|:-:|:-:|:-:|
| 1 | 名前  | 作成するテンプレートの名前  | Win2k16-JPN  |
| 2 | リソースグループ  | テンプレートを作成するリソースグループの指定  | hogehoge  |
| 3 | イメージを作成後、この仮想マシンを自動的に削除します  | テンプレート作成後VMを削除するかしないか  | チェックを入れる  |

![TEMP03.png](https://qiita-image-store.s3.amazonaws.com/0/150678/2691f443-3aeb-8390-02bf-e0068896bbe2.png)

８) ｢azureportal｣よりVMが削除されたことを確認する
![TEMP04.png](https://qiita-image-store.s3.amazonaws.com/0/150678/9162a4c5-4ae6-3c57-e978-d9557481b306.png)

９) ｢イメージ｣をクリックする
![TEMP05.png](https://qiita-image-store.s3.amazonaws.com/0/150678/8421aa54-5657-7c4d-ce61-6009c7ca5296.png)

１０) ｢作成したテンプレート(Win2k16-JPN)｣の確認を行い作業は終了
![TEMP06.png](https://qiita-image-store.s3.amazonaws.com/0/150678/85a587de-b535-a96d-ef82-bfb76c1ef42e.png)

---


補足）使い方
｢イメージ｣から｢作成したテンプレート｣をクリックする
｢VMの作成｣をクリックする
※あとは普通のVM作成と同じ！！

![TEMP07.png](https://qiita-image-store.s3.amazonaws.com/0/150678/e09c4967-3408-8f23-718c-075cd145e7a0.png)

---

これで作業は終了です。AzureのVMは何を使っても必ず英語になるので日本語化してからキャプチャーとってイメージファイルを使用することをお勧めします！！
Jupyter-gopherlab

# Jupyter-gopherlab

JupyterのGoカーネルを探すと次の選択肢があります。

* [gopherlab](https://github.com/fabian-z/gopherlab) (Go >= 1.6, ZMQ 4.x)
* [Gophernotes](https://github.com/gophergala2016/gophernotes) (Go >= 1.4, ZMQ 2.2.x)
* [IGo](https://github.com/takluyver/igo) (Go >= 1.4)

https://github.com/jupyter/jupyter/wiki/Jupyter-kernels

Ubuntu 16.04ではgolang 1.6.2が入るため、ここではgopherlabの環境を構築します。

## 準備

libzmq-4.x系を要求されますが、Ubuntu 16.04ではlibzmqのバージョンが古いため、次の手順でlibzmqをインストールする必要があります。

```sourceslist:/etc/apt/source.list.d/zeromq.list
deb http://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0/ ./
```

上記ファイルを作成し、libzmq3-devをインストールします。（libzmq3-devでlibzmq-4.xが入ります。）

```bash
wget https://download.opensuse.org/repositories/network:/messaging:/zeromq:/release-stable/Debian_9.0/Release.key -O- | sudo apt-key add
sudo apt update
sudo apt install libzmq3-dev
```

## 環境構築

https://github.com/fabian-z/gopherlab にしたがって粛々とkernelを作成します。

```bash
go get github.com/fabian-z/gopherlab
mkdir -p ~/.local/share/jupyter/kernels/gopherlab
cp -r $GOPATH/src/github.com/fabian-z/gopherlab/kernel/* ~/.local/share/jupyter/kernels/gopherlab/
cp -a $GOPATH/bin/gopherlab ~/.local/share/jupyter/kernels/gopherlab/
sed -i "s#/go/bin/gopherlab#$HOME/.local/share/jupyter/kernels/gopherlab/gopherlab#g" $HOME/.local/share/jupyter/kernels/gopherlab/kernel.json
```

いつものようにjupyter-notebookを起動すると、新規NotebookのところにGo (gopherlab)と追加されています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/26144/0af730ef-446b-e612-3e6c-c8b6d5808e88.png)

右上にGopherくんが表示されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/26144/20f4c24e-135f-0f16-2db3-7d9531b8cf03.png)

kernel errorが発生した場合、GOPATH等が通っていない可能性がありますので、jupyter notebookの吐き出すエラーログ等をご確認下さい。


## Hello World

```go
import "fmt"
fmt.Printf("Hello world\n")
```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/26144/5bc56b96-0bdc-365e-5530-0c270c6f30b3.png)

セルの間隔が少し気になりますね…。

Goをインタプリタで扱うことができるため、大変学習効率が良いと思われます。
[Survey] Kaggle - Quora 1位解法まとめ


Kaggle - Quora Question Pairs[^1]の1位解法[^2]の調査記事です．

Author: Maximilien@DAMI
Title: Quora Question Pairs
Discussion URL: https://www.kaggle.com/c/quora-question-pairs/discussion/34355

---------------------------------

## 特徴量

### 分散表現

- 単語単位: Word2Vec
- 文単位: Doc2Vec, Sent2Vec
	- 文の分散表現は単語単位に比べて上手くいかなかったとのこと．
- SNLI[^4]で学習済みのESIM[^3]

### 古典手法

- LDAやLSIでの類似度
- bag of character N-gram(TFIDFとそのままの両方)での類似度(N=1〜8)
- Abhishek氏[^5]とowl[^6]氏が提案した特徴量
- レーベンシュタイン距離
- 共通トークンの割合
- 質問長，質問の長さの差
- 大文字の数，クエスチョンマーク
- 質問1と2が"Are", "Can", "How"などで始まっているかどうか
- 様々な距離

### データ生成時の構造

#### 前提知識

サンプルデータの作り方に偏りがあって，質問IDをノード，質問1と2を辺としたグラフから得られる特徴量が性能改善につながっていた．

---------------------------------

## モデル

- 学習済みGloVeでのSiamese LSTM[^8] [^9]
- 学習済みfastTextでのDecomposable Attention[^7]
- 学習済みfastTextでのESIM(単一モデルで最良の性能)

#### 備考

- 学習済みのfastTextやGloVeの重みを調整しても改善は見られなかった

---------------------------------

## サンプルごとの重みの調整

#### 前提知識

- 訓練データと検証データの正例と負例の比率が異なっている
- そのため，訓練時には検証時に性能がもっとも発揮されるよう正例と負例の重みの割合を変えてあげる必要がある．

### 分割方法

- さらに最適化するためのグラフ構造によって下記3パターンに細分化し調整

https://www.kaggle.com/c/quora-question-pairs/discussion/31179

下記の3パターンに分けた

- qid1_count = qid2_count = 1
- min_qid_count = 1 かつ max_qid_count > 1
- min_qid_count > 1

---------------------------------

## Model Stacking

- Layer 1: 300のモデル, PaulとLamのニューラルネット，XGBoost, LightGBM, Scikit Learnの関数(ET, RF, KNNなど) 
- Layer 2: 150のモデル, すべての入力，Layer1の予測値，ESIM
- Layer 3: L1とL2のLassoでリッジ回帰
- Layer 4: ２つの提出物を55:45の比率でブレンドして作成


## References

[^1]: Kaggle, [Quora Question Pairs](https://www.kaggle.com/c/quora-question-pairs), 2017.
[^2]: Maximilien@DAMI, [1st place solution](https://www.kaggle.com/c/quora-question-pairs/discussion/34355), 2017.
[^3]: Chen, [Enhanced LSTM for Natural Language Inference](https://arxiv.org/abs/1609.06038), 2017.
[^4]: Bowman, [The Stanford Natural Language Inference (SNLI) Corpus](https://nlp.stanford.edu/projects/snli/), 2015.
[^5]: Abhishek, [Abhishek's features](https://www.kaggle.com/c/quora-question-pairs/discussion/31284)
[^6]: the1owl, [Matching ¿Que? for Quora - End to End 0.33719 PB](https://www.kaggle.com/the1owl/matching-que-for-quora-end-to-end-0-33719-pb)
[^7]: Parikh, [A Decomposable Attention Model for Natural Language Inference](https://arxiv.org/abs/1606.01933), 2016.
[^8]: Koch, [Siamese Neural Networks for One-Shot Image Recognition](http://www.cs.utoronto.ca/~gkoch/files/msc-thesis.pdf), 2015.
[^9]: Koch et al., [Siamese Neural Networks for One-shot Image Recognition](https://www.cs.cmu.edu/~rsalakhu/papers/oneshot1.pdf), 2015.
maplotlibのヒストグラムに累積比率を追加する


下図のようにヒストグラムに累積度数や比率など重ねてプロットしたくなるのでメモ。

![fig.png](https://qiita-image-store.s3.amazonaws.com/0/47296/44d2c03c-ae57-e20d-0910-df04f4b49a2a.png)

ヒストグラムのプロット時、`pyplot.hist()`の戻り値で度数やビンの情報を取得できるので、それを使って第2軸に累積比率を計算して、適切な場所に重ねる。コードは以下（主要な部分のみ）

```python
"""ヒストグラムに累積比率を追加する"""
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns

# % matplotlib inline
# seabornのスタイルでプロット
sns.set(style="darkgrid", palette="muted", color_codes=True)

# トイデータ生成
np.random.seed(0)
dt = np.random.normal(size=100)

fig, ax1 = plt.subplots()

# ヒストグラムプロットとビン情報の取得
n, bins, patches = ax1.hist(dt, alpha=0.7, label='Frequency')

# 第2軸用値の算出
y2 = np.add.accumulate(n) / n.sum()
x2 = np.convolve(bins, np.ones(2) / 2, mode="same")[1:]

# 第2軸のプロット
ax2 = ax1.twinx()
lines = ax2.plot(x2, y2, ls='--', color='r', marker='o',
         label='Cumulative ratio')
ax2.grid(visible=False)

plt.show()

```

凡例とかちゃんと付けたい方[こちら](https://gist.github.com/messefor/2f75e5d761da1dc7411bb24daf4afe76)に完全版あります。~~`seaborn.FacetGrid()`使う場合はどうやるんでしょうね~~ 　書きました。
　[maplotlibのヒストグラムに累積比率を追加する2 〜FacetGridを使う〜](http://qiita.com/messefor/items/f15e215d0d3c7cc1a9e8)
Backbone.js メモ1

  [Backbone.js アプリケーション開発ガイド](https://www.oreilly.co.jp/books/9784873116587/)

この本を買ったので読んだ内容で理解したものをまとめていく。

# 1章と2章まとめ
## MVCについて

Webサーバー側でのMVCモデルとはコントローラーの位置づけが違う点。
もうかなり昔のことなので記憶があいまいだけど、Servletでは、HTTPリクエストを受け取ってどの処理を呼ぶかという処理を担っていたのがMVCでいうコントローラだったような。

Backbone.jsの世界ではそれをルーターと呼ぶらしい。
かつコントローラーに相当するロジックがビューに含まれているとのこと。

モデルは入力されたデータ保持・管理みたいな位置づけ。

## テンプレートエンジン
Underscore.jsしか知らなかったけどHandlebars.jsというのもあるんだって。
react-native install react-native-fbsdk で Expected "/*", "//", or "{" but "<" found. エラー


ReactNativeでFacebookログイン使用として公式ドキュメントに従い、`react-native install react-native-fbsdk` したところ以下のエラーで怒られました。

```
rnpm-install ERR! Something went wrong while linking. Error: Expected "/*", "//", or "{" but "<" found. 
Please file an issue here: https://github.com/facebook/react-native/issues 

Expected "/*", "//", or "{" but "<" found.
```

よくわからないのでぐぐってみると、https://github.com/facebook/react-native/issues/10032#issuecomment-309087710 に解決方法がありました。

`react-native install react-native-fbsdk`の代わりに`npm install react-native-fbsdk@0.6.0 --save`でインストールしなさいよということだったので、試してみると無事インストール成功しました。

そのあとのリンクも`react-native link react-native-fbsdk`コマンドで正常終了。

誰かがReactNativeやるとissue漁ることになると書いてましたが、割りとその通りになってきました。
YMF825の音階パラメータについて

#YMF825の音階パラメータについて

###Maker Faire Tokyo 2017会場で、入手した『[YMF825Board](https://yamaha-webmusic.github.io/ymf825board/intro/)』で、[サンプルアプリ](https://github.com/yamaha-webmusic/ymf825board/blob/master/sample1/ymf825board_sample1/ymf825board_sample1.ino)では、ドレミファソのパラメータしか記述されていないので、keyon()関数に与えるパラメータを計算してみた。

例えば）

ドの音を出す際は
keyon(0x14,0x65);
ってなっている。

レの場合は
keyon(0x1c,0x11);

ってなっており、この引数に与えるデータって何だ？となる。

YMF825の[IF仕様書](https://github.com/yamaha-webmusic/ymf825board/blob/master/manual/fbd_spec2.md)によると、Control Register Write Registersの#13,#14で、FNUM,BLOCKで指定するようである。

FNUMとBLOCKの値(C2〜C4まで)は、このように定義されています。

|Note|Freqency|BLOCK|FNUM|
|:----:|:-:|:-:|:---:|
|C2|130.8|3|357|
|C#2|138.6|3|378|
|・・・|・・・|・・・|・・・|
|C4|523.3|5|357|

で、レジスターの構成は

|I_ADDR|D7|D6|D5|D4|D3|D2|D1|D0|
|:----:|:-:|:-:|:---:|:---:|:---:|:----:|:----:|:----:|
|#13   |"0"|"0"|FNUM9|FNUM8|FNUM7|BLOCK2|BLOCK1|BLOCK0|
|#14   |"0"|FNUM6|FNUM5|FNUM4|FNUM3|FNUM2|FNUM1|FNUM0|

っていう並びになっています。
せめて、FNUM7〜9が一つずれていればまだわかりやすいのだが・・・・

keyon()関数は、第一引数が#13の値、第二引数が、#14の値を指定してくれということです。

うーーん、こりゃ変換が大変だということで、変換テーブル表をExcelでつくりました。
MIDIで慣らすことを想定しているので、Note番号も入れてあります。
緑色が仕様書に書かれてた数値で、その他のあたいはたぶんこうなるだろうということで計算してあります。（ご利用は、自己責任で！）

![image.png](https://qiita-image-store.s3.amazonaws.com/0/33220/1b4bd581-0af3-9f53-7be5-283ccf0809ec.png)

以上、ご参考までに
か弱い本番環境でxargs使って丁寧に1個ずつログファイルを圧縮する

# 想定している悲惨な環境

- Webサーバーの/var/log以下にアクセスログが世代管理されずに放置されているので圧縮したい
- 消すにしろ、圧縮するにしろ、本番環境なので一気にまとめてやるとI/OとかCPUとか死んでしまう（10年プレーヤーの物理サーバー辛い）
- 意外とアクセスある

# xargsの便利なpオプションで丁寧に

xargsにはp(スモールピー）オプションがあり、コマンド実行するかどうかを聞いてくれる。yもしくはYを押すと実行してくれるので、topコマンドで負荷見ながら実行してあげるといいと思います。nオプションを指定しておかないと元の木阿弥になるパターンがあるので忘れずに。

```bash
find . -name "*.log" | xargs -p -n1 gzip
```

圧縮済みのファイルとかが散らばっている場合には除外してあげてください。

```bash
find . -name "*.log" ! -name "*.gz" | xargs -p -n1 gzip
```

# か弱い本番で死にかけるやり方

```bash
find . -name "*.log" -exec rm {} \;
```

とかやると死ぬ。

```bash
find . -name "*.log" -exec gzip {} \;
```

とかやっても死ぬ。
もし、か弱いサーバーに出会ったり作ってしまった場合にご活用くださいませ。
KeeAgent(KeePass) + ssh.exe(start-ssh-pageant.cmd)の覚書

### windows@コマンドプロンプト環境
- ちょっとわからなかったのでやり方をメモしておく
- ssh.exe/ssh-pageantはVS2017付属のgit
    - つまりgit for windows(MSYS2 + αの環境?)


### 手順
```
λ set SSH_AUTH_SOCK=/tmp/.ssh-pageant-username
λ start-ssh-pageant.cmd

# 起動してる！
λ ps
      PID    PPID    PGID     WINPID   TTY         UID    STIME COMMAND
     9196       1    9196       9196  ?         197609 20:37:02 /usr/bin/ssh-pageant

# 実行 or キーの確認
λ ssh hogehoge -vvv
or 
λ ssh-add -L
```

### 環境情報とか
```
λ git --version
git version 2.10.2.windows.1
λ ssh -V
OpenSSH_7.3p1, OpenSSL 1.0.2j  26 Sep 2016
```

### 参考情報
[Mingw\-w64/MSYS2 を入れなくても Git for Windows で間に合うみたい](http://d.hatena.ne.jp/m-hiyama/20151013/1444704189)
> Git for Windowsは、MSYS2＋αなのです。「＋α」部分はもちろんWindows向けに調整されたgitコマンドです。
JavaScriptのtouchstartを止めるとclickイベントが発火しない

ブラウザゲーム作っててスマホで登録したclickイベントが発火しない現象に悩まされました。
どの行が悪さしてるか、それはしらみつぶしに探していった結果わかりました。（下記）

```html
<body>
    <button id="button"></button>
</body>
```

```js
var button = document.getElementById('button');

document.addEventListener('touchstart', function(event) {
    event.preventDefault();    //この行が悪さしてる
});

button.addEventListener('click', function(event) {
    //これ発火しない
});

```

# touchstartイベントをpreventDefault()するとclickイベントが発火しない

当該要素はもちろん、親要素で止めてもダメです。
しかもtouchstartという別イベントの挙動に影響されてるというのがわかりづらいですね＞＜

ちなみにこのバグ、発生する端末についての情報が錯綜しており「Androidなら大丈夫だけどiOSのSafariとChromeで起こるよ派」「AndroidのChromeでも起こるよ派」「Androidでもタブレットなら大丈夫だったよ派」など色んな方がいらっしゃいます。たぶんどのOSがとかじゃなくwebkitの一部バージョンが悪さしてるんじゃないかな…と予想。

しかし実際にこのバグが発生する端末がまだ存在するのは間違いないので、それを考慮したコードを書くことをおすすめします。ちなみに私は以下のように解決しました。

```js
button.addEventListener('touchstart', function(event) {
    event.stopPropagation();    //親要素へ伝播しなければpreventDefault()も発生しない
});
```

# （補足）イベントに対する「ブラウザの標準動作」は親要素への伝播が完了した後

JavaScriptで発生したイベントは、まず当該DOM要素（この場合はbutton）に登録した関数を発火し、そこでstopPropagation()されなければその親要素（→body→document）へとイベントがどんどん伝播されていきます。

で、**それがすべて完了すると＝最も親の要素まで到達すると（あるいはstopPropagation()で強制中断されると）**最後に満を持して「ブラウザの標準動作」が実行されます。

仕様です。ただ知らないと混乱します。不具合の切り分けの際にこれが理解を妨げました。

# （補足）「ブラウザの標準動作」はpreventDefault()が一回でも実行されるとキャンセルされる

いやそのまんまだろ！何が罠なんだ！！と思うなかれ。該当要素（button）でpreventDefault()する方は直感的にも納得ですが、親要素のbodyやdocumentでpreventDefault()した場合も、ブラウザの標準動作はキャンセルされます。

ここでやってしまった勘違いは、**documentでpreventDefault()すればdocumentの標準動作がキャンセルされる。buttonでpreventDefault()すればbuttonの標準動作がキャンセルされる。**という思い込み！

そもそも「documentの（タッチに対する）標準動作」なんてものはろくに存在しないので、親要素になんでpreventDefault()を書いたのか（目的：すべての子要素のタッチを吸収）を思い出せばこんな勘違いはしないと思うのですが…コードを書いているうちに忘れちゃうんですよねえ＞＜

# 結論：問題は、切り分けよう！！

今回は、わかってみればシンプルなバグが原因でした。
しかし、イベントについて雑な理解をしていたため補足にある２つの思い込みに惑わされて
「真のバグ」の発見と発生条件の解明に手間取ってしまいました。
条件のよくわからないバグに想像した時は、背後に「別の思い込み」が無いかもう一度仕様を確認しましょう！
Deep Security User Night #5 レポート

こんにちは、ひろかずです。

Deep Security User Night #5に行ってきたので一筆書きます。
会場は前回に続き[HAPON新宿](http://hapon.asia/shinjuku/)。
日本地図をモチーフにした机がオシャレな空間です。

プシュッと開けてからスタートです。

#お品書き
- Google Cloud Platformの紹介とセキュリティとDS on GCPの話
- 我が家の箱入り娘を世間に晒すのは危険なのでDeep Securityに見守ってもらった話
- Deep Security APIを活用したルールアップデートの自動化について

#Google Cloud Platformの紹介とセキュリティとDS on GCPの話
Google Cloud Japan
金子さん

トレンドマイクロとは長い付き合い
よなよなエール好き（箱買い派）

2017/6にDeep SecurityがGCPに対応
AWSに比べてまだまだ機能は足りないけど、これから
評価ガイドあります！（スタートアップガイド）

- IaaSにManagerを立てて、保護サーバーにAgentを入れる方式

GCPの概要
Google関連サービスは、10億を超えるユーザー
どういうインフラで動いてるの？

- バカでかいデータセンター
- データセンターから自作
- ラックも自作
- 国内サーバベンダーより多くのサーバを作ってる
- コンポーネントを極限まで削っているので、セキュア
- 管理は自動化。分散処理基盤がある。
- データセンター as a Computer
- その一部を切り出すのがGCP
- 東京リージョン開設時は超忙しかった
- インフラ規模のインフラ（プラネットスケールインフラストラクチャ）
- 3年間で3兆円の投資

セキュリティ頑張ってます！

- すべてのレイヤーに厳しいセキュリティが施されている
- Googleのセキュリティ専任部門(750人)
- FISCにも対応！
- NICに特注チップを付けて、変なところにパケットを飛ばさないようにチェック
- データは暗号化され、分割と難読化でディスク単位では読みだせないようにしている。
データは、GCP内でやり取りされる（VMコピー時に、通信はインターネットに出ない）

HTTP(S)ロードバランサ

- 1IPでリージョン跨ぎの負荷分散
- 暖気申請なしで100万リクエストに対応

IaaSの特徴

- ライブマイグレーション
- 勝手にやってくれるクラウドサービスはGCPだけ。
- KVMベースのハイパーバイザで対応している
- 1000VMが5分で起動する
- VMネットワークは16Gbps
- GCPカスタムマシンタイプ（GPU特化型とか）

BigQuery

- SaaSのようなデータウェアハウス
- 72GBのフルスキャンが6.7秒
- 大量サーバとストレージ、ペタビットネットワークによる超並列処理クエリ
- 1TBを1秒でスキャンするために、10000ディスクスピンドルを用意する考え方

そろそろDeep Security

- BigQueryでDSのログを検索（1.32TB, 40億レコード）
- 4.2秒で検索！

#我が家の箱入り娘を世間に晒すのは危険なのでDeep Securityに見守ってもらった話
フューチャーアーキテクト株式会社
日比野さん

Deep SecurityとElasticSearch

- ハニーポットに対する通信をDSでの検知状況を可視化
- パロアルトのファイアウォールも用意
- ハニーポットはコンテナ
- 今回は、サーバ型、低対話型のハニーポットを用意
- 低対話型は、簡単だが取れる情報はそれなり

標的型攻撃の攻撃フェーズに対してハニーポットが取れる情報

- 偵察
- 情報探査
- 情報集約
- 情報送信

ハニーポット書籍

- 実線サイバーセキュリティモニタリング
- サイバー攻撃の足跡を分析するハニーポット観察日記

今回のハニーポットは、Open Canaryを採用（コンテナでデプロイ）

- Dockerコンテナ実行環境を用意して、
- ログはLogStashでElasticSearchに送信
- ハニーポットのAWS適正利用規約がある（事業者によって異なるので注意）
- Deep Securityは、10.1を使用
- DSaaS環境を利用（今回は双方向通信を採用）
- Deep Securityのログは、UDP514で通信させた

Paro Alto

- 15日間は無料
- ライセンス高いから、忘れずに消す！

ログの可視化には、ElasticStackがおすすめ！

- Kibana
- Elastich
- X-Pack(有償サブスクリプション：レポーティング、アラート、グラフ、ML)
- 最新版5.5で構築し、Syslog受信したログをElasticSearch

結果

- 中国、台湾が大活躍
- 8/31-9/3ごろまで
- ピーク時6000件のログがでた（ParoAlto）
- 平日は、MSSQL(1433)が多かったが、土日はSSHが爆裂
- 攻撃で使われるアカウントやパスワードは、リストに載っているものがやはり多かった（デフォルトパスワードは、やはり危険）
- 機械学習は、閾値を設けた使い方が有効そう
- Deep Securityのログの正規化は簡単にできた。
- ファイアウォール機能で遮断していたので、侵入防御やセキュリティログ監視は反応しなかった。

まとめ

- ログは事実だが、それだけでは意味がある分析結果は得られない
- とりあえずログを集めるのはNG
- 何をなすためにログを集めるのかという必要性を理解して、小さく始めるのがいい
- ログの結果から対策に活かすPDCAが大事！


#Deep Security APIを活用したルールアップデートの自動化について
アイレット株式会社
恩田さん

Deep Securityは、securitypackというサービスで使っている。
ルールアップデートしてますか？

- 手動や自動で適用してもいいけど、いきなり防御されたら大変
- アップデート処理は、アクセスが集中するので処理が重くて大変！

DeepSecurity API

- REST
- Sorp

REST API

- 機能がだいぶ足りない
- 新しい機能が実装されている

SOAP API

- 古典的な機能が実装されている
- 機能の数は多数

SDK

- 統一されたフロントを提供するので区別しなくていい(機能の60％)
- dsm.py:マネージャークラス
- polices.py：ポリシークラス, ルールクラス
- が、GitHubプロジェクトは全然動いてない
- なので、足りない部分は実装しよう！

まとめ

- SOAPが解決してくれる

要望

- アップデート配信日はサーバーを強化してください！
- APIとUIのドメインを統一してほしい


今回も盛り上がった回でした！

今日はここまでです。
お疲れさまでした。
ちょっとずつ読むドメイン駆動設計 第一部 ドメインモデルを機能させる 第ニ章 コミニュケーションと言語の使い方6

# 1つのチームに１つの言語

書籍には、１つのチームに２つの言語(ドメインエキスパート側と開発側)があることへの批判が書かれていますが、問題はそこではなく、言語が「ない」ことが問題なのではないかなと思います。

同じ意味で複数の用語が、あるときはローカル変数に、あるときはグローバル変数、あるときは関数名に登場し、それがトランザクションスクリプトで書かれているため、変更があった場合に変更箇所を探すのに上から下まで何千行もあるファイルから探し当てなければならない。。。とか。

ドメインエキスパートとの会話でも複数の用語が同じ意味で使われているが、モデル化していないため、開発側はそれに気が付かずあちこちに同じ実装をしてしまう。。。とか。

開発側で使用しているデータベースの用語が打ち合わせで使われて、ドメインエキスパート側はあいまいに捉えれれて実装が終わってビューまで見れる段階でやっとそれが間違っていたことに気がつく。。。とか。
さらに問題はデータベースの用語は削除とか挿入とか１行とか、データとか開発者でなくてもなんとなく理解（実際はできていないが）できてしまうことがさらに問題を複雑にしたり。。。とか。

なんとなく画面ができあがったが、ユーザーがしたいこととなんとなく合わないという違和感の原因が項目の名前が不自然だったため。。。とか。。。

探せばいろいろ出てきますが、それがそのままユビキタス言語を使用する利点になるかと思います。

> ユビキタス言語を用いることにより、開発者側の会話やドメインエキスパートとの議論、そして、コードそのものでの表現がすべて、共有されたドメインモデルから得られた同一の言語に基づくようになる。(第一部
 第二章より)

![Untitled (1).png](https://qiita-image-store.s3.amazonaws.com/0/150455/6692cadc-a864-1592-e63c-26eca3f74c35.png)


1つのチームに１つの言語を！努力して手に入れよう。
ChromeのImage Capture API を使ってJavascriptで写真撮影

Image Capture API を使って写真撮影をしてみました

## Image Capture API とは

Chrome 59 で追加されたカメラを操作するAPIです


## デモ

https://tamanugi.github.io/imagecapture_take_photo_sample/

```html:index.html
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>test</title>
</head>
<body>

<div id="container" style="margin: auto;">
  <video id="video" autoplay width="320" height="320"></video>
  <canvas id="canvas" width="320" height="320"></canvas>
  <button onclick="takePhoto()">写真撮影!!</button>
</div>

</body>
<script>
let video  = document.getElementById('video')
let canvas = document.getElementById('canvas')
let imageCapture

window.onload = _ => {

  navigator.mediaDevices.getUserMedia({video: true})
  .then(mediaStream => {
    video.srcObject = mediaStream

    let videoTrack = mediaStream.getVideoTracks()[0]
    imageCapture = new ImageCapture(videoTrack)
  })

}

let takePhoto = _ => {
  imageCapture.takePhoto()
    .then(blob => createImageBitmap(blob))
    .then(imageBitmap => drawCanvas(canvas, imageBitmap))
}

/**
 * https://github.com/GoogleChrome/samples/blob/gh-pages/image-capture/grab-frame-take-photo.js 
 */ 
function drawCanvas(canvas, img) {
  canvas.width = getComputedStyle(canvas).width.split('px')[0];
  canvas.height = getComputedStyle(canvas).height.split('px')[0];
  let ratio  = Math.min(canvas.width / img.width, canvas.height / img.height);
  let x = (canvas.width - img.width * ratio) / 2;
  let y = (canvas.height - img.height * ratio) / 2;
  canvas.getContext('2d').clearRect(0, 0, canvas.width, canvas.height);
  canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height,
      x, y, img.width * ratio, img.height * ratio);
}

</script>
</html>

```


ImageCapture には takePhoto と grabFrame の２つの関数があるのですが
それぞれの違いがよくわからず・・・

公式デモ
https://googlechrome.github.io/samples/image-capture/
Laravelでログファイル名をカスタマイズする方法

Laravel5.3及び5.4でログファイル名を[任意の文字列]-yyyy-MM-dd.logに変更する方法について書く。

# laravel-yyyy-MM-dd.logに変更する
config/app.phpを以下のように編集するだけ。

```config/app.php
'log' => 'daily',
```

さらにここから、[任意の文字列]-yyyy-MM-dd.logというファイル名にする方法を以下に書いていく。

# [任意の文字列]-yyyy-MM-dd.logに変更する
## Laravel5.3まで
ConfigureLogging.php内のメソッドをオーバーライドする。以下の内容でapp/Bootstrap/ConfigureLogging.phpを作成する。

```app/Bootstrap/ConfigureLogging.php
<?php

namespace App\Bootstrap;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Foundation\Bootstrap\ConfigureLogging as BaseConfigureLogging;
use Illuminate\Log\Writer;

class ConfigureLogging extends BaseConfigureLogging
{
    protected function configureDailyHandler(Application $app, Writer $log)
    {
        $log->useDailyFiles($app->storagePath() . '/logs/[ここを任意の文字列に変更].log');
    }
}
```

## Laravel5.4
Laravel5.4ではConfigureLoggingが廃止されたので、代わりにLogServiceProviderを使用する。

以下の内容でapp/Providers/LogServiceProvider.phpを作成する。

```app/Providers/LogServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Log\LogServiceProvider as ServiceProvider;
use Illuminate\Log\Writer as Writer;

class LogServiceProvider extends ServiceProvider
{
    protected function configureDailyHandler(Writer $log)
    {
        $log->useDailyFiles(
            $this->app->storagePath().'/logs/[ここを任意の文字列に変更].log',
            $this->maxFiles(),
            $this->logLevel()
        );
    }
}
```

config/app.php内に以下を追加

```config/app.php
'providers' => [
  
    App\Providers\LogServiceProvider::class,
]
```

これで[任意の文字列]-yyyy-MM-dd.logというファイル名のログファイルを作成できる。
Git Challenge #6 参加記

2017年9月2日 (土) にミクシィグループ主催の[Git Challenge](http://alpha.mixi.co.jp/entry/2015/10/16/114203) [#6](https://www.facebook.com/mixihr/posts/1927690774153570)に参加してきました。

#参加したきっかけ
友人から話を聞き、このイベントの存在を知りました。ちょうど以下のような理由が揃っていたので、参加してみることにしました。

* 東京でのインターンシップが終わった直後というちょうど良い日程だった
* Gitはよく使っているツールなので馴染みがある
* 技術系のイベントにあまり参加したことがないので参加してみたかった

#Git Challenge
大雑把な流れとしては、

1. チュートリアル
2. ランチ
3. 本番
4. 懇親会

といった形でした。

新卒採用の一環として行っていることもあってか、参加者に__実務で役立ちそうなGitの知識を少しでも習得してもらおう__という意図を感じる問題設定やスケジュールとなっていました。そのため、競技プログラミングになんとなく抵抗感がある (しかし開発はバリバリやる) 人でも楽しめるイベントとなっているのではないかと思います。

このイベントでは、主催者側から指示された2人組でチームを組むのですが、自分のチームは自分が簡単な問題から地道に解いていき、もう一人が難しめの問題を解けそうなところから解いていく、といった戦略でやっていきました。この戦略自体はよかったと思うのですが、もう一人の人と解く問題が被ってしまうことがたびたびあり、問題を解く際にSlackで解く問題を宣言するなどの対策を行えばよかったというのが反省点でしょうか。

#感想
Git Challengeという競技自体は、Gitの使い方を楽しみながら実践的に勉強することができるため、新人研修等で取り入れるとちょうど良いように感じました。
また、ランチや懇親会等で現役のエンジニア (ミクシィグループの若手社員) とお話することができ、そういった意味でも参加してよかったです。
[廃版] C++ Builder > TTrackBar > 値変更中にOnChange()が繰返し実行される > 変更終了の検知案

(追記 2017/09/06)
<font color=red>
下記に記載事項は「ビルド環境」「OS環境」により再現しないかもしれません。
環境が変わった時点でバグとなる可能性が考えられるため、お薦めの方法ではありません。
なんらかの参考にはなるかもしれないため、記事としては残しておきます。
</font>

<hr>

```txt:動作環境
C++ Builder XE4
Windows 7 Pro (32bit)
```

スライダーとして使用を検討しているTTrackBar。

OnChange()イベントで処理をしようとすると、スライダー変更中の全てのイベントで処理が実行されてしまう。

例として、値を20から46に変更した場合、以下のように途中の値のイベントも発生してしまう。

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/8a0a1ebd-9f6b-a042-6621-726c502ceb65.png)

最後の46が三つ繰り返されるところが、値の変更を終了した時点。
この振る舞いを利用して、変更終了を検知するのはどうだろうか。

## 変更終了の検知 v0.1
### code 

```Unit1.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
	: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::TrackBar1Change(TObject *Sender)
{
	static int pre = -1;

	if (pre == TrackBar1->Position) {
		Memo1->Lines->Add("End change");
	}
	pre = TrackBar1->Position;

	String val = IntToStr(TrackBar1->Position);
	Memo1->Lines->Add(val);
}
//---------------------------------------------------------------------------
```

![qiita.png](https://qiita-image-store.s3.amazonaws.com/0/32870/5b7f05a5-879f-214f-f7ca-b999c272fc9e.png)

二回実行されるが、変更中のすべてのイベントを拾うよりは「まし」ではある。

### 補足

マウスでTTrackBarの位置変更時は同じ値が3つ続くことがある。
キーボードでTTrackBarの位置変更時は同じ値が2つ続くことがある。

## <font color=red>注意事項</font>

OnChangeイベントにて同じ値が繰返し出る現象は、記事の実行環境(C++ Builder XE4)でビルドして、実行をした場合に確認している。

異なるIDEのバージョンや異なるOSでの動作については未確認である。上記に基づく実装コードを使用していると、IDEバージョンアップ時やOS変更時に「はまる」かもしれない。
Spooky.jsでファイルのダウンロード - スクレイピング(実装編)


# いざ、実装

下記のように実装しました。

```js
// 助ネコ商品マスターダウンロード

try {
    var Spooky = require('spooky');
} catch (e) {
    var Spooky = require('../lib/spooky');
}

// 日付のフォーマットを楽にするモジュール
var dateformat = require('dateformat');

var now = new Date();
var date = dateformat(now, 'yyyymmdd_HHMMss');
// console.log(dateformat(now, 'yyyy年mm月dd日 HH時MM分ss秒'));

const spooky = new Spooky({
	child: {
		transport: 'http'
	},
	casper: {
		logLevel: 'debug',
		verbose: true,
		waitTimeout: 100000,
		viewportSize: {
			width: 1280,
			height: 1024
		},
        pageSettings: { // BASIC認証
            userName: 'hoge',
            password: 'hogehoge'
        }
	}
}, function(err) {
	if(err) {
		e = new Error('failed to init.');

		e.details = err;
		throw e;
	}

	spooky.start();


	spooky.debug = false;
	// UserAgent(PC)
	spooky.userAgent('Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36');

    // ページを表示
	spooky.open('https://example.co.jp/');

	// spookyと通常のnodejsとのメモリ空間は別々
	// https://github.com/SpookyJS/SpookyJS/wiki/Introduction

	// トップページ
	spooky.then(function() {
		this.mouse.move('a[href="item.cgi"]'); // 「商品マスター」メニュー上にマウスオーバー
	});
	// 商品マスターメニューをマウスオーバー
	spooky.waitUntilVisible('a[href*="item_import_goods.cgi"]', function() {
		this.click('a[href*="item_import_goods.cgi"]');
	});
	// 受注検索画面が表示されるまで待つ
	spooky.waitFor(function() {
		return this.getCurrentUrl() === 'https://example.co.jp/item_import_goods.cgi?';
	});

	// ここから、商品マスター画面
	spooky.then([{
		date: date
	}, function() {
		var path = "/output/";
        // CSVダウンロード
        var csvname = path + date + "_basic.csv";
        this.download("https://example.co.jp/item_import_goods.cgi?GET_CSV=CSV%E3%83%80%E3%82%A6%E3%83%B3%E3%83%AD%E3%83%BC%E3%83%89", csvname);
	}]);

	// run()内のfunctionは、spooky処理終了時にコールされる。exitを呼ばないとphantomプロセスが残ってしまう
	// ちなみにspookyインスタンスのfunction内でコメントを入れると動作しない
	spooky.run(function() {
		this.emit('next', "now exit!");
		this.exit();
	});

	spooky.on('next', function(msg) {
		console.log(msg);
	});

	spooky.on('error', function(e, stack) {
		console.error(e);
		if (stack) {
			console.log(stack);
		}
	});

});
```

this.mouse.move()で、マウスオーバーを再現できる。

今回ダウンロードしたいデータは、【csvダウンロード】ボタンを押すとダウンロードが始まるようなサイトだが、this.click()では、ダウンロードは始まらない。
this.download()の引数に、ファイルをダウンロードしたいURLとパラメーターを渡すことでファイルがダウンロードされる。

# cronで定期的にダウンロードしたい

とある商品マスターcsvのバックアップのために作成したので、このバックアップを定期的に実行したい。
定期的に実行する＝cronが思いつくのだが、下記のように書くだけだと動作しない。

```shell-session
* */1 * * * /usr/local/bin/node /home/hoge/backup.js
```

原因はcronの環境変数がザルのため、Phantom.JSの実行ファイルパスが見つけられないことが原因。
下記のサイトを参考に、crontab内にPATHを設定することで動作するようになった。
http://dqn.sakusakutto.jp/2014/04/crontab_path.html

```shell-session
PATH=/usr/local/bin:/usr/bin:/bin
* */1 * * * /usr/local/bin/node /home/hoge/backup.js
```
RubyでGUIアプリケーション

Rubyで色々GUI環境試してみて[ruby-gnome2](https://github.com/ruby-gnome2/ruby-gnome2)使うのが一番しっくりきたので

## 環境

- Mac OS 10.12.6
- Ruby 2.4.1
- ruby-gnome2 3.1.8

```bash:bash
mkdir gtk3sample
cd gtk3sample
bundle init
vim Gemfile
```

```Gemfile:Gemfile
# frozen_string_literal: true
source 'https://rubygems.org'
git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
gem 'rake'
gem 'gtk3'
```

```bash:bash
bundle install --path vendor/bundle
vim sample.rb
```

```ruby:sample.rb
require 'gtk3'

app = Gtk::Application.new('org.gtk.example', :flags_none)

app.signal_connect 'activate' do |application|
  window = Gtk::ApplicationWindow.new(application)
  window.set_title('Window')
  window.set_default_size(200, 200)

  label = Gtk::Label.new('Hello, Gtk3')
  window.add(label)

  window.show_all
end

puts app.run
```

```bash:bash
bundle exec ruby sample.rb
```

![スクリーンショット 2017-09-05 19.33.19.png](https://qiita-image-store.s3.amazonaws.com/0/80816/428b6ff5-cce9-9f98-e1af-840d634f8dfa.png "スクリーンショット 2017-09-05 19.33.19.png")

# 参考

- [RubyでGUIアプリケーションを書く](https://www.slideshare.net/xmisao/rubygui-77390099)
- [kwskgtk](https://github.com/xmisao/kwskgtk)
- [ruby-gtk3-tutorial](https://github.com/cedlemo/ruby-gtk3-tutorial)
Unity 2017.x+InputField+Androidで日本語入力ができない問題への対策

Unity 2017.1 において Content Type を Standard 等にしていると、 Android 上で InputField から日本語入力できない（日本語入力に切り替えられない）というケースがあるようです(2017.2も試しましたが現時点では改善なしでした)。
こちらは InputField 経由でなく、自分で `TouchScreenKeyboard.Open` を用いてキーボードを呼びだすことで回避可能のようでした。
以下サンプルコードです。

```
using UnityEngine;
using UnityEngine.UI;
using System.Collections;

/// <summary>
/// 2017.x を用いたバイナリが Android 上だとキーボードで日本語入力できない問題のワークアラウンド用.
/// InputField の子に Button を置き、その Button にアタッチして使用する.
/// </summary>
public class InputFieldButton : Button {

    private InputField inputField
    {
        get
        {
            if (inputField_ == null) {
                inputField_ = GetComponentInParent<InputField> ();
            }
            return inputField_;
        }
    }
    private InputField inputField_;

    private TouchScreenKeyboard keyboard_ = null;
    private string originalText_ = "";
    private bool wasCanceled_ = false;

    void CreateKeyboard()
    {
        if (keyboard_ != null) return;
        if (!IsInteractable ())    return;

        if (!inputField.textComponent || inputField.textComponent.font == null)
            return;

        originalText_ = inputField.text;
        keyboard_ = TouchScreenKeyboard.Open (inputField.text, TouchScreenKeyboardType.Default, true);
    }

    void DestroyKeyboard()
    {
        if (!inputField.textComponent || !inputField.IsInteractable ())
            return;            

        if (wasCanceled_) {
            inputField.text = originalText_;
            wasCanceled_ = false;
        }
                
        if (keyboard_ != null) {
            keyboard_.active = false;
            keyboard_ = null;
            originalText_ = "";
        }
    }

    void LateUpdate() {
        if (keyboard_ == null) return;

        inputField.text = keyboard_.text;

        if (keyboard_.wasCanceled) {
            wasCanceled_ = true;
            DestroyKeyboard ();
        }

        if (keyboard_.done) {
            DestroyKeyboard ();
        }
    }

    public override void OnPointerDown (UnityEngine.EventSystems.PointerEventData eventData)
    {
        CreateKeyboard ();
        base.OnPointerDown (eventData);
    }

    public override void OnPointerClick (UnityEngine.EventSystems.PointerEventData eventData)
    {
        CreateKeyboard ();
        base.OnPointerClick (eventData);
    }
}
```
CEDEC 2017 レポート

8月30〜9月1日の間、パシフィコ横浜にて開催されたCEDEC 2017に３日間参加してきました。このレポートでは私が出席したセッションについての報告をしたいと思います。SNS投稿不可のセッションもあったのでご了承ください。

#8月30日
######Technical Artist Bootcamp 2017 vol.1 「Automation for TA」
jenkinsを使った自動化の講演でした。Mayaの起動、Eメール通知などをjenkinsでできるようにしていました。さらにPythonのvertualenvを使った開発環境説明やjenkins、static linkを使ってライブラリ等を自動で更新できるようにする取り組みを説明していました。このあとのセッションでもjenkinsを使った効率化や自動化の話がかなり出てきたのでjenkinsに興味を持ちました。

######アーティストのためのTimeline活用術
最近Unityに映像表現向けのタイムラインエディタが機能追加されたらしく、それを使った説明が今回のUnityのセッションで多かったです。このセッションではタイムラインエディタを利用してゲームのカットシーンなどの作成に使える活用方法を説明していました。カメラやサウンドの設定が簡単にできるようになっていました。

######〜アーティストだけでやったらこうなった！〜Unityを使ったリアルタイムなアニメ映像表現
Unityちゃんの製作者の京野さんのセッションでした。このセッションもタイムラインエディタを使って映像表現に挑戦する話でした。今までのUnityちゃんの扱いと違い、シリアスな雰囲気を出している動画が見れました。この制作ではタイムラインエディタを使用してAfterEffectsのように映像を作っていこうという取組みでしたが、実際はなかなかAfterEffectsのように扱えなかったみたいで、かなり独自の方法で作成していたようです。Unity標準のエフェクトを多様したりして力技で色を作っていたみたいです。特に助かった機能がMayaのリファレンス機能らしく、DCCツールで何回もデータをインポートしなくても、プレファブに自動で適用することができたようです。

######無駄な反復作業とオサラバ！ビジュアルツールでUnityのアセットワークフローを最適化する
UnityのAsset Bandleを扱いやすくするためのAsset Bandle Graph Tool(ABGT)についての講演でした。ABGTはグラフのノードをつないでアセットを制御するツールで、使用するアセットの条件を絞ることでアセット作成を分けることができるようでした。

#8月31日
######Maya+Pythonでインハウスツールを作ろう！
Pyside,Qt Designerを使用してMayaのモデルをアセット化してインポートできるようにする画面の作成の仕方の講演でした。Qt DesignerでGUIを作成し、PyQtUtilを使用してMayaのウインドウに表示させていました。アセットを登録するためのDBはsqlite3を使用していて、Pythonでスタンドアローンでサーバーを立てていました。PythonのctypesでOpenGLの関数を呼び出してサムネイル画像も自動で作成できるようにスクリプトを組んでいました。また、処理に時間がかかっているところを特定し、修正するところまで実演していました。

######アーティストのためのリアルタイムリアルタイムシェーダー学習法
基本的なシェーダーの扱い方やプログラム上でどうやって動くのかといったことについての講演でした。シェーダーはコンピュータの中でどんなように動いているのかや、シェーダーでできる表現についてや、勉強するためにどんな技術資料を見るべきかなどをお話していました。

#9月1日
######VRリアルタイムCGアニメーションの演出・作り方ーVR特有の壁を超えるためにー
視線誘導や表現のガイドラインなど、VRの空間においてユーザーの体験をどう制御するかといった取組みの講演でした。


######キャラクターらしさ学習AI：多数のキャラクターの個性や違いの可視化によるシナリオライティング支援システムの事例
キャラクター特徴を抽出するために用いられたAI技術の講演でした。キャラクターのセリフのCSVファイルからそのキャラクターを特徴づける言葉を学習し、どういった属性のキャラクターなのかをグラフで可視化できるようにしていました。これによってキャラクターの監修が効率化でき、また被っているキャラクターがいないかなどが調べられるので差別化が計れるということでした。

######クラウドの分析システムを活用したアクセスログにもとづくリアルタイム不正ユーザーBANシステム
AWSのKinesis Analyticsを使用した自動アカウント停止システムの講演でした。リソースが大量に消費されている事態を見て、不正なアクセスがとても多くなっていることを確認し、それを解決するために実装をしたそうです。複数のAPIのログから不正アカウントを特定するためストリーム処理を施していました。ログが時間通りに来るかがわからなかったため時間通りに集計するのが難しかったそうです。

######本当にリアルなMixied Realityコンテンツを実現するための技術開発
MRコンテンツを作成に挑戦する講演でした。技術力もすごかったですが、MRコンテンツを作成するのがVRより遥かに手間がかかるという印象を受けました。ある一定の空間を死角がないようにスキャンし、それをデモルームメッシュと合わせてバーチャルとリアルの空間の位置を合わせていました。デバイスと空間の位置を合わせるのに輝度を測り、マッチするポイントを探すなど位置を調整するのがすごく大変だと思いました。

#感想
今回初めて参加してまず規模感に驚きました。ゲーム業界の様々な方々が参加し、セッションの内容も技術や芸術、ビジネスの話など様々な講演がありました。そのため非常に人も多く、人気のセッションは会場の外まで行列が出来ました。セッション以外にも様々な企業などがVRなどの技術的な展示を行っていました。個人的にはLive2DのVRが面白かったです。特徴的だったのは砂に空気を送り込み流体として扱っている展示でした。砂がお風呂みたいになっていました。
NetworkManagerからdnsmasqを起動しないようにする

自宅のPCがdnsmasqありだと名前解決がうまくいかないので切る方法をメモしておく。

## /etc/NetworkManager/NetworkManager.c を編集

```diff 
 [main]
 plugins=ifupdown,keyfile,ofono
-dns=dnsmasq
+#dns=dnsmasq

 [ifupdown]
 managed=false
```

## NetworkManagerの再起動
```
sudo systemctl restart NetworkManager
```
[Swift] 画像をリサイズする

#画像をリサイズする
UIImageを指定した横幅に合わせてリサイズする方法を試してみた。

```swift:Extensions.swift
extension UIImage {
    func resized(toWidth width: CGFloat) -> UIImage? {
        let canvasSize = CGSize(width: width, height: CGFloat(ceil(width/size.width * size.height)))
        UIGraphicsBeginImageContextWithOptions(canvasSize, false, scale)
        defer { UIGraphicsEndImageContext() }
        draw(in: CGRect(origin: .zero, size: canvasSize))
        return UIGraphicsGetImageFromCurrentImageContext()
    }
}
```

```swift
//使用例
let image:UIImage = UIImage(named:"myImage")
let resizeImage = image.resized(toWidth: 300)
```
Processing for Android を AndroidStudio で動かしたい

# Processing って？
グラフィックに特化したビジュアルプログラミングが出来る、Javaベースの言語
例えばこういうのが作れる（オシャレ！）
https://www.openprocessing.org/

以下 Processing for Android を AndroidStudio で動かす設定

# まずはここからダウンロード
https://github.com/processing/processing-android/releases/tag/latest
AndroidMode.zip

# 展開してコピペ
```
.
├── examples
├── icons
├── libraries
├── mode
├── mode.properties
├── processing-core.zip // processing-core.jar にして　./app/libs に入れる
├── templates
├── theme
└── tools
```

# `build.gradle`
```
dependencies {
    compile files('libs/processing-core.jar')
}
```

# 詳細やサンプルコードは公式参照
http://android.processing.org/tutorials/android_studio/index.html

# license
core library のライセンスが LGPL なので注意
https://github.com/processing/processing-android/wiki/Copyright-and-Licensing

# まとめ
AndroidStudio でコーディングできる == Kotlin で Processing できる！

--- 
参考リンク
http://android.processing.org/
https://github.com/processing/processing-android
Gitコマンド覚書

#ローカル作業
##add
####特定のフォルダだけ追加する
`git add directory`
####複数のフォルダを指定して追加する
`git add dir1 dir2`
####複数のフォルダを指定して追加する（wildcard）
`git add dir*/`

##commit
####Text editorでコメントを書く
`git commit`
####1行コメントを書く
`git commit -m "comment"`
####複数行コメントを書く
`git commit -m "summary" -m "detail1" -m "detail2"`

##config
####設定例: コマンドエイリアスを作る
`git config --global alias.co checkout`
`git config --global alias.ada 'add -A'`
オプションを付ける場合はシングルクォートでくくる。

####設定削除例: コマンドエイリアス
`git config --global --unset alias.co`

##diff
####ワーキングツリーの差分を見る
`git diff`
####任意のファイル同士の差分を見る
`git diff --no-index -- file_1 file_2`

##log
####表示数を指定する
`git log -n2`
最近の変更だとわかっているとき
####ログの1行めのみ表示する
`git log --oneline`
さっと探したいとき
####ファイルをどうした（追加、削除、変更）のか知りたいとき
`git log --name-status`

##merge
####今のブランチにmasterをマージする（基本）
`git merge origin/master`

####remoteブランチの内容を強制的に反映させる
`git merge origin/master --theirs`

##remote
####接続先リモートリポジトリのURLを知る
`git remote -v`

##reset
####ワーキングディレクトリの変更を戻す
`git reset HEAD target/directory/path`
SVN revertに相当する。

####ローカルの変更をすべて破棄する
`git reset --hard`
####まだpushしていないコミットを取り消す
（number は reflogコマンドで確認する）
`git reset --hard HEAD@{number}`
####addを取り消す
`git reset path...`

##rm
####ファイルは残して管理外にする
`git rm -r --cached directory`
やっぱり管理をやめたいファイルがあるとき
####ファイルも消す
`git rm -r directory`
`git rm file`

##stash
####現在のローカルの変更を保存する
`git stash`
`git stash save "覚書ラベル"`
stashの実行後は、ローカルの変更は消えてHEADに戻る
####現在のローカルの変更の一部を保存する
`git stash push --message "覚書ラベル" -- pathspec`
特定のパス(pathspec)にあるファイルのみ。
####最後に保存したstashを取り出す（stackからは消える）
`git stash pop`
####最後に保存したstashを適用する（stackに残る）
`git stash apply`
ためしに適用してみたり、複数のブランチに適用したときに使う。
####先頭のstashを破棄する
`git stash drop`
####stashの一覧を見る
`git stash list`
####特定のstashの内容（ファイル一覧）を見る
`git stash show stash@{0}`

##tag
####現在のブランチにタグをつける（そしてリモートに上げる）
`git tag name_of_tag`
`git push origin name_of_tag`
####特定のコミットにタグをつける
`git tag name_of_tag commit_hash`
####コメントを付けてタグを作成する
`git tag name_of_tag -m "comment"`

[その他のtagコマンド](https://qiita.com/ritukiii/items/79a46103bdf24229a1ef)

#リモート
##checkout
####現在のブランチから新しいブランチを作る
`git checkout -b NewBranch`

##push
####ローカルで作成したブランチをpushする
`git push --set-upstream origin`

# 環境変数
[環境変数一覧](https://git-scm.com/book/ja/v2/Git%E3%81%AE%E5%86%85%E5%81%B4-%E7%92%B0%E5%A2%83%E5%A4%89%E6%95%B0)
gitではなく、Linux系の環境変数の設定方法だが、以下のように設定と解除を行う
`export 変数名=値`
`unset 変数名`

リモートとの接続（fetchやpull）がうまくいかないときに、
`export GIT_CURL_VERBOSE=`
としてから実行すると、curl -v 相当のログが出る。
[Symfony2 Monolog] Monologをごにょる

## あらまし

symfony2を使おうと思うんやけど、ログファイルが１つになってるのが気に食わんねんな。
dev.logとかprod.logとか。
なんの機能のログなんかわかったもんちゃうし、ファイルサイズでかなるし。
たとえばbundleごとに動的に出力先ファイルが切り替わるとか、そういうカスタムができる状態にできたらええなぁって。
と、そういうわけでね (´･ω･｀)

どういう風に切り替えるねんって話は書いてへんからね。
そこは自分で練ってや、ボウヤちゃうんやし (´･ω･｀)

## classの配置

あとで出てくるserviceの設定でどうとでもできるので、ご自由にどうぞ。

* 配置の例
    * XxxBundle/Logger/Formatter/CustomLineFormatter.php
    * XxxBundle/Logger/Handler/CustomStreamHandler.php

## config.ymlの設定

```/app/Resources/config/config.yml
monolog:
    handlers:
        main:
            type: service
            id: handler.stream.custom
```

- ノーマルで使ってもしゃーないので、Monologハンドラをすべて削除する。
- mainを"type=service"として記述する。
- mainに対して利用するサービスIDを指定する。

## service.ymlの設定

```/app/Resources/config/service.yml
service:
    # ログフォーマッタ"line"
    formatter.line.custom:
        class: 'namespace\of\CustomLineFormatter'
        arguments: [ null, null, true, true ]
    # ログハンドラ"stream"
    handler.stream.custom:
        class: 'namespace\of\CustomStreamHandler'
        arguments: [ '%kernel.logs_dir%/#log_file#.log', 100, true, null ]
        calls:
            - method: setFormatter
              arguments: [ @=container.get('formatter.line.custom') ]
```

- ストリームハンドラのサービスを登録する。
- ストリームハンドラからログフォーマッタを利用するよう設定する。
    - "@=container.get('サービス名')"でサービスコンテナからサービスを拾える。
        - [[Symfony2 config] サービスコンテナのサービスを拾う](http://qiita.com/Joxy441/items/6079dbc13c23335ad412)
- ログフォーマッタの第３第４引数をtrueに固定しているのは、"[]"が邪魔なのと、見難いので改行して欲しいから。

## ストリームハンドラ

```XxxBundle/Logger/Handler/CustomStreamHandler.php
class CustomStreamHandler extends StreamHandler {
    CONST DEFAULT_LOG_FILE_NAME = 'default';

    public function __construct($stream, 略) {
        parent::__construct($stream, 略);
        $this->replaceLogFileName();
    }

    private function replaceLogFileName() {
        $log_file_name = $this->generateLogFileName();
        // 出力対象ファイルを書き換える。
        $this->url = str_replace('#log_file#', $log_file_name, $this->url);
    }

    private function generateLogFileName() {
        // ごにょごにょしてファイル名を決定する。
        return $lig_file_name;
    }

    // ...
}
```

親クラスのコンストラクタの実装内容はこちら(↓)

```StreamHandler.php 
public function __construct($stream, 略) {
    parent::__construct($level, $bubble);
    if (is_resource($stream)) {
        $this->stream = $stream;
    } elseif (is_string($stream)) {
        $this->url = $stream;
    } else {
        throw new \InvalidArgumentException('A stream must either be a resource or a string.');
    }

    $this->filePermission = $filePermission;
    $this->useLocking = $useLocking;
}
```

- \$streamがリソースではない場合には、\$this->streamには反映せず、$this->urlに反映される。
    - ymlからpathが拾われた場合、そのルート("is_string()"側)に入る。
    - テキスト指定なので、ファイルパス書き換え対象は\$this->urlとなる。
- まあ、本番環境やったらStreamHandlerじゃなくて、CrossedFingerHandler？の方がええやろかね。

## ほんでもって

なんかよくわからんけど、対象ファイルの差し替えとしては一応機能するようになったものの、想定した以外のファイルが転がってることが結構あって、謎。
hoge.css.logとか。
(処理の詳細は伏せるが)何をしとるんだ (´･ω･｀)
タイムスタンプを見る限りでは、何かしらのエラーがあったときとかっぽいけど。
ポートを占有しているプロセスの特定

# 概要

Windowsのコマンドプロンプトで、特定のポートを使用しているプロセスを特定する。

## ポート番号からPIDを調べる

```
netstat -ao | find "8080"
```

-a
>すべての接続とリッスン ポートを表示します。

-o
>各接続に関連付けられたそれらを所有するプロセス ID を表示します。

## PIDからプロセス名を調べる

```
tasklist | find "123"
```

## 課題

ポート番号からプロセス名を一発で調べたい
flowtypeで存在しないkeyを取り出すときに型エラーを出す


以下のようなジェネリックな関数を定義します。
$Keysを使いオブジェクトのキーを検査します。
これだけでは、実用性があるかはわかりませんが、特定の場合に便利なときがあります。

```js
function getObj<V: Object, O: { [*]: V }, K: $Keys<O>>(obj: O, key: K): V {
  return obj[key]
}
```

こんな感じで使えます。

```js
function getObj<V: Object, O: { [*]: V }, K: $Keys<O>>(obj: O, key: K): V {
  return obj[key]
}

type User = { name: string }

const user1: User = { name: 'aclie' }
const user3: User = { name: 'bob' }

const users = { id1: user1, id3: user3 }

const v1 = getObj(users, 'id1')
const v2 = getObj(users, 'id2')
const v3 = getObj(users, 'id3')

```

id2は定義されてないので、型エラーが発生します。


```
 23: const v2 = getObj(users, 'id2')
                ^^^^^^^^^^^^^^^^^^^^ function call
 23: const v2 = getObj(users, 'id2')
                              ^^^^^ property `id2`. Property not found in
  7: function getObj<V: Object, O: { [*]: V }, K: $Keys<O>>(obj: O, key: K): V {
                                                  ^^^^^^^^ object literal
```


しかし、データを取り出すために一度関数を通す必要があり取り回しが悪いです。

`{ [key: string]: Object }`のようなマップオブジェクトのキーの検査は現状諦めています。
もし知見があれば、コメントまたはTwitterまで教えてください。
[git] rebase-applyディレクトリを作れないエラー

## 現象
```bash
$ git rebase master
```

で表題のようなエラーが出た。

正確なエラー詳細は下記

```
It seems that I cannot create a rebase-apply directory, and I wonder if you are in the middle of patch application or another rebase. 
If that is not the case, please
        rm -fr /Project/.git/rebase-apply
and run me again.  I am stopping in case you still have something valuable there.
```

つまりは、やり残しのRebaseがあるよってことらしいが記憶にない。それってすごくやばそう。
しかしこのままでは進めないので、指示通り`rebase-applyディレクトリを削除して再開すると無事Rebasedされる。

## 対応
### Execution
```bash
$ rmdir ./git/rebase-apply
$ git rebase master
```
### Result
```
First, rewinding head to replay your work on top of it...
Applying: Add column to new table
Using index info to reconstruct a base tree...
M	db/schema.rb
Falling back to patching base and 3-way merge...
Applying: Remove another branch's commit
```


## 結論
rebaseのほったらかしには気をつけましょう。
[Android] AppBarLayoutの伸縮に連動して○○する

`AppBarLayout` の View インスタンスに対して、下記のように `addOnOffsetChangedListener()` をセットすればOKです。

```java:
someAppbarLayout.addOnOffsetChangedListener((anAppbarLayout, verticalOffset) -> {
    float per = ((float) Math.abs(verticalOffset) / someAppbarLayout.getTotalScrollRange());

    // .. something to do
});
```

`AppBarLayout` の縮み具合によって変数 `per`(float) の値が `0.0`〜`1.0` の間で変わるので、あとはお好きな演出を。