OmniAICreator/Qiita-1.07M huggingface dataset:
CircleCIの環境変数設定のTips

# はじめに

CircleCIを使ってElectronアプリのビルド環境を構築する中で環境変数の設定で躓いた箇所がありました。
そこから得られたTipsをこの記事にまとめます。
実行環境としてmacosを使っていますが、おそらくその他の環境でも同様だと思います。

環境変数に関する公式のドキュメントは [環境変数の使い方 - CircleCI](https://circleci.com/docs/ja/2.0/env-vars/) にあります。

# 実行環境

- CircleCI 2.0
- macos
    - xcode10.0.1

# Tips

## `~` や `$HOME` が使えないところがある

`Environment Variables` や `.circleci/config.yml` の `environment` で `~` や `$HOME` を使い、その環境変数を使用すると `No such file or directory` のエラーになりました。

おそらくこれらで設定した環境変数は `export x="~"` このように設定され、期待したものではないと想像しました。

### 解決策

公式にある `run ステップ内で指定しているシェルコマンドで宣言されたもの` の方法で設定して解決します

## シェルコマンド `export hoge=fuga` では設定できない

`export hoge=fuga` では設定できませんでした。

### 解決策

公式にある通り `echo 'export hoge=fuga' >> $BASH_ENV` で設定できます

## runを分けないと環境変数が正しく読み込めない

これはダメでした。

```yaml
      - run:
          name: Setup Path And File
          command: |
            echo 'export HOGE_LINK=~/hoge.txt' >> $BASH_ENV
            echo 'fuga' > $HOGE_LINK
```

### 解決策

runを分けることで解決できます。

```yaml
      - run:
          name: Setup Path
          command: |
            echo 'export HOGE_LINK=~/hoge.txt' >> $BASH_ENV
      - run:
          name: Setup File
          command: |
            echo 'fuga' > $HOGE_LINK
```

# 最後に

間違っている箇所などあれば指摘頂けると幸いです。
Linux(debian系)にwindows￥dirをマウントする

必要なpackageのinstall

$ sudo apt-get install cifs-utils

をインストールする。

$ sudo mkdir /mnt/windows　マウント先を作成

[コマンド]
$ sudo mount -t cifs //192.168.x.x/pub /mnt/windows -o user=xxxx(WindowsのUserName)

コマンドが面倒であれば/etc/fstabの編集(デリケートなので注意して下さい)
$ sudo cp -p /etc/fstab /etc/fstab.org　で、オリジナルの退避をします。

編集箇所[/etc/fstab 例]
//192.168.x.x/pub /mnt/windows cifs user=xxxx,rw,noauto,owner 0 0

IP Addressのxには環境
userのxには(WindowsのUserName)を指定して下さい。
xとしても有効にはなりませんので。

こうしてやれば
$ sudo mount /mnt/windows　だけで
password for UserName@//192.168.1.x/pub:　と聞かれるのでwindowsのUser(administrator)のpasswordをいれると
マウントが可能になります。

$ cd /mnt/windows に移動すればWindows共有がマウントされています。
$ df　すると
//192.168.1.x/pub xxxxxxxx xxxxxxxx xxxxxxxx xx% /mnt/windows

となります。

LinuxのFileをWindowsに保存するのも良いかもしれません。
私はWindows/pub(共有先)にBackUpFileを保存しています。

最後に
$ sudo umount /mnt/windows　でアンマウントします。。
Address already in useの対処法(Windows)

下記エラーで実行が妨げられた場合、すでに使っているアドレスを一度キルしないといけないみたい。

`org.jboss.netty.channel.ChannelException: Failed to bind to: /0.0.0.0:[ポート番号]`
`Caused by: java.net.BindException: Address already in use: bind`

方法(Windows)：コマンドで
`netstat -nao | find "[ポート番号]" `で使用しているProcessNoを探す
（もしくは`netstat -an -p tcp`する）
出たら
`taskkill /f /pid (探したProcessNo) `
で、キルしてやって再度実行すればおｋ。

要は一人しか使えないものに対して
すでに使ってるお前(ProcessNo)をシメて(taskkillして)、おれが使う的な感じ。



※Eclipseの場合
タスクマネージャー＞サービス＞Tomcatを停止でも行けた
通信速度の「上り下り」とクラウドやFWでの「上り下り」の意味の違い

# 2019/02/18　追記

通信速度のときに見かける「上り・下り」の概念では「アップロード・ダウンロード」のことを指すが、クラウドの場合は「上り・下り」を「クラウドへのIN・クラウドからのOUT」を示す。

上り・下りの意味が逆になっているがこれはどういうことなのか？

## 答え

通信速度での「上り・下り」は**「upload/download」**であり、
クラウドでの「上り・下り」は**「ingress/egress」**である。

日本語では同じ言葉となるが元の英語が異なるため指す内容が違っていた。

---

# もともとの文章

ネットワークのおける上り・下りってご存知ですか？

皆さんが使ってるスマホからみた場合は以下のとおりです。

* ダウンロード：下り
* アップロード：上り

さて、ここでGCPの料金表を見てみましょう。

どうやらGCPのVPC（ネットワーク）では、**上り通信**が無料のようです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/68103/fdd63a22-3ec2-320a-5abe-215c332dc334.png)

ということはGCPからみると「外に出ていく通信」が無料ということですね。

しかしこちらを見てください。これは同じページを英語で表示したものです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/68103/8d4be606-4200-73b9-dc6a-0e1d9a21263e.png)

ん？　無料なのは**「Ingress」**となっていますね。

IngressとはVPCに入ってくる通信のことを指し示しますので、GCPからみると**「中に入っていく通信」**が無料ということですね。

どゆこと？？？
つまり「Ingress＝上り」ってこと？？　しかしIngressを

辞書をひくとingress=入ってくるというニュアンスなので、アップロード（出ていく）を意味する上りとは違いますよね。

```
ingressの意味や使い方 【名詞】 (⇔egress) 《文語》【不可算名詞】1立ち入り，入来，進入.2入場権，入場の自由. 
```

どうしてこんなことになっているのでしょうか？？？

そしてみなさん誤解しないのでしょうか？？？
GitHubのドラフトプルリクエストを試す

2/14のGitHubブログで、**ドラフトプルリクエスト** が紹介されていた。

Introducing draft pull requests - The GitHub Blog https://github.blog/2019-02-14-introducing-draft-pull-requests/

## ドラフトプルリクエストの作成
プルリクを作成するときに *[Create Draft Pull Request]* を選択すると、ドラフト状態となる。

![スクリーンショット 2019-02-15 10.27.29.png](https://qiita-image-store.s3.amazonaws.com/0/52227/3d15d4bd-7111-299a-bb3c-7b06e70bb1e6.png)

ドラフト選択後、あとはそのままボタンを押すだけ
![スクリーンショット 2019-02-15 10.27.41.png](https://qiita-image-store.s3.amazonaws.com/0/52227/7df37626-571c-72c0-dffb-5c98e0878e45.png)

ドラフト状態になると、色などのスタイルが変わるし、マージボタンが押せなくなっった。

　![スクリーンショット 2019-02-15 10.31.59.png](https://qiita-image-store.s3.amazonaws.com/0/52227/cc7b5b4e-951b-dc6f-0d63-4d27f4a070ec.png)

## ドラフトからレビューにするには

**[Ready for review]** を押すとすぐレビュー状態に切り替わった。
マージボタンも押せるようになってた。
![draft_click.png](https://qiita-image-store.s3.amazonaws.com/0/52227/b9f3d1d6-9ad4-5344-3cfb-e5fdc2b9ec00.png)

## まとめ
もうタイトルにWIPをつけるのではなく、ドラフトプルリクエストを使っていこう
NCL > function > getMainMarker(wks) > wksを受け取って、塗りつぶした星形のリソースを返す

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
GeForce GT 730 1GB GDDR5
CentOS 6.9 (64bit)
NCAR Command Language Version 6.3.0
for WRF3.7.1, WPS3.7.1
  openmpi-1.8.x86_64 とその-devel
  mpich.x86_64 3.1-5.el6とその-devel
  gcc version 4.4.7 (とgfortran)
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

NCL(NCAR Command Language)関連。

### 関連

- [NCL > マーカー > 塗りつぶした星形を配置する](https://qiita.com/7of9/items/a20670f52afde81af84f)

マーカーの定義をする場合にインデックスを作るが、それにはwksが必要となる。
マーカーの各種定義とwksの生成後の実装が読みにくくなったため、NCLの関数を使って整理することにした。

この記事では作った関数の紹介を行う。

### 資料

関数の作り方の資料
- https://www.ncl.ucar.edu/Training/Webinars/NCL_Processing/NCL_Processing_Intro_Part_3.pdf


### 実装

関数部分だけの実装

詳細は[NCL > マーカー > 塗りつぶした星形を配置する](https://qiita.com/7of9/items/a20670f52afde81af84f)を参照。

```ncl
undef("getMainMarker")
function getMainMarker(wks)
begin
 ; marker (filled star shape)
 mstring = "z"  ; filled start shape
 fontnum = 35
 xoffset = 0.0
 yoffset = 0.0
 ratio = 1.0
 size = 1.0
 angle = 0.0
 index_filled_star = NhlNewMarker(wks, mstring, fontnum, xoffset, yoffset, ratio, size, angle)

 ; filled star (white)
 wrkres = True
 wrkres@gsMarkerColor = "White"
 wrkres@gsMarkerIndex = index_filled_star
 wrkres@gsMarkerSizeF = 0.01
 return(wrkres)
end
```

getMainMarker()コール時に引数としてwks(workstation)を渡す。
Symbolオブジェクト

#Symbolオブジェクト
文字列の前に`：`をつけたもの。

```
:name
```
Symbolオブジェクトにすると、**文字列ではなく整数**として扱われる。
⇒処理速度が早くなる。

```
*Symbolでは同じSymbol名であれば同じオブジェクトとなる

*以下、ターミナルでpryを起動して実行
symbol1 = :name
symbol2 = :name

*以下2つは、同じIDが出力され、同一のオブジェクトであると分かる
symbol1.object_id
symbol2.object_id
```
オブジェクト指向の強みは変更可能性にこそあると思った。

オブジェクト指向って再利用できるから良いってどこの記事、本にもまとめられています。
そんなの誰でもわかってるけど、それだけではいまいちピンと来ていなかった。

たぶんそれは僕がオブジェクト指向ネイティブだから。
オブジェクト指向が普及していなかった時にプログラミングをしていた人からするとオブジェクト指向は画期的だったのだろう。でもそんなことは知ったこっちゃない、そうしろとプログラミング言語に言われるのだから。誰かに「あーしろ」「こーしろ」と言われるわけではない。そうしないと基本的に動かなかったり、意味不明な挙動をするのだ。

無意識にできていることは素晴らしい事ではあるが、なぜそれが良いのか、どうしてそうするのかを知っていないとエンジニアとは言えない。

そんなある日クライアントにデモを見せるタイミングがあって、デモ中にこんな風にできない？あんな風だといいよね？みたいな言葉が出る。

そんなときに

「あー、それなら秒でできますよ。... リロードしてください。」

「おー！！」

みたいな体験があるとかっこいい。

オブジェクト指向で書いていると挙動の簡単な変更はすぐにできる。
しかもオプションでいろいろ変更できるようにしているとなおさら。
Javascriptのプラグインなどは基本的にoptionで簡単な挙動は変更できる。
クライアントは基本的に表面の動きを見ているので、表面の変えたいところが目の前で変わるのを見れば魔法か何かだと思ってしまうのも無理がない。

エンジニアにとっては当たり前であるが、クライアント（非エンジニア）にとっては魔法に見えることが多くある。その芸を支えるのがオブジェクト指向だと思った。

単に書けるエンジニアではなく、デモで魅せられるエンジニアは強いとおもった。
【翻訳】Minimally Sufficient Pandas（エッセンシャル版）

# Overview

この記事は
[pandasクックブック-―Pythonによるデータ処理のレシピ](https://www.amazon.co.jp/pandas%E3%82%AF%E3%83%83%E3%82%AF%E3%83%96%E3%83%83%E3%82%AF-%E2%80%95Python%E3%81%AB%E3%82%88%E3%82%8B%E3%83%87%E3%83%BC%E3%82%BF%E5%87%A6%E7%90%86%E3%81%AE%E3%83%AC%E3%82%B7%E3%83%94%E2%80%95-Theodore-Petrou/dp/425412242X) の著者である [Ted Petrou](https://twitter.com/tedpetrou) 氏の以下の記事、

[Minimally Sufficient Pandas](https://medium.com/dunder-data/minimally-sufficient-pandas-a8e67f2a2428)

の一部を、許可を得て翻訳したものです。
https://twitter.com/arc279/status/1095511875050033152

全文は「何故そうしたほうが良いのか？」などにも詳しく言及していて長文のため、具体例だけ先に訳しました。
詳しい理由などは元記事を参照してください。
元記事の全文は[こちら](https://qiita.com/arc279/items/aa3042192df12600b1c6)です。

不自然な点、間違っている点などがありましたら指摘してもらえると助かります。
リポジトリは[ここ](https://github.com/arc279/translate-minimally_sufficient_pandas)にあります。


以下、忙しい人のための意訳です。

---

# カラム(Series)の選択にドット表記を使わない。ブラケット表記を使う。
* OK) `df[“count”]`
* NG) `df.count`

# `ix` メソッドは使わない
  * ラベルで参照する時は `loc` を使う
  * インデックスで参照する時は `iloc` を使う

# `at` `iat` は使わない

`loc` `iloc` より若干速いが、単一セルの参照にパフォーマンスを気にするなら `numpy.array` に変換した方がよい

# `read_table` は使わない
  * 同じ機能を複数の方法で実現できるのは混乱するので良くない
  * `read_csv` のデリミタを指定する

# na と null

* `isna` と `isnull` は同じ
* `notna` と `notnull` も同じ
  * `isna` `notna` を使う
  * `fillna` `dropna` との整合が取れる

# 算術、比較メソッドは必要な時以外使わない
  * 通常は演算子を使用する
  * `axis` を指定する必要がある場合だけメソッドを使う

# python 組み込みと同名のメソッドは pandas のメソッドを使用する

pandas のメソッドはcで実装されたメソッドを呼んでるので速い。(absだけは同じ)

* OK) `df.sum()`, `df.min()`, `df.max()`, `df.abs()`
* NG) `sum(df)`, `min(df)`, `max(df)`, `abs(df)`

# `groupby` の集計の書き方の統一

`df.groupby('grouping column').agg({'aggregating column': 'aggregating function'})` 方式を使う

（訳注）dictの順序を保持しない python3.6 未満だとカラムの追加される順序が不定になるので注意

# MultiIndex の扱い方

* 非常に扱いが複雑になるので使わないほうが良い（若干のパフォーマンス向上と引換に）
* 単一インデックスに直して扱うと良い（reset_index()を使う）

# `groupby`, `pivot_table`, `crosstab` の違い

* 具体例見た方が早い
* 本質的には同じことをやってる
* `groupby`: 結果が MultiIndex になる
* `pivot_table`: 結果が Single Index + 「集計列のユニーク値」の列になる
    * グループを比較する時は `pivot_table` を使う
* `groupby` は計算の途中経過、`pivot_table` は計算結果、と解釈すると良いのでは
* `crosstab` はカウント用途
    * `pivot_table` とできることは同じ
    * `normalize` パラメータで正規化できる
    * 相対頻度を見る時に `crosstab` を使う

# `pivot` メソッド

* データを整形(縦横の変換)
* 集約はしない。値の重複があるとエラーになる。
* `pivot` は使わず `pivot_table` の使用を検討したほうが良い。

# `melt` メソッド と `stack` メソッド
  * 具体例見た方が早い
  * 横持ちのデータを縦持ちに変換
  * `melt`: インデックスが列に移動するので `set_index` してやる必要がある
  * `stack`: 縦持ちの種別に指定した列をindexとして扱う
  * `stack` より `melt` を使う（MultiIndexを避け列名も指定できる）

# `pivot` メソッド と `unstack` メソッド
  * 具体例見た方が早い
  * MultiIndex の縦持ちのデータを横持ちに変換
  * 列が  MultiIndex になる
  * 代わりに `pivot_table` を使ったほうが良い
CentOS7でPhalconの環境を構築するとても良い方法

via https://beyondjapan.com/blog/2017/02/execution-environment-php-phalcon-on-centos

#脳死でできるコピペコマンドリスト

###epelリポジトリのインストール
```bash
sudo yum install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm
```

###remiリポジトリのインストール
```bash
sudo yum install -y http://rpms.remirepo.net/enterprise/remi-release-7.rpm
```

###phpのインストール
```bash
sudo yum --enablerepo=remi-php72 install -y php php-mbstring php-mysqlnd
```
###Phalconのインストール
```bash
sudo yum --enablerepo=remi-php72 install -y php-phalcon
```

###確認
```bash
sudo systemctl restart httpd
php -r "echo Phalcon\Version::get();"
```
Slack の User ID を確認する

## はじめに
Slack の ID を教えて！みたいな場面よくあると思います（あるのか？）。
そんな時にパッと思い出せないですよね、自分の ID 。
これはそういう時の tips です。

## 手順
### 1. [Account Settings | Your workspace](https://droidkaigi.slack.com/account/settings#username)  にアクセスする

<img width="500" alt="スクリーンショット 2019-02-15 10.38.31.png" src="https://qiita-image-store.s3.amazonaws.com/0/185323/15aad2b7-4b12-d35f-7aac-769dbca033ff.png">
### 2. `expand` をクリックする

<img width="500" alt="スクリーンショット_2019-02-15_10_39_54.png" src="https://qiita-image-store.s3.amazonaws.com/0/185323/d4d15ecc-4c3f-7046-00e4-1e2a0022572c.png">

## 以上です
とても簡単でした。
NCL > マーカー > 塗りつぶした星形を配置する 

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
GeForce GT 730 1GB GDDR5
CentOS 6.9 (64bit)
NCAR Command Language Version 6.3.0
for WRF3.7.1, WPS3.7.1
  openmpi-1.8.x86_64 とその-devel
  mpich.x86_64 3.1-5.el6とその-devel
  gcc version 4.4.7 (とgfortran)
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

NCL(NCAR Command Language)関連。

### 内容

- 塗りつぶした星形を配置する
    - [predefined makers](https://www.ncl.ucar.edu/Document/Graphics/Images/markers.png)には塗りつぶした星形はない
    - フォントテーブルにある塗りつぶした星形を使う
        - [Font 35](http://www.ncl.ucar.edu/Document/Graphics/Images/font35.png)の"z"に対応


### 参考実装

https://www.ncl.ucar.edu/Document/Functions/Built-in/NhlNewMarker.shtml
のExample4をもとにした

- 余分な処理の除去
- 星形仕様のためのパラメータ


### 実装

```filledMarker_190215.ncl
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"

begin
  wks = gsn_open_wks("x11","marker")
  gsn_define_colormap(wks,"rainbow+gray")

  canvas = create "canvas" logLinPlotClass wks
    "vpXF"                  : 0.0
    "vpYF"                  : 1.0
    "vpWidthF"              : 1.0
    "vpHeightF"             : 1.0
  end create

  mstring = "z"
  fontnum = 35
  xoffset = 0.0
  yoffset = 0.0
  ratio   = 1.0
  size    = 1.0
  angle   = 0.0
  new_index = NhlNewMarker(wks, mstring, fontnum, xoffset, yoffset, ratio, size, angle)

  mkres               = True
  mkres@gsMarkerSizeF = 0.2
  mkres@gsMarkerColor = "black"
  mkres@gsMarkerIndex = new_index
  datx = (/0.2, 0.6, 0.2, 0.6/)
  daty = (/0.2, 0.2, 0.6, 0.6/)
  gsn_polymarker(wks, canvas, datx, daty, mkres)

  frame(wks)   ; Advance the frame.
end
```

### 実行

```
$ ncl filledMarker_190215.ncl
```

![2019-02-15_10h31_47.png](https://qiita-image-store.s3.amazonaws.com/0/32870/0878930d-c0c7-88bd-6b0f-1e50069acc90.png)
SikuliX 1.1.4 コマンドラインから実行するメモ


# 概要
sikuliX 1.1.4からいろいろ変わっているがよくわかっていないので試行錯誤したメモ

# コマンドライン概要
```cmd:コマンド
java -jar sikulix.jarの置き場所 -r スクリプトフォルダ.sikuli
```
## 説明
sikulix.jarの置き場所はIDE起動するときに使っているので説明省略

スクリプトフォルダ.sikuli
これは名前をつけて保存した時のフォルダ名(.sikuliは自動で付与される)
![説明_.png](https://qiita-image-store.s3.amazonaws.com/0/345260/5c58eae2-314c-46c1-6893-2a219a793801.png)

適切なところに保存する.

#bat作成
-rでIDE起動せずに無人で動くのでそのままコマンドライン概要の中身を張り付ければ行ける。

勝手にマウスカーソルが動くので若干気持ちが悪さを感じるが楽
batをランチャーに起動すれば細かい単位で自動化も容易と想定
後でbatの彩を添えたい。

#謎
実行ファイルとしてエクスポートは1.1.3以前の従来仕様？
Export as jarは1.1.4以降の仕様？
両方ともパッキングしていると思われるがどちらにしても動かし方がよくわかっていないので
必要になったら調査する。
[Unity] 確率判定

RPGとかなんやらで「何％の確率で何かが起きる」みたいな時に使える関数があると便利だと思って書いておきます。

# ソース
```csharp
/// <summary>
/// 確率判定
/// </summary>
/// <param name="fPercent">確率 (0~100)</param>
/// <returns>当選結果 [true]当選</returns>
public static bool Probability(float fPercent)
{
    float fProbabilityRate = UnityEngine.Random.value * 100.0f;

    if(fPercent == 100.0f && fProbabilityRate == fPercent)
    {
        return true;
    }
    else if (fProbabilityRate < fPercent)
    {
        return true;
    }
    else
    {
        return false;
    }
}
```

# 使い方
```csharp
if(Probability(30))
{
    //30％の確率で起こるイベント
}
```

他にも方法はいろいろあると思うけど、自分はこれが使い勝手良かった。
ピーク検出の方法

先日こんなつぶやきを投稿した。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">こういうピークをうまく拾う良い方法ないかなあ <a href="https://t.co/TQe87zwTiQ">pic.twitter.com/TQe87zwTiQ</a></p>&mdash; Akinori Ito (@akinori_ito) <a href="https://twitter.com/akinori_ito/status/1095669565063815169?ref_src=twsrc%5Etfw">2019年2月13日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

よく考えたら去年自分で書いてたわ。以下解説。

例えばこんなデータがあり、ピーク位置を検出したい。
![Rplot1.png](https://qiita-image-store.s3.amazonaws.com/0/219428/50491aa2-24ea-25c2-8a33-b8e600ec70d4.png)

ある点がピークだということは、ピークが極大の場合、その点の前後の点はピーク点の値より小さい（極小の場合はその逆）のはず。そこで、データx[1..n]に対して、d[i]=x[i]-x[i-1]を計算する。
![Rplot2.png](https://qiita-image-store.s3.amazonaws.com/0/219428/a577e12d-a69e-fd16-5670-78525d02dcba.png)
このグラフで値が0になっている点がピークのはずだ。

次にq[i]=d[i]*d[i-1]を計算する。こんな感じになる。
![Rplot3.png](https://qiita-image-store.s3.amazonaws.com/0/219428/dbe4dd53-d6ae-635f-d822-cb9ae3138d87.png)
値が負になっている点は、隣り合う2点の符号が異なっている点なので、この点の前後でdが０交差していることがわかる。そこで、値が負の点だけを拾ってくれば、それがピークになっている。

実際にはどんなピークを拾ってもよいわけではないので、ピークの値にしきい値を設けたり、大きいピークから順番に拾って、その周囲の一定範囲にあるピークは拾わないなどの細かい処理を行う。

コードはこんな感じ。

```R
detect.peaks <- function(res,thres,pwidth,type="min") {
  len <- length(res)
  if (type == "min") {
    res[res>thres] <- thres
  } else {
    res[res<thres] <- thres
  }
  dif <- res[2:len]-res[1:len-1]
  ddif <- dif[2:(len-1)]*dif[1:(len-2)]
  ppos <- c()
  while (TRUE) {
    p <- which.min(ddif)
    if (ddif[p] == 0) break
    if (length(ppos)>0) {
      q <- abs(ppos-p)
      if (min(q) > pwidth) {
        ppos <- c(ppos,p)
      }
    } else {
      ppos <- c(ppos,p)
    }
    ddif[p] <- 0
  }
  ppos+1
}

```

これで検出してみる。

```R
p <- detect.peaks(x,0.1,10,"max")
```

こんな感じになった。
![Rplot4.png](https://qiita-image-store.s3.amazonaws.com/0/219428/8f191b02-d0f6-49d9-be36-697467ab23ec.png)

# 追記

河原英紀先生からリプライをいただいた。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">自分がMATLAB でよく使っている方法。例えば、こんなデータ：<br>y = conv(hanning(50), randn(1000,1)) .^ 2;<br><br>ピークの場所を求め<br>base_id = 1:length(y);<br>peak_loc = base_id(y &gt; y([1 1:end-1]) &amp; y &gt; y([2:end end]));<br><br>以下で、確認<br>figure;plot(y)<br>hold all;plot(peak_loc, y(peak_loc), &#39;o&#39;) <a href="https://t.co/oKgtPJR38w">https://t.co/oKgtPJR38w</a></p>&mdash; Hideki Kawahara (@hidekikawahara) <a href="https://twitter.com/hidekikawahara/status/1096227172107206656?ref_src=twsrc%5Etfw">2019年2月15日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

ピーク点は単調増加かつ単調減少であるという性質を使った方法です。こっちの方がエレガントかも。
curlでGETするときにパラメータをいっぱい指定する

## 前提
```
❯ curl --version
curl 7.54.0 (x86_64-apple-darwin18.0) libcurl/7.54.0 LibreSSL/2.6.4 zlib/1.2.11 nghttp2/1.24.1
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp
Features: AsynchDNS IPv6 Largefile GSS-API Kerberos SPNEGO NTLM NTLM_WB SSL libz HTTP2 UnixSockets HTTPS-proxy
```

## 前置き
Web APIのテストなんかで `curl` コマンドをよく使うと思いますが，ページネーションなどが絡むと `?page=3&num=10` みたいにたくさんのパラメータを渡す必要がある場合があり，わりと面倒です．

```shell-session
curl 'example.com/contents?page=3&num=10'
```

まぁこれでも良いのですが， `''` で囲むのを忘れるとシェルがエラー出したりします．

```shell_session
❯ curl example.com/contents?page=3&num=10
[1] 9757
zsh: no matches found: example.com/contents?page=3
[1]  + exit 1     curl example.com/contents?page=3
```

## 楽な指定方法
```shell-session
❯ curl -v -G -d page=3 -d num=10 example.com/contents
*   Trying 93.184.216.34...
* TCP_NODELAY set
* Connected to example.com (93.184.216.34) port 80 (#0)
> GET /contents?page=3&num=10 HTTP/1.1
> Host: example.com
> User-Agent: curl/7.54.0
> Accept: */*
```

`-G` を付けるのがポイントです．通常 `-d` でbodyを指定すると`POST`になってしまうのですが，`-G`を付けることにより強制的に`GET`にします．
そしてその場合`-d`で指定したデータは`?foo=bar`の形式で良い感じに付けてくれるようになります．


## 結論

- 自分でシェルの特殊文字をエスケープする必要がなくなる
- パラメータの順序を入れかえたりしても`?`と`&`を書き換えたりする必要がなくなる
- 複数のパラメータを独立して指定できるのでスクリプトが書き易くなる

などの効果が得られます．たぶん．
Surface Pro 6でMicrosoft StoreからWindows 10 Proを買うとActivation Errorが起きる (0xC004F213)

USBメモリの回復ディスクの作成から出荷時の状態への初期化で直るらしい。

https://answers.microsoft.com/ja-jp/windows/forum/all/%E3%82%A2%E3%83%83%E3%83%97%E3%82%B0%E3%83%AC/698f6847-8f0a-4633-b2b2-18f965527b30?auth=1

去年の11月から直ってないらしい。。
https://answers.microsoft.com/en-us/windows/forum/all/surface-pro-6-asking-for-product-key-on-windows-10/30871a89-c376-4922-ab7d-372c34ce09a2
Google App Engine(GAE) スタンダード環境でSequelizeを使ってCloud SQL for MySQLへつなぐ

Cloud SQL for MySQLへの接続にはまった為、メモとして残したいと思います。

#前提条件
- Node.js v10.x
- Sequelize v4.42.0
- Cloud SQL for MySQL v5.7
- GAEとCloud SQL for MySQLは同じプロジェクトであること(パブリックIPが設定済みであること)

#Sequelizeの設定例
```javascript

const sequelize = new Sequelize('database', 'username', 'password', {
  dialect: 'mysql',
  host: 'localhost',
  dialectOptions: {
    socketPath: `/cloudsql/${process.env.INSTANCE_CONNECTION_NAME}`,
  },
})
```
GAEからCloud SQLに接続する際は基本的にCloud SQL Proxyを使用して接続するみたいです。。
その為、デフォルトのTCPソケット接続ではなくUNIXソケット接続に切り替えます。
重要なのはhostとdialectOptions内のsocketPathです。
hostはデフォルトがlocalhostなので未設定でもいいです。
dialectOptions内のsocketPathには「/cloudsql/」という文字列の後に
Cloud SQLのインスタンス接続名を入れます。
インスタンス接続名はCloud SQLの [概要] ページのプロパティに記載されています。
gcloud cli でaccount 切り替えとproject の切り替え方法


ただの備忘録ですが、以下のコマンドでaccount, projectの切り替えが可能です。

```
# account の切り替え
gcloud auth list
gcloud config set account your_account@example.com

# project の切り替え
gcloud projects list
gcloud config set project your_project_12345
```
API Gatewayに別アカウントで所有しているドメインを使ってカスタムドメイン名を設定する

# Steps
1. 別アカウントで所有しているドメインを利用した証明書の取得
2. 証明書をセットしたカスタムドメイン名の作成
3. カスタムドメイン名をRoute53のレコードに設定

# 1. 別アカウントで所有しているドメインを利用した証明書の取得
証明書の発行自体はACMからすぐにできましたが、ドメインを持っていること自体の証明が必要でした。  
DNS証明という方法があって、これから証明書を取得するドメイン名のサブドメインに対して、自分が指定したドメイン名（=証明書を申請した側のAWSアカウントで作成された、`******.acm-validations.aws/`のようなアドレス）　の組み合わせを作成し、それをドメインを所有している側のアカウントでレコードに登録することで証明しています。  

![](https://i.imgur.com/VCKkX3y.png)


参考:
 - [AWS Certificate Manager で証明書の準備をする](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-custom-domains-prerequisites.html)
 - [DNS を使用したドメインの所有権の検証](
https://docs.aws.amazon.com/ja_jp/acm/latest/userguide/gs-acm-validate-dns.html)

# 2. 証明書をセットしたカスタムドメイン名の作成
API Gatewayの　Custom Domain Nameから、こんな感じでドメイン名を設定します。  
![](https://i.imgur.com/7TtNTXu.png)


なお、ドメイン名に関する用語が紛らわしいので整理すると...  
"デフォルトのベースURL": `https://api-id.execute-api.region.amazonaws.com/stage`  
"リージョンのドメイン名"(またはターゲットドメイン名）: `https://api-id.execute-api.region.amazonaws.com`
"カスタムドメイン名": `https://api.example.com/myservice`  

ガイドにも書いてありますが、リージョンAPIのカスタムドメイン名を作成する場合にAPI Gatewayから返ってくるのは"リージョンのドメイン名"なんですね。これをDNSレコードに設定することで、カスタムドメイン名を使うための手続きが完了します。  

参考: [API Gateway で API のカスタムドメイン名を設定する](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/how-to-custom-domains.html)


# 3. カスタムドメイン名をRoute53のレコードに設定
ドキュメント [API Gateway でリージョン別 API 用のカスタムドメイン名をセットアップする](https://docs.aws.amazon.com/ja_jp/apigateway/latest/developerguide/apigateway-regional-api-custom-domain-create.html)ではCLIのコマンドが示されている箇所です。  
![](https://i.imgur.com/3EXk1ln.png)

Aliasとして設定します。

# その他
* 疎通確認の際、 `http` でアクセスしないように気をつけてください。Chromeでドメインだけ（`test.example.com`）打ち込むと`http` として解釈されます。
FreeBSDのportsのspamassassinの日本語化

FreeBSDのportsには、オリジナルのmail/spamassassinと、日本語patchがあたったjapanese/spamassassinがありました。
しかし、japansese/spamassassinは2018-12-31で削除されてしまったようです。([FreshPorts](https://www.freshports.org/japanese/spamassassin/))
昨日の迷惑メール報告の記事を書いた後で、sa-learn が失敗していることで気がつきました。

patchの開発状況を確認すると、もともとspamassassin-3.4.0と3.4.1用のパッチがあったようですが、3.4.2には同じパッチが当たらなかったようで、その辺もportsが削除された原因かも知れません。
参考: [SpamAssassinの日本語対応状況 - インフラエンジニアway - Powered by HEARTBEATS](https://heartbeats.jp/hbblog/2018/10/spamassassin.html)

日本語パッチがあたっていないと、日本語のベイズフィルタの学習がうまくできないのと、そもそも tokenizer.preで指定したプラグインのロードに失敗します。

本来であれば、新しい japansese/spamassassin portsを作成すべきなのでしょうが、メンテナになるほどの根性もないので、既存の mail/spamassassin の portsをちょこっといじってお茶を濁すことにします。

まずは、Makefileに以下を追加します。

```Makefile:/usr/ports/mail/spamassassin/Makefile
PATCHFILES=spamassassin-3.4.2-japanese-tokenizer.patch
PATCH_SITES=https://raw.githubusercontent.com/heartbeatsjp/spamassassin_ja/maste
r/patches/
PATCH_DIST_STRIP=-p1
```
githubのファイルにリンクを貼る方法がわからなかったのでPATCH_SITESを上記のようにしたのですが、正しいやり方ってあるんですかね？

これだけだと、makeしても以下のエラーで止まってしまいます。

```shell-session
# make
===>  License APACHE20 accepted by the user
===>   spamassassin-3.4.2_3 depends on file: /usr/local/sbin/pkg - found
=> spamassassin-3.4.2-japanese-tokenizer.patch is not in /usr/ports/mail/spamassassin/distinfo.
=> Either /usr/ports/mail/spamassassin/distinfo is out of date, or
=> spamassassin-3.4.2-japanese-tokenizer.patch is spelled incorrectly.
*** Error code 1
```

そこで、実際にこのファイルを fetch コマンドで持ってきて、ls と sha256 コマンドでファイルのサイズと sha256 を求め、distinfoに追加します。

```text:/usr/ports/mail/spamassassin/distinfo
SHA256 (spamassassin-3.4.2-japanese-tokenizer.patch) = 4179a177e8b03afff0738ba482e43cb8bda5266d9e04f3d7fe6741b054f305a5
SIZE (spamassassin-3.4.2-japanese-tokenizer.patch) = 20109
```

これだけだと、stageから実際の場所に追加のファイルがインストールされないので、pkg-plistにも追加します。

```text:/usr/ports/mail/spamassassin/pkg-plist
%%SITE_PERL%%/Mail/SpamAssassin/Plugin/Tokenizer.pm
%%SITE_PERL%%/Mail/SpamAssassin/Plugin/Tokenizer/MeCab.pm
%%SITE_PERL%%/Mail/SpamAssassin/Plugin/Tokenizer/SimpleJA.pm
```

後は、再インストールすればOK

```shell-session
# service sa-spamd stop
# make
# make deinstall
# make reinstall
# service sa-spamd start
```

spamassassinはもう流行らないんですかねえ。何か代わりのものがあるのかなあ。
Facebook・Twitter・LINE・Pocket・はてブの公式シェアボタンリンクまとめ

FacebookやTwitterなど
各シェアボタンを埋め込むコードをいつもググっているのでメモしておきます📝

##Facebook

いいね！ボタン - ソーシャルプラグイン
https://developers.facebook.com/docs/plugins/like-button?locale=ja_JP

##Twitter

Twitter Publish
https://publish.twitter.com/?buttonType=TweetButton&widget=Button

##LINE

LINE Social Plugins
https://media.line.me/ja/how_to_install#lineitbutton

##pocket

Pocket for Publishers: Pocket Button
https://getpocket.com/publisher/button

##はてブ

はてなブックマークボタンの作成・設置について
http://b.hatena.ne.jp/guide/bbutton

#スニペット

シェアボタンのHTMLコードスニペットです。
HTMLコードはスニペットを使い回して時短してます🕑

```
<div class="p-sns">
  <ul class="p-sns__list">
    <li class="p-sns__item -facebook">
      Facebookボタン
    </li>
    <li class="p-sns__item -line">
      LINEボタン
    </li>
    <li class="p-sns__item -twitter">
      Twitterボタン
    </li>
     <li class="p-sns__item -pocket">
      Pocketボタン
    </li>
  </ul>
</div>
```

#
SharePoint Online でアイテム登録時にダイアログを表示する(クラシック UI)

SharePoint でアイテムを登録する時、確認のためのダイアログを表示するようにします

## 環境

* サーバー環境：SharePoint Online
* 開発・検証環境：Windows Pro 10, Chrome

## 実装

1. 登録画面(または、編集画面)にて、[右上の歯車マーク] → [ページの編集] を選択する
  ![](https://1bed.allright.life/wp-content/uploads/2019/02/c1.png)

2. 外枠の内側をクリックし、[パーツ] → [Webパーツ] を選択する
  ![](https://1bed.allright.life/wp-content/uploads/2019/02/c2.png)
 
3. [メディア及びコンテンツ] → [スクリプトエディター] を選択し、[追加] ボタンを押下する
  ![](https://1bed.allright.life/wp-content/uploads/2019/02/c3.png)

4. スクリプトエディターの [スニペットを編集] を押下する
  ![](https://1bed.allright.life/wp-content/uploads/2019/02/c4.png)

5. PreSaveAction 関数を作成し、その中に window.confirm を書いて、[挿入] ボタンを押下する  
  ![](https://1bed.allright.life/wp-content/uploads/2019/02/c5.png)

```HTML
<script type="text/javascript">
function PreSaveAction ()
{
    if (window.confirm('登録してよろしいですか？')) {
        return true;
    }
    return false;
}
</script>
```
6. 左上の [編集の終了] から [編集の終了] を選択する  
  ![](https://1bed.allright.life/wp-content/uploads/2019/02/c6.png)

## 動作確認

上記で、設定は完了になり、登録画面で [保存] ボタンを押下すると、下図のような確認ダイアログが表示されるようになります  
![](https://1bed.allright.life/wp-content/uploads/2019/02/c7.png)
NCL > 折れ線図 >xyMarkLineModes, xyMarkers, xyMarkerColor, xyMarkerSizeFの使用例 

```txt:動作環境
Xeon E5-2620 v4 (8コア) x 2
32GB RAM
GeForce GT 730 1GB GDDR5
CentOS 6.9 (64bit)
NCAR Command Language Version 6.3.0
for WRF3.7.1, WPS3.7.1
  openmpi-1.8.x86_64 とその-devel
  mpich.x86_64 3.1-5.el6とその-devel
  gcc version 4.4.7 (とgfortran)
for WRF3.9, WPS3.9
  Open MPI v2.1.1
  gcc version 4.9.2 (とgfortran; devtoolset-3使用)
　NetCDF v4.4.1.1, NetCDF (Fortran API) v4.4.4
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37) 
Python 3.6.0 on virtualenv
GNU bash, version 4.1.2(2)-release (x86_64-redhat-linux-gnu)
date (GNU coreutils) 8.4 
tmux 1.6-3.el6
```

NCL(NCAR Command Language)関連。

### 概要

NCLの公式のチュートリアル[Example 1](https://www.ncl.ucar.edu/Document/Manuals/Getting_Started/Examples/gsun01n.shtml)が分かりにくい。

- シンプルなスクリプトにした
    - 88行 -> 17行
- xyMarkersは番号でなく、名前指定にした
- [Named colors](https://www.ncl.ucar.edu/Document/Graphics/named_colors.shtml)を使ってみた
- 余分なコメントを消した

### 実装

```NCL:gsun01.ncl
load "$NCARG_ROOT/lib/ncarg/nclscripts/csm/gsn_code.ncl"
begin
  datx = (/10.,20.,30.,40.,50.,60.,70.,80.,90./)
  daty = (/0., 0.7, 1., 0.7, 0., -0.7, -1., -0.7, 0./)

  wks = gsn_open_wks("x11","gsun01n")
  resources = True
  resources@xyMarkLineModes = "MarkLines"
  resources@xyMarkers       = "asterisk"
  resources@xyMarkerColor   = "deeppink2"
  resources@xyMarkerSizeF   = 0.03

  plot = gsn_xy(wks, datx, daty, resources)

  delete(plot)
  delete(resources)
end
```


![2019-02-15_08h36_39.png](https://qiita-image-store.s3.amazonaws.com/0/32870/9c42f7ac-f624-6268-a023-8daa76cb727e.png)
【iOS】アプリ画面を縦固定に制御する

プロジェクトを選択し下記項目のPortraitを選択する。
コードの記述は不要です。

General > Deployment info > Device Orientation
<img width="245" alt="スクリーンショット 2019-02-15 8.11.16.png" src="https://qiita-image-store.s3.amazonaws.com/0/194284/4c6afe07-e6a8-b076-3ce3-00505b794ee0.png">
検索式まとめ：Windows10ファイルエクスプローラー

# 検索式まとめ：Windows10ファイルエクスプローラー

+ Windows10のファイルエクスプローラーで、検索ボックスを使ったファイル検索での「検索式」をまとめます。
+ 基本的に自分がよく使う、使いたいものを載せるため、過不足あるかもしれません。
+ 今後、他に良いものを見つけたら随時更新していこうと思います。

|![explorer.png](https://qiita-image-store.s3.amazonaws.com/0/238650/df0ef03b-f96e-6605-a66e-f000d0868236.png)|
|:-:|

## 目次
[検索ボックスを使用した検索のメモ](#検索ボックスを使用した検索のメモ)
[検索式一覧](#検索式一覧)
[おまけ](#おまけ)
[エクスプローラの初期画面を「PC」にする方法](#エクスプローラの初期画面をpcにする方法)
[今いるフォルダ階層でコマンドプロンプトを開く](#今いるフォルダ階層でコマンドプロンプトを開く)
[コマンドプロンプトから管理者権限で別に窓を開く](#コマンドプロンプトから管理者権限で別に窓を開く)

<br>
## 検索ボックスを使用した検索のメモ
+ Google検索と同じ感覚でやっちゃだめ。
+ インデックス作成の有無で動作が変わる。
  + 作成済みの場所は全文検索する(中身も見る)。
  + 未作成の場所はファイル名を検索する。
  + 作成済みだと「字単位」ではなく「単語単位」で見る？らしい。
  + 単語で見ているからか、確実に在る文字を打っても認識しない時が多い
+ ファイル名だけでは無く全文検索（中身も検索）できる。
  + 上で書いているように、インデックス作成済みの場所は全文検索する。
  + Text、Excel、Word、Powerpoint等の中身も全文検索する。
  + 試してみたら、「拡張子.log、.cfg」は全文検索しなかった。
+ 検索ボックスの検索文字列をは大文字小文字は区別しない。
+ 検索式(AND, NOT等)は大文字で使う。小文字だと検索文字列として認識する。
+ 検索式の：(コロン)は、全角半角どちらでもよい。

<br>
## 検索式一覧

※2021/04/18再度検証

+ かなり認識がずれていたので修正しました。
    - 「AND」等を使ってファイル名検索（名前：）をする場合は、式の両方に「名前：」を付けないと駄目でした。付けない方はファイル内検索される。
    - 「名前：」等を付けない検索は、ファイル内・フォルダパス・ファイル名等を見る。
    - WEBで見る情報では動かないことが多い。

|検索式|検索対象|備考|
|:-----|:-----|:-----|
|A|Aをファイル内かファイル名に含む
|A __AND__ B|Aをファイル内かファイル名に含む __AND__ Bをファイル内かファイル名に含む
|名前：A __AND__ B|Aをファイル名に含む __AND__ Bをファイル内かファイル名に含む
|A __AND__ 名前：B|Aをファイル内かファイル名に含む __AND__ Bをファイル名に含む
|名前：A __AND__ 名前：B|Aをファイル名に含む __AND__ Bをファイル名に含む
|A __OR__ B|Aをファイル内かファイル名に含む __OR__ Bをファイル内かファイル名に含む
|名前：A __OR__ B|Aをファイル名に含む __OR__ Bをファイル内かファイル名に含む
|A OR 名前：B|Aをファイル内かファイル名に含む __OR__ Bをファイル名に含む
|名前：A __OR__ 名前：B|Aをファイル名に含む __OR__ Bをファイル名に含む
|__NOT__ 名前：A|Aをファイル名に含まない
|名前：A|ファイル名にAを含む
|名前：~!A|ファイル名にAが含まれない
|名前：=A|ファイル名がAと完全一致する|
|名前：~A*|ファイル名がAで始まる
|名前：~*A|ファイル名がAで終わる（拡張子含む）
|サイズ：<10mb|サイズが10MB未満のファイル|
|サイズ：>10kb|サイズが10KBを超えるファイル|
|サイズ：>=1MB|1MB以上のファイル|「<=」は以上だと思ったら「超える」になった。
|更新日時：今日|更新日時が今日のファイル|
|更新日時：=2019|更新日時が2019年のファイル|
|更新日時：>=19/01/01|更新日時が2019/01/01以降のファイル|

<br>
## おまけ
### エクスプローラの初期画面を「PC」にする方法
Windows10からエクスプローラーを開くと「クイックスタート」が開くようになりました。
個人的にはこれが使いづらいため、エクスプローラーの初期画面を「PC」にしています。

1. メニューバーの「ファイル」
2. 「フォルダーと検索のオプションの変更」
3. 「全般タブ」
4. 「エクスプローラで開く：」から開く場所を選択
5.  「PC」か「クイックスタート」が選べます。
 

### 今いるフォルダ階層でコマンドプロンプトを開く
1. エクスプローラーのアドレスバーに「cmd」と入力する。

### コマンドプロンプトから管理者権限で別に窓を開く
1. コマンドプロンプトを開いた状態で以下を入力する。

> powershell start-process cmd -verb runas

<br>
## 参考URL

2021/04/18の更新時、こちらのサイトを見たのですがとても参考になりました。
[Windowsのファイル検索のコツとその仕組み](https://ch.nicovideo.jp/iorin/blomaga/ar169613)
end
Linux/debian系NFS共有サーバー設定

RaspberryPi Model B+(raspbian release 9.6 stretch)
Ubuntu 16.04 LTS
Debian GNU/Linux 9 (stretch)
で、確認しました。

まずは 
nfs-server側に
$ sudo apt-get install nfs-kernel-server
でinstall

実行は
$ sudo systemctl nfs-kernel-server start
$ sudo /etc/init.d/nfs-kernel-server start

等で起動時にnfs-kernel-serverが実行されるようになります。

[設定]nfs-server側
sudo mkdir /srv/NFS　共有先を作成する。
sudo cp -p /etc/exports /etc/exports.org　Install時に出来たオリジナル(exports)を退避して
sudo vi /etc/exports　編集する

[exports編集箇所]
defaultではhostname1 hostname2を変更するくらいです。行頭の＃を外す(コメントアウト)。
＃/srv/home hostname1(rw,sync,no_subtree_check)
を
/srv/NFS 192.168.x.x/255.255.255.0(rw,sync,no_subtree_check)にする。

他のディレクトリも設定できます
/home/user 192.168.x.x/255.255.255.0(rw,sync,no_subtree_check)

[設定]nfs-client側
$ sudo apt-get install nfs-common
$ sudo /etc/init.d/nfs-common start

マウントするディレクトリの作成
$ sudo mkdir /mnt/NFS-client

[fstabの編集]（必要であれば）
$ sudo cp -p /etc/fstab /etc/fstab.org　オリジナルの退避
$ sudo vi /etc/fstab　fstabの編集(デリケートなので注意してください)
[fstab]
NFS-server /mnt/NFS-client nfs rw,nosuid,_netdev,noauto,hard,intr 0 0
共有先　マウント場所　fstype option(手動でマウント) 起動時dumpの有無 起動時mountしない
ここで色々とoptionが設定できます。

[コマンド/nfs-client側]
$ sudo mount -t nfs (hostのIPaddress)192.168.x.x:/srv/NFS /mnt/NFS-client

で/mnt/NFS-clientにマウントされるので
$ cd /mnt/NFS-client
で、nfs-serverの共有ディレクトリに移動できます。

$ sudo umount /mnt/NFS-client
で、アンマウントします。
Reactで画像がリンク切れの時に代替画像を表示したい時のサンプル 

`imgタグ`の`onError`に以下を記述すればＯＫ


```js
onError={(e) => e.target.src = 'image path'}
```

以下、実装するときのイメージサンプル。

```js:Sample.js
import React, {Component} from 'react';
import noimage from './noimage.png';

class Sample extends Component {
    render() {
        <img className={'sample'}
            alt={'test'}
            src={'image path'}
            onError={(e) => e.target.src = noimage} />
    }
}

export default Sample
```

`noimage.png`は適当なものを用意して、設置で動くはず

# 参考ページ
[react.js Replace img src onerror](https://stackoverflow.com/a/48222599/3339309)
UMLツール astahの便利な使い方

## はじめに
私は、図を描くのが好きです。そして、モデリングツールが好きです。そして、astahが好きです。

UMLツールは、仕事でもプライベートでもastahを使用しています。

本記事では、astahで、便利な使い方を紹介していこうと思います。

## 公式のマニュアルが最高に素晴らしい
公式マニュアルが素晴らしすぎるので、公式マニュアルを見るのが一番いいと思います。

* 公式マニュアル
  - [http://astah.change-vision.com/ja/manual.html]

## オブジェクト図が書きたい
オブジェクト図は、ツールパレットにあるインスタンス仕様・リンク等の図要素を使って描いてください。

以下のオブジェクト図は、赤枠内のインスタンス仕様とリンクで作成。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293729/9f3792b0-511d-9f9d-a089-eba74f1aa62a.png)

詳細は以下にリンク参照。

* オブジェクト図、パッケージ図、ロバストネス図は描画できますか？
  - [http://astah.change-vision.com/ja/faq/faq-astah/object-diagram.html]

## 関連名の矢印の向きを切り替えたい
クラス図の関連名の矢印を逆にしたいときがあると思います。

以下のようなパターンです。 (「違うそうじゃない。」と歌いたくなる・・・)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293729/19abe018-1c5f-dfa0-4565-b6131ffd6f1d.png)

関連名の方向から、矢印の向きを切り替えることが可能です。

![関連名の矢印を逆にしたい.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/293729/1b508f2d-38ce-c6cc-9706-c7f034ca717a.gif)

## 関連を自分自身に引く
関連を自分自身に簡単に引きたい場合があると思います。

あるクラスから線を引き始めて、再び引き始めたクラスをクリックすると、関連を自分自身に引くことができます。

![関連を自分自身で引く.gif](https://qiita-image-store.s3.amazonaws.com/0/293729/4d7253a6-09d0-95dc-6ea5-998c69b8365e.gif)

## ノートから図へのアンカー
クラス図に、説明文書を載せたい場合は重宝します。
アンカーはクラス・クラスのパラメーターやクラスのメソッドに引くことができます。

![ノートから図へのアンカーの説明.gif](https://qiita-image-store.s3.amazonaws.com/0/293729/92720329-9a64-0288-f916-947c42f147ea.gif)!

## あとがき
便利な使い方を本記事に追加していく予定です。
Python　辞書を多次元リストにして並び替える

#この記事について
わたしは今、<a href="https://px.a8.net/svt/ejp?a8mat=2TY11N+1E0HWQ+3L4M+5ZU2A" target="_blank" rel="nofollow">Udemy</a><img border="0" width="1" height="1" src="https://www19.a8.net/0.gif?a8mat=2TY11N+1E0HWQ+3L4M+5ZU2A" alt="">などでPythonを学習しています。しかしどんどん忘れてしまうので、備忘録としてQiitaに記事として残します。

#辞書をリストにする
##辞書とは
Pythonにおける辞書（ディクショナリ）とは、大量のデータを効率的に扱う仕組みです。
ただし、リストと異なり数値であるインデックスを持ちません。その代わりに、Keyをもって、そのKeyごとにValueをもつ、という構造になっています。

例えば次のような感じです。

```Python
dict = {
    '東京': 600,
    '大阪': 800,
    '福岡': 700
}
```

東京、大阪、福岡がKeyで、600, 800, 700がそれぞれのKeyのValueです。
Keyで識別していますからKeyは重複不可ですので注意してください。

辞書の値を取り出すときは、

```Python
dict['東京']
```

のようにします。

##では実際のコードを

```Python
def sell(place, sales):
    print(place, 'で', sales, '販売されました')

dict = {
    '東京': 600,
    '大阪': 800,
    '福岡': 700
}

items = list(dict.items())
sorted_items = sorted(items, key=lambda x: x[1], reverse=True)

print('元の順序', items)
print('大きい順', sorted_items)

l = len(items)-1
i = 0

while i <= l:
    sell(sorted_items[i][0], sorted_items[i][1])
    i += 1
```


##いくばくかの解説

```Python
items = list(dict.items())
```
↑リスト型に変換します。
辞書はそのままだとソートできないので、ここで辞書型にしています。

```Python
print(type(items))
```
↑とすると、itemsがリスト型であることを確認できます。

```Python
list()
```

↑は組み込み関数で、カッコ内で与えられたものをリストに変換します。

```Python
sorted_items = sorted(items, key=lambda x: x[1], reverse=True)
```

↑並び替えています。reverse=Trueは、降順の場合です。何もなければ昇順です。
lambdaは、おいおい開設する機会を作ります。
ちょっと難しいのでここでは省略。すいません。


#最後に
あくまでも個人的なメモですので、ご参考程度にお願いします。
【UiPath】RPAツール作ってみる。～自動家計簿～


こんにちは。

これから仕事でRPAツールを使うことになったので、
RPA理解のため実際に作りたいものを作ってみました。
備忘録も兼ねてまとめてみました。

ツールはUiPathを使用しています。

### 今回作りたいもの
今回は、「前月の入出金明細を取得しExcelにコピーする」という簡易的なツールを作ってみようと思います。
・インターネットバンキングの会員サイトにログイン
・入出金明細をコピー
・コピーしたものをCSVファイルに出力


###　必要なもの
・Windows環境
・UiPathStudio


### 実装

１．テキストファイルからログイン情報を取得する。
　～準備～
　　　「ID」、「パスワード」を、テキストファイル（csv形式）に記載しておく。
　　　（ソースにベタ書きでも良かったのですが、修正しやすいようにファイルに記載しました。）

　・テキストファイルを読み込み、変数loginInfo（型：String）に設定。
　　　アクティビティ：ReadTextFile

　・取得した文字列をSplitメソッドを使って分解し、変数userInfo（型：String[] ）に設定.。
　（カンマ区切りで分解したい場合、Split(","c) と記載すれば可能です。）
　　　アクティビティ：Assign

　　userInfoには以下のように設定される。
　　　userInfo(0)　：　ID
　　　userInfo(1)　：　パスワード
![キャプチャ.JPG](https://qiita-image-store.s3.amazonaws.com/0/303730/a882d88e-4acd-2a92-15fb-e0bbaf1c81b7.jpeg)

２．インターネットバンキングの会員サイトにアクセスし、ログイン情報を入力する。
三菱UFJダイレクト：
https://entry11.bk.mufg.jp/ibg/dfw/APLIN/loginib/login?_TRANID=AA000_001

　・サイトにアクセス
　　　アクティビティ：OpenBrowser


　・「ID（ご契約番号）」、「パスワード」を入力
　　　アクティビティ：Click
　　　アクティビティ：TypeInto

　　　ご契約番号　⇐　userInfo(0)
　　　パスワード　⇐　userInfo(1)

　・ログインボタンを押す
　　　アクティビティ：Click
![ユーザーID.JPG](https://qiita-image-store.s3.amazonaws.com/0/303730/3adfa8d6-7393-6ea0-3fe8-801dc8d18ad2.jpeg)
![パスワード入力.JPG](https://qiita-image-store.s3.amazonaws.com/0/303730/db990e1e-dad4-e71b-2b77-2284517e8daa.jpeg)

３．入出力明細を取得し、CSVファイルに出力
　・入出力明細を取得する。
　　　アクティビティ：BrowserScope
　　　アクティビティ：ExtractData

　・CSVファイルに書き出す
　　　アクティビティ：WriteCsvFile
![入出力明細.JPG](https://qiita-image-store.s3.amazonaws.com/0/303730/46b27105-6658-da2d-a0fd-22eadeaa5502.jpeg)


上記の処理を実行すると、
結果、以下のようなCSVファイルが作られます。
![CSV.JPG](https://qiita-image-store.s3.amazonaws.com/0/303730/8e54323d-b8c6-59b2-119f-fc805fa929e9.jpeg)


以上です。
[WordPress]公開側からメディアを追加する

公開側で画像をアップロードして任意の投稿のアイキャッチに設定したい場合などに。

```php
function insert_attachment($media, $post_id, $old_id, $title, $caption) {
	require_once(ABSPATH.'wp-admin/includes/image.php');
	require_once(ABSPATH.'wp-admin/includes/file.php');
	require_once(ABSPATH.'wp-admin/includes/media.php');
	$wp_upload_dir = wp_upload_dir();
	$post_data = [
			'post_title' => $title,
			'post_content' => $caption,
			'guid' => $wp_upload_dir['url'].'/'.basename($media)
	];
	if ( $post_id && $thumbnail_id = media_handle_upload($media, $post_id, $post_data) ) {
		if ( $old_id ) {//旧アイキャッチを削除
			wp_delete_attachment($old_id, true);
		}
		//アイキャッチ設定
		set_post_thumbnail($post_id, $thumbnail_id);
		return true;
	}
	return false;
}

$media = 'file';
insert_attachment($media, $post_id, $old_id, $title, $caption);
```

$mediaはtype='file'のname

```html
<form method="post" enctype="multipart/form-data">
	<input type="file" name="file">
</form>
```
CentOS7でVirtualHostをSSL化する(Apache2.4)

# 概要
筆者はよく忘れがちなので備忘録として書き残すことにしました
今回も初めて書く方に向けて書いていきたいと思います
以前に取得した[ワイルドカード証明書](https://qiita.com/NaaO/items/c51b3ab33e3435f6935f)を使用していきます


# 検証環境
- CentOS Linux release 7.6.1810 (Core) 
- Apache/2.4.6 (CentOS)

# DNSの設定
まず初めに[お名前ドットコム](https://www.onamae.com/domain/navi/dns_controll/input)のようなサイトにサブドメインの設定をする必要があります
筆者は前回同様に[お名前ドットコム](https://www.onamae.com/domain/navi/dns_controll/input)を使用しておりますのでここのサイトにグローバルIPを登録する必要があります
このサイトに飛び
![キャプチャ.PNG](https://qiita-image-store.s3.amazonaws.com/0/339993/54ac9c77-0d61-3c77-98bf-a86f2d5ff468.png)


この画像のようにホスト名の箇所に`*`VALUEの箇所に`[Global_IP]`を入力し追加、設定してください
これでDNS側の設定は終わりです


#  記述箇所
まず初めにサイトを置きたいフォルダ任意の名前で作成します
今回は`hoge`というフォルダを作成します

~~~Terminal
# mkdir /var/www/html/hoge
~~~

`/etc/httpd/conf.d/`の下のディレクトリに任意の名前でファイルを作成します
今回は`hoge.conf`にしていきます

~~~/etc/httpd/conf.d/hoge.conf
<VirtualHost *:80>
  DocumentRoot /var/www/html/hoge
  ServerName hoge.example.com
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
</VirtualHost>

<Virtualhost *:443>
  DocumentRoot /var/www/html/hoge
  ServerName hoge.example.com

  SSLEngine On
  SSLProtocol all -SSLv2

  SSLCertificateFile /etc/letsencrypt/live/example.com-0001/cert.pem
  SSLCertificateKeyFile /etc/letsencrypt/live/example.com-0001/privkey.pem
  SSLCertificateChainFile /etc/letsencrypt/live/example.com-0001/chain.pem

</VirtualHost>
~~~

保存が終わったらプロセスを再起動してください

~~~Terminal
# systemctl restart httpd
~~~

以上でSSL化されると思われます
もし、エラーが返される場合は`*.conf`の権限の設定かと思われます

![無題.png](https://qiita-image-store.s3.amazonaws.com/0/339993/0bc28a79-6c73-1242-b46a-1df7a848599b.png)

成功した場合このように表示されていると思います。

今回は終わりです
とあるエンジニアの問題意識 2019-02-14



# 意思決定の精度を上げるには。何度か読み返したが、まだ解釈しきれていない。何か奥深い知恵が隠されている気がする。僕自身が理解のレベルに達していない。新人教育の振り返りに合わせてチームにも共有する。吠えない犬の話が一番気になっている。#エンジニア <https://t.co/3OCjkeGM3V> <http://twitter.com/YumaInaura/status/1095723963420893184>

# もし今日が人生最後の日だったらと考える。でもどうして最後の仕事だったらとは考えないのか。今日失業したら毎日 #エンジニア の勉強会に行く。毎日スターバックスでプログラミングをする。誰にもとらわれず自由だ。面接のある就職活動はしない。苦しいだけだ。最悪なときの理想を描く。悪くない。 <https://t.co/pvmyDf3dJM> <http://twitter.com/YumaInaura/status/1095816875487850496>

# 自己顕示欲の高い状態の人は、特徴の1つとして、難しい言葉を使う。言葉の圧縮ではなく、単に調整がない。相手の理解度は無視する。噛み砕くことがない。噛み砕けないのだ。粉砕経験がないから。本人はうまく騙せていると思っているが、周りにはうすうす伝わる。長期的な人間関係では特に。#エンジニア <https://t.co/aKudNi7Qev> <http://twitter.com/YumaInaura/status/1095826615320293376>

# オブジェクト指向はなぜ必要か。ただひたすらに人間の脳と親和性の高いコーディングのため。僕らはプログラミングに向き合っているようであって常に自分たちの脳と向き合っている。プログラミングは人間行為だ。#エンジニア <https://t.co/T6xyxSdNvX> <http://twitter.com/YumaInaura/status/1095837971394121728>

# 心から。今日も。仕事を遊園地にしたい努力。キラキラと輝くもの。本当に実になる勉強したい。エンジニアリングの刺激的な記事を読みたい。日々の業務に流されず斧を磨きたい。何がため。エンジニアとしてな人生を存分に楽しむため。仕事時間は1日の3分の1。この果実を捨てたくない。#エンジニア <https://t.co/hJqtOUPh5T> <http://twitter.com/YumaInaura/status/1095845989527605248>

# インプット学習とアウトプット学習。

インプット学習も時には、それなりに良い。脳の中の複雑な状態が、前者が良いと告ている。そんなタイミングがある。事実自分に何が起こっているかは分からない。

ゆっくりとマインドフルネスの呼吸法を保ちながら、Qiitaのページをめくるなど。

# 世の中には面白そうな記事がたくさんある。エンジニアリングの。

だけど表紙だけに騙されて、実は面白くないことがたくさんある。本を買うときと同じだ。

さっとページをめくって、今の自分が面白がれない内容だと分かれば、一瞬でページを閉じる。引き返す素早さを上げよう。

# 最短経路でたどり着きたいエンジニア。回り道が好きなエンジニア。

どちらもとても優秀なエンジニア。僕は身近に見たことがある。

前者は生産性が高く、後者は多様性を持つ。短期戦略か長期戦略家。スパンこそ違えど、どちらにしても結果的に、大きな知恵と知識を身につける。

# ファイルパスの階層が深いと、エディタで目的のファイルを探す時に、なんとも戸惑う。

時にはディスプレイの前から逃げ出したくなることもある。見つからないコストは凶悪だ。僕はとくに弱い。

今このコストに自覚的になったが、なんとも対策しづらい部分はある。コードベースの歴史もあり。

# 未だにプライベート用のMacBookProにzshを入れていない。pecoも。エンジニアにあるまじき。

デフォルトで使えないもののコスト感の大きさ。.vimrcやら.zshrcやらをコピーしてくるだけで、死にたくなるだろう。甘んじて死にたい。

開発環境改善も、独自の生態系を作りすぎるとやばい。いつの間にか腐るし。

# 実感を説明することは難しい。僕は1日の出来事に対して自覚的でありたいが、業務中に日記でも書こうものなら、会社によっては鉄槌をくらうだろう。

頭の中が整理できる分だけ生産性が上がる気がするが証明手段がない。

とはいえ幸いにSlackでの分報は許容されている。あれは業務の一環だ。

# 注意力散漫。モンキーマインド。

ディープワークは果てしない道のりだ。Slackや自分の脳にどうしても注意力を砕かれる。随分とこの粉砕に対して敏感にはなった。ほんの薄い空気のような注意状態のスイッチング。よほど洞察力を磨かなければ、もともと鈍い自分には見づらい。

# 複雑化が嫌いだ。好きな人がいるんだろうか。

脳に優しくない。人間の脳が脆すぎる。メモリが揮発性すぎる。

人類ドメイン特化。猿的な頭のためのプログラミング。

なぜこんなに物を忘れるのか。誰も気付いていないだけだ。ワーキングメモリが少ない日はさらに苦しい。渋め。

# 心の底から自分の人生に対して自覚的でありたい。

エンジニアリングの最中の一秒一刻に対してマインドフルでありたい。その机から一瞬たりとも離れるのが嫌だ。息が吸えなくなるじゃないか。

# 昔、レビューばかりしていた頃、毎晩、レビューする悪夢を見ていた。

うなされていた。

プログラミングでも、やりすぎるとコードばかり書く夢を見るらしい。

夢の世界。

# 業務を進めるか、勉強を進めるか。業務で技術は身につくというが、環境による。

ただひたすら事務作業のようになってしまう状況だってある。

自分の知恵と工夫が必要だ。面白そうな仕事に飛びつくか、なんとか隙間を縫って技術的キャッチアップをするか。戦略もそれぞれ。

# プログラムの動作確認。よくわからないブラックボックスの部分。

現状のコードのまま動かすか、一から積み上げるか。ふりだしに戻って、一番最初からやり直したいときもある。そうでないと理解が追いつかない。

だけど折衷案もある。完成されたものを、ピュアな状態に少しずつ崩す。粉砕。

# Original by Github issue

https://github.com/YumaInaura/YumaInaura/issues/591








<!-- Update From Qiita API -->

# チャットメンバー募集


何か質問、悩み事、相談などあればLINEオープンチャットもご利用ください。

https://line.me/ti/g2/eEPltQ6Tzh3pYAZV8JXKZqc7PJ6L0rpm573dcQ





# Twitter


https://twitter.com/YumaInaura


<!-- Update From Qiita API -->
Can I use ... のGA連携で自分専用にカスタマイズ

新しいフロントエンド技術の普及率を調べる定番ツールが Can I use ... https://caniuse.com/ です。

このツールはGoogle Analyticsと連携して、もっと自分のための Can I use ... にカスタマイズすることができます。
<img width="966" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/440554c0-7e51-adfc-b023-0e3222aaa451.png">

この方法を見つけたときスゲー！と思ったのですが、5年も前に紹介されてました。

[HTML5やCSS3のブラウザサポート状況を簡単に調べられる「Can I use&#8230;」のGoogleアナリティクス連携が便利  |  Rriver](https://parashuto.com/rriver/tools/can-i-use-beta-integration-with-google-analytics)


画面も変わっているので2019年版として紹介します！

# ⚙️ Settingsから行う

テキストボックス横の`Settings`を開き、`From Google Analytics:`の`Import`ボタンを押します。
<img width="964" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/50a78b90-4c52-e76b-8cfe-51aa3512f9f2.png">
ポップアップでお決まりのGoogleログインフォームが出てくるので、Google Analyticsを利用しているアカウントでログインします。
<img width="598" alt="ログイン_-_Google_アカウント_と_Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/4bfbf050-1517-18a6-2d17-844ea7bfc587.png">
自分は最初、ポップアップブロックでポップアップが防がれてしまったので、同じ状態になった人はポップアップを許可してもう一度`Import`ボタンを押してください。

それから連携するアカウント > プロパティ > ビューを選択します。
<img width="622" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/8dae8ffc-c5d8-7183-b7bc-6add9cd1de43.png">
最後に日付を設定して`Import data`ボタンを押すと完了です。デフォルトの30日間で問題ないと思います。
<img width="445" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/a974f3ba-f5d7-69f1-30d3-31a7bfe9581f.png">
`Close`ボタンを押し、`ページを再読み込み`します。
<img width="990" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/625b6538-c0ed-b659-25fc-4e2fcecb639b.png">
反映させるには画面の再読込が必要です。すぐには反映されず、最初戸惑いました。

これで新しい技術について、全世界、日本、自分のサイトの訪問者、というそれぞれのスコープで普及率を瞬時に知ることができるようになりました。
<img width="966" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/440554c0-7e51-adfc-b023-0e3222aaa451.png">
きっと多くの人が`すべてのウェブサイトのデータ`という抽象的なビュー名のままなので、Google Analyticsの管理画面で適切に変更しておくことをお勧めします。

# 自動更新はされない

インポートしたブラウザシェアは自動更新は(たぶん)されません。自動更新するには refresh_token の保存が必要なので。

なのでときどき同じようにインポートする必要があります。

# 複数追加できる

違うビューをインポートすると、その分`Usage`のセグメントが追加されていきます。
同じビューだと上書きで更新されるようです。

# 削除はSource:メニューから

間違って追加した場合は、`Setting`フォームの`Soruce:`プルダウンから選んで削除できます。
<img width="263" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/163662f2-9ff6-5e81-1f82-f9ae01ead109.png">

# Japanが表示されないけど？

自分は以前、*「あんたのいる日本を追加するかい？」*みたいなサジェストが出てきてワンクリックで追加されました。

`From geography:`からインポートすることができます。
<img width="256" alt="Can_I_use____Support_tables_for_HTML5__CSS3__etc.png" src="https://qiita-image-store.s3.amazonaws.com/0/35178/1ec46002-8d6c-d504-c093-3225271f416d.png">

# WebPシェアチェッカー

この機能を知らず作ってしまったのがこちらです…
https://sim.lightfile.net/webp-share/
![webp-share.gif](https://qiita-image-store.s3.amazonaws.com/0/35178/e9286722-ea77-78cd-9bd6-a6e0ed32cebc.gif)

この仕組み、WebP対応以外の技術もCan I use ... と同じように表示できたら便利じゃね？と思ったらすでにあったという。
パフォチューで1週間無駄にした男が考えた最強のボトルネック特定テクニック

## 概要

3行で

- パフォチュー中毒になった
- 結果、1週間無駄にした
- 効率的にボトルネックを特定する術を得た

## パフォチューは中毒性がある

パフォチュー中毒になっていました。
思考が止まらない、便秘になる、寝られないで辛かったです。
パフォチューに中毒性があるポイントは以下の2つです

- ランダム性
- 想像と実態が異なることが多い
- お得感

### ランダム性

パフォチューの成果はランダムにやってきます。
効果があると思ってやったことが効果がなかったり、
急に良い方法を思いついて効果が出たり。

ギャンブルと同じで
このランダム性が中毒性につながります。

### 想像と実態が異なることが多い

あ、あれやったら良いわ。
やっとパフォチュー終わったわ -> 喜びでドーパミン出る

試す
逆に遅くなる 
いつになったらパフォチュー終わるのか
もう一週間なんの成果も出てないわ-> 焦りでドーパミン出る

想像と実態で二度おいしいわけです。
これもギャンブルと似ています。

ギャンブルと似ていると思います。

### お得感

パフォチューは、
初期コスト、コードのメンテナンスコストを度外視すると、
トレードオフなしでパフォーマンスだけ上がります。

要するに「タダで」効果を得られるのでお得なわけです。
これは、「無料」という言葉に多くのヒトが魅了されるのと似ています。

こういうのをやりすぎた公告は、
景品表示法で規制されていますよね？

これも中毒性のポイントです。

## ボトルネックがわかっていない

本題に入ります。
前述のパフォチュー中毒で過ごした1週間。
数多くの手法を試しましたが、なんの成果も出ませんでした。

その理由は

「ボトルネックがわかっていなかった」

これでした。

とはいえ、一般的に言うような「推測するな計測せよ」とか、
キャッシュの仕組み、メモリ帯域、演算ユニット、hyper threadingとかは理解しているつもりでした。

でも計測方法が間違えていました。

## 良い計測ツールを使え

VTuneとかは使ったことは無いですが、有料のリッチな計測ツールを使えば良いと思います。
それらを買いたくないヒトのために無料の計測ツールをご紹介します。

### IACA - ループのスループットを予測できる

ループのスループットを予測できるツールです。使い方はぐぐると出てきます。
https://software.intel.com/en-us/articles/intel-architecture-code-analyzer

※ 様々な注意事項があるので、公式pdfドキュメントを見てください。例えば、vdiv, vsqrtのレイテンシーは保守的に見積もられます。

### SDE - 実際に実行された命令数を計測できる

実際に実行された命令数を計測できるツールです。
https://software.intel.com/en-us/articles/intel-software-development-emulator

どの演算ユニットがボトルネックになっているかを計測できます。

## このツールは使うな

使うなというほどではないですが、false positive、false negativeが発生する可能性があります。

### single threadでの実行時間計測

single threadで実行した結果を元に最適化しても、multi threadで実行するとまったく結果が変わらないということが発生しました。

おそらく、hyper threadingの効果です。以下の計測結果が出たからです。
スレッド数を論理コア数に合わせると、最適化前後で実行時間が変わらない。
スレッド数を物理コア数に合わせると、最適化前後で実行時間が変わる。

最適化した箇所はIACAで計測した結果、演算ユニットボトルネック(divとsqrt)になっていた箇所でしたが、hyper threadingで他の箇所(divやsqrtが含まれない)と同時実行された結果、演算ユニットボトルネックが隠れたのだと思います。

### 特定関数の実行時間計測

個別に計測したときに、結構大きい割合を占めている特定関数の実行時間を短縮しても、全体の実行時間が変わらないということが発生しました。

### profiler

また、profilerも役に立ちません(正確には、XCodeのInstrumentsはだめでした)。実際のボトルネック箇所ではない部分が大きく表示されていました。理由は不明。

## 最強のボトルネック特定テクニック

前述のようなツールが訳に立たない背景は、パフォーマンスはメモリ帯域、CPUの複雑な仕組み、hyper threadingなどが複雑に絡み合った関数になっているからです。

その中で戦う術を教えます。

### モデル

前述のようなツールが役にたつためには、(近似的に)以下のように、全体の実行時間を分解できる必要があります。

```
// F(x, y, z): 全体の実行時間
// f(x), g(y), h(z): 各コードブロックの実行時間
// x, y, z: コードブロック
// N: 並列数
F(x, y, z, N) = (f(x) + g(y) + h(z)) / N
```

しかし世の中こんなに甘くないです。実際は分解不可能です

```
F(x, y, z, N)
```

どう戦うか？

-> 偏微分を使え

以下を計測します。

```
δF(x, y, z, N)/δx
δF(x, y, z, N)/δy
δF(x, y, z, N)/δz
δF(x, y, z, N)/δN
```

### 実践

上記モデルの考え方を実践してみます。
具体的にはどうするのでしょうか？

-> 特定コードブロックの実行回数を2倍にします。

δF/δx, δF/δy, δF/δzを計測できます。

実行を省略できる場合は省略(実行回数を0回にする)でも良いです。
コードブロックがout-of-placeアルゴリズムであれば、2倍にするのが簡単だと思います。
どちらもできない場合は以下のようなテクニックでシミュレーションします。

・メモリ書き込み時に書き込み量を2倍にしてみる
・メモリ読み込み時に読み込み量を2倍にしてみる。
・各演算ユニット(AVX add/mul, div, 普通の命令)に相当する無駄な計算を入れてみる。

そして、もっとも大きいδF/δxを最適化します。
また、最適化効果も見積もれます。
50%最適化したとしたら、全体の実行時間短縮量は、0.5 * δF/δxです。
これを見て割に合わないなら(スペック増強コストより高いなら)、やめたほうが良いです。
-> やめられないのがパフォチューですが

また、Nを変えてみます。
これはみんなやると思うので省略。

## まとめ

いかがだっただろうか？