OmniAICreator/Qiita-1.07M huggingface dataset:
Pipenvのpyenvサポート(自動バージョンインストール)が動かないとき

ハマったのでメモ。20191209時点のお話。

# tl;dr
こんな感じになってしまったら、

```shell
$ pipenv sync
Warning: Python 3.7 was not found on your system…
Would you like us to install CPython 3.7.5 with pyenv? [Y/n]: Y
Installing CPython 3.7.5 with pyenv (this may take a few minutes)…
✔ Success!

Warning: The Python you just installed is not available on your PATH, apparently.
```

これでOK :ok_hand: 

```shell
pip install --user pipenv==v2018.7.1
pip install pip==18.0
```


# Pipenvのpyenv support
Pipenvには、[pyenvがインストールされていればPipfileに記載されているバージョンを勝手にインストールしてくれる機能](https://pipenv.kennethreitz.org/en/latest/advanced/#automatic-python-installation)がある。

が、現時点での[latest(v2018.11.26)](https://github.com/pypa/pipenv/releases/tag/v2018.11.26)では壊れているらしい、、、
issue: [Pyenv support broken #3551](https://github.com/pypa/pipenv/issues/3551)

やってみるとこんな感じで、Successと出るがちゃんと動かない。

```shell
$ pipenv sync
Warning: Python 3.7 was not found on your system…
Would you like us to install CPython 3.7.5 with pyenv? [Y/n]: Y
Installing CPython 3.7.5 with pyenv (this may take a few minutes)…
✔ Success!

Warning: The Python you just installed is not available on your PATH, apparently.
```


# Pipenvのバージョンを下げる
issueのコメントには「masterブランチ使えば動く」とか「バージョンを下げれば動く」というコメントがあるので、バージョンを下げてみた。

```shell
$ pip install --user pipenv==v2018.7.1
...
Successfully installed pipenv-2018.7.1
```

今度はPipenv自体が動かなくなった。

```shell
$ pipenv sync
...
TypeError: 'module' object is not callable
```


# pipのバージョンも下げる
Pipenvをダウングレードしたので、対応するpipのバージョンも下げないといけないぽい。
issue: [pip 18.1 causes "TypeError: 'module' object is not callable" #2924](https://github.com/pypa/pipenv/issues/2924)

```shell
$ pip install pip==18.0
...
Successfully installed pip-18.0
```

これでうまくいった :thumbsup: 

```shell
$ pipenv sync
...
All dependencies are now up-to-date!
```

# ただしlockが壊れる
issue: [Running pipenv gives TypeError: 'module' object is not callable #2871](https://github.com/pypa/pipenv/issues/2871)

つらい。とりあえずバージョンを切り替えながら運用している。つらい。

```shell
$ pip install --user pipenv==v2018.11.26
```


# 蛇足
Pipenvのリリースがずっと止まってる件については[こちらのissue](https://github.com/pypa/pipenv/issues/3742)で議論されているようです。頑張れ〜〜 :muscle:
Azure Virtual WANとAzure Firewall Managerを理解する

本記事は以下サイトにて記載しています。
恐れ入りますがリンクから移動してご参照ください。

**Azure Virtual WANとAzure Firewall Managerを理解する**
https://cloudsteady.jp/post/10089/
　
　
現在パーソルプロセス＆テクノロジーではAdvent Calendar 2019を開催中です。
https://qiita.com/advent-calendar/2019/ppt

こちらも興味ある記事あれば是非ご参照ください。
Microsoft Learn 10日目

12月は、毎日 [Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/) を受講していこうという記録。
※受講後に書き込むので公開に間に合わないこと多々あります(アドベントカレンダーの意味ｗ)

12/10 は
**Core Cloud Services - Azure アーキテクチャとサービスの保証**
 - Azure のアプリの信頼性を向上させる
**Azure アカウントを作成する**
 - はじめに(メモ略)
 - Azure カウントと Azure サブスクリプション

を受講。以下、簡易メモ。

# Core Cloud Services - Azure アーキテクチャとサービスの保証
## Azure のアプリの信頼性を向上させる
独自の SLA を作成すると、特定の Azure アプリケーションに合わせてパフォーマンスの目標を設定できる。
それを、アプリケーション SLA と呼ぶ。

### アプリの要件を理解する
効率的で信頼性の高い Azure ソリューションを構築するには、ワークロード要件を知ることが必須。
また、サービス全体またはリージョン全体で中断が発生したときを考えて計画しておくことも必要になる。

### 回復性
障害から回復して動作を続行する、システムの能力のこと。
障害を回避することではなく、ダウンタイムまたはデータの損失を回避するように障害に対応することが必要となる。
回復性の目的は、障害後にアプリケーションを完全に機能している状態に戻すことであり、高可用性とディザスターリカバリーは、回復性の2つの重要な構成要素である。(業務でよく聞く内容！！！)

### コストおよび複雑さと高可用性
"可用性"＝システムが動作し実際に使用可能である時間。
可用性を最大化するには、潜在的なサービス障害を防止する手段を実装する必要がある。
ソリューションが複雑になるにつれて、相互依存するサービスが増え、ソリューション内の潜在的な障害点を見過ごしやすくなる。この課題に対して、高可用性が要件に対してどの程度クリティカルであるかによって、アプリケーションの SLA に追加される複雑さとコストを処理するかを考慮する。

# Azure アカウントを作成する
ここのセクションは日本語未対応のユニットが多かった。 Google 翻訳で強制的に日本語翻訳して乗り切る。

## Azure カウントと Azure サブスクリプション
(ぶっちゃけ、以前の [演習](https://qiita.com/d01tsumath/items/c68f29d25f85d6dceade) の前にこれやるべきじゃない？とか思ったり思わなかったり...ｗ)

### Azure アカウントとは
Azure Active Directory (Azure AD)、または Azure AD から信頼されているディレクトリにおける ID のこと。
以下の情報が含まれている。
・名前、メール、連絡先の設定
・クレジットカードなどの課金情報

### Azure サブスクリプションとは
Microsoft Azure にリソースをプロビジョニングするために使用される論理コンテナーのこと。
仮想マシンやデータベースなどの全てのリソースの詳細が保持されている。
よく使われるサブスクリプションオプションの種類は以下。
#### 無料
最初の30日間に任意のサービスで使用できる200ドルのクレジット、人気の製品への12か月間の無料アクセス、25以上の製品の無料アクセスが含まれるオプション。

#### 従量課金制
1か月間の課金期間に使用したサービスに対して請求がかかるオプション。

#### エンタープライズ契約
1つの契約でクラウドサービスやソフトウェアライセンスを柔軟に購入できるオプション。
エンタープライズ規模の組織が対象。

#### 学生
最初の12か月間に使用できる100ドルのクレジット、サインアップ時にクレカが不要な無料サービスが含まれている。
(恐らく学校の)自分のメールアドレスを使って、在学状況を証明する必要がある。
投資のすゝめ from beginner to beginner

投資について、もっと身近に気楽に感じてもらおうと思い、この記事を書く。
と言っても、あの商品がいいとか、この銘柄が上がるなんて
書くことは出来ないので、投資の利点と主な商品について書いていく。

# 投資の利点
* お金が増える！
 - 投資をする最大の理由だと思う。当然減る可能性もあるけども。
* リスク分散
 - もし銀行が破綻したら、預けているお金が全額返ってこない可能性あり。
 - 物価が上昇しても(インフレ)銀行に預けているお金は変わらない。つまり価値としては下がってしまう。
* 経済に敏感に
 - 取引をしていると、なぜ上がったのか、下がったのか気になって経済に関心を持つようになる!?<br>
   まあ、これは人それぞれ。

# 株とは
会社がお金を集めるために発行したもの。株取引はそれを売買すること。

## どうやって株で稼ぐのか
 - キャピタルゲイン - 株の売却で得られる利益<br>
   つまり、安い値段で買って高い値段で売る。言うのは簡単。
 - インカムゲイン - 株の配当金や優待で得られる利益<br>
   会社によって異なるが、持っている株数に応じて配当金が出たり、優待がもらえたりする。<br>
   これだけで生活できる人生に憧れる。

## どうやって株を選ぶのか
 - ファンダメンタル分析 - 会社の業績等を見て株を選ぶこと。 <br>
   会社の決算情報や四季報などを利用する。
 - テクニカル分析 - チャートの値動きを見て株を選ぶこと。 <br>
   ゴールデンクロスやデッドクロスなど色々な分析手法がある。

この株を探す作業が一番大変だと思う。
難しく考えず、自分の応援する会社の株を買うのも一つの手かと。


# 投資信託とは
資産運用の専門家が株や債券などに投資・運用する商品。
投資金額に応じて分配される仕組み。

## 投資信託の利点
1. 少額から買うことができる。なので、お金が無くても買える。
2. 専門家が運用してくれる。なので、難しい銘柄選びの必要がない。
3. 既にリスク分散されている商品が多いため、極端な値下がりが起きづらい。
4. 個人投資家では買いづらい国などの商品に投資できる。

## おすすめの買い方
投資信託は[ドル・コスト平均法](https://kabukiso.com/idiom/dollcost.html)と相性がいい。
また、各証券会社で投資信託の定期買付サービスを行なっている。
カテゴリ(株式や債券など)や投資地域を分散させて定期買付で積立することで、
損失が発生する可能性を減らしつつ資産形成ができる。
ちなみに、筆者はそうしている。

# 債券とは
国や地方公共団体や会社がお金を借りるために発行されるもの。
購入額に応じて金利がもらえる。
償還日が決まっていて、満期償還日には(原則)額面金額が戻ってくる。

## 債券の利点
1. 安全性の高い商品。一般的に金利が低いほど安全。
2. 金利が決まっているので、安定した利益を得られる。
3. 銀行に預けるよりも金利が高い。

## 債券を買うメリットとデメリット
債券では安定した金利を得ることができるため、
購入金額が多いほど、金利で得られる額も増える。
そのため、大口投資家が購入することが多い。
個人投資家で購入金額が少ないと、その分の利益は少なく、
また償還日まで金額も拘束されてしまうため利点は少ないかもしれない。
お金持ちの人はぜひ！

# その他
先物・オプションやFXなど、他にも商品はたくさんあるが、
[投機的](https://ja.wikipedia.org/wiki/投機)でもあるので、今回は割愛。

# 最後に
投資というとギャンブル的なイメージがあったりでいいイメージではないかもしれないが、
そんなことはないということを理解してもらえるように記事を書いた。
よりギャンブル的に取引をすることもできるが、余剰資金で投資をして欲しい。
それと最後に、**投資は自己責任で！**
実験系でもPythonで効率化したい(3)PandasでExcelみたいなことをしたい

## 動機
- [(1)](https://qiita.com/asakuraTsukazaki/items/b0f6ed8a2eb5ebc997af)を見てください

## 環境
- Windows10
- Anaconda(3.x)
- (2)でpySerialを`conda install`しました

## 目標
- わたしの環境でのマニュアル操作の自動化を例として、自動化方法を示す

## 方法
pandasというPythonで使える、Excelのような表操作に適したパッケージがあります。これとmatplotlibというグラフを簡単にきれいに描画できるパッケージを用いて「自動で取得した電圧値をグラフ化する」の例を提示します。
### 例
空間に電流が広範囲に、一方向に流れているときに、空間より小さいマトを使って電流を測定するとします。マトを電流に対して垂直に少しずつ横切らせ、ステップごとの電流を記録するとき、その「移動の制御」と「電流の測定」をpyserialから制御します。移動の制御はシグマ光機[SHOT102](https://www.global-optosigma.com/jp/software/motorize/manual_jp/SHOT-102.pdf)、電流の測定はADVANTEST社のR6441シリーズを用いています。
![2019-12-09_19.57.13.png](https://cdn.discordapp.com/attachments/575215439257403392/653550776089575466/2019-12-09_19.57.13.png)

#### Cell1
```python
import serial
import time
import pandas as pd
import matplotlib.pyplot as plt
```
`serial`はpyserialを使う、`time`はシリアル通信のインターバル時間を作る、`pandas`はdataframeを使う、`matplotlib.pyplot`はグラフの描画のために使います。

#### Cell2
```python
## 定数指定 
MAX = 42000
COMpulse = "COM9"
COMampere = "COM10"
bitRate = 9600
```
`pyserial`で用いる定数を指定します。
#### Cell3
```python
## 変数初期化 
pulse = 0
ampere_list = []
pulse_list = []
ampere_average_list =[]
```
使用する変数を初期化します。

#### Cell4(省略可)
```python
## 奥原点移動(初期化)
ser = serial.Serial(COMpulse, bitRate, timeout=0.1)
ser.write(b"H:2-\r\n")
time.sleep(0.1)
print(ser.read_all())
ser.close()
```
動作確認と計測原点に移ります。

#### Cell5
`pulse`は0-42000の値を取り、1パルスあたり3μm移動します。(実際は2パルスあたり6μm動きますが、コマンドはこのように記述するようです)。各positionでの電流の値を5回サンプリングし、平均してその点での値とします。平均する回数は任意です。光学台を最後まで動かし終わったら、電流と位置の値のリストをdataframeとしてくっつけて、pulse値を実際の長さに変換し、matplotlibで描画する。という流れになっています。(ついでにdataframeをcsvに出しています。)

```python
## 測定開始
while 1:
    if pulse >= MAX:
        ## 位置がMAXまで来ている場合while文を終了
        break
    ## 現在位置の情報を記録
    pulse_list.append(pulse/2) #pulseは何故か2倍で指定して命令するので2で割っている
    ## 電流を測定する(5回とって平均したものをその位置での値とする)
    for i in range(5):
        ser = serial.Serial(COMampere,bitRate,timeout=0.1)
        time.sleep(0.5)
        ser.write(b"MD?\r\n")
        time.sleep(0.5)
        tmp = ser.read_all()
        ampere = float(tmp.split()[1])
        ampere_average_list.append(ampere)
        ser.close()
    ## 電流とpulse(位置)をlistに追加
    ampere_list.append(sum(ampere_average_list)/len(ampere_average_list))
    ampere_average_list = [] #リストを初期化
    
    ## 光学台を動かす
    pulse += 1000
    position = "A:2+P"+str(pulse)+"\r\n" # コマンドを文字列の結合で作る
    ser = serial.Serial(COMpulse,bitRate,timeout=0.1)
    ser.write(bytes(position, 'UTF-8'))
    time.sleep(0.5)
    ser.write(b"G:\r\n")
    ser.close()
    

## リストをdataframeに変える
print(ampere_list)
print(pulse_list)
df = pd.DataFrame({'ampere(A)':ampere_list,'pulse':pulse_list})
## pulse値を長さに変える
def pulseToMilliMeter(pulse):
    return pulse*0.006
df["position(mm)"] = df["pulse"].map(pulseToMilliMeter) # Excelの一括関数適用のようなことができる
df.to_csv('./csv/hoge/result.csv',index=False)
## matplotlibを用いてグラフを描画する
plt.figure()
df.plot(x='position(mm)',y='ampere(A)')
plt.savefig('./img/sample.png')
plt.close('all')
```

## おわりに
以上で効率化できたとします。実際Enterを押すだけなので、かなりシンプルになりましたし、再現性も高まります。他にも効率化できるネタができたら、続きを書きます。
実験系でもPythonで効率化したい(2)RS232CとpySerial

## 動機
- [(1)](https://qiita.com/asakuraTsukazaki/items/b0f6ed8a2eb5ebc997af)を見てください

## 環境
- Windows10
- Anaconda(3.x)

## 目標
- pySerialでRS232Cインターフェイスを持つ機器とシリアル通信する

## pySerialを入れる
### なぜ入れるか
- 多くの測定器具はRS232Cインターフェイスと、シリアル通信によるコマンド制御が用意されている
- pyserialとコマンド制御機構があれば、基本的に制御できるはず
- 詳しくは[公式サイト](https://pythonhosted.org/pyserial/)を見てください

### 入れ方
- conda promptから

```shell
conda install -c anaconda pyserial
```

### 使い方
JupyterNotebookでの実行を前提とします。(pythonスクリプトでも同様なはずです)

#### 例
まずはパッケージをimportします。**パッケージ名と違う**ので注意してください。

```python
import serial
import time
```

DSubをUSBに変換して繋ぐなりして、PCにデバイスを接続します。
Windowsの場合はデバイスマネージャーからCOM(数字)みたいなのを探してください。COM3と書かれたデバイスが該当デバイスの場合

```python
COM="COM3"
bitRate=9600
ser = serial.Serial(COM, bitRate, timeout=0.1)
```
bitRateはお好みで。
これでシリアル通信ができるので、あとは各測定器具のコマンド集を見て

```python
ser.write(b"H:2-\r\n")
```

などと入力してください(例はシグマ光機[SHOT102のコマンド](https://www.global-optosigma.com/jp/software/motorize/manual_jp/SHOT-102.pdf)で、2軸目に対して、原点に復帰する命令です。)

- `\r\n` は改行文字です。詳しくは[こちら](https://ja.stackoverflow.com/questions/12897/%E6%94%B9%E8%A1%8C%E3%81%AE-n%E3%81%A8-r-n%E3%81%AE%E9%81%95%E3%81%84%E3%81%AF%E4%BD%95%E3%81%A7%E3%81%99%E3%81%8B)を御覧ください。

- ()の中のbは文字列であることを意味しています。
bを書かない場合は、一文字しか送れません。

```python
# time.sleep(0.1)
print(ser.read_all())
```
使用するデバイスによっては、命令が実行できたかどうかが、`read()`によって返されるものがあります。

- `read()` 一文字
- `read_line()` 一行
- `read_all()` すべて

で返された文字列が読めるようです。
これまでのコードを同時に実行するときは、time.sleep(0.1)など、数秒待たないと失敗することがあるかもしれません。

```python
ser.close()
```

命令の後は、シリアル通信を終了するのを忘れないこと。

以上です。ありがとうございました。
次の記事では連続実行してリストに入れてpandasでデータフレームにしてcsvに吐くコードまで書きます。
実験系でもPythonで効率化したい(1)ChocolateyでAnacondaインストール

## 動機
- 退屈なことはPythonにやらせたい！(某書とは一切関係がございません)

## 環境
- Windows10
- Anaconda(3.x)

## 目標
- Chocolateyをインストールする
- Anacondaをインストールする

## Chocolateyを入れる
### なぜ入れるか
- Chocolateyを使えばインストール、アップデートなどがコマンド(GUIを使えばクリック)一発
- 別の環境に移行した際もconfigファイルでパッケージを一括インストールできる
- macでbrewに慣れてると欲しいよねとなる

### 入れ方
- キーボードでWindows + x → a(PowerShellが管理者権限で起動します)
- 次に示すコマンドをコピペしてEnter([公式サイト](https://chocolatey.org/install)も見てください)

```powershell
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
```

## ChocolateyGUIを入れる
### なぜ入れるか
- 移行時に使うconfigファイルが簡単に出せる

- PowerShellを毎回管理者権限で起動したい人は飛ばしていただいても大丈夫ですよ！

### 入れ方

```powershell
choco install ChocolateyGUI -y
```

- 詳しくは[こちら](https://qiita.com/kangetsu121/items/b6352b547cd32e71bc65)の記事が読みやすいです
  - configファイルの出し方も書いてあります

## Anacondaを入れる
### なぜ入れるか
- Windowsだとこれを入れておけという風潮を感じるから
- pandasやjupyterなどのパッケージもデフォルトで入っているから
- 特に深い理由はないです

## 入れ方

```powershell
choco install anaconda3 -y
```


- あるいはChocolateyGUIから左のchocolateyタブで`anaconda`と検索してください


- ダブルクリックで目的のパッケージを選び、右下のインストールボタン


以上です。ありがとうございました。

## 余談
- 今年10回以上Windowsをクリーンインストールした知見から来年はもう少し楽にしようとまとめました
- Windows10はデジタルライセンス認証されていれば、ストレージを変えたり(物理)、クリーンインストールしたりしても大丈夫なので、気軽に入れて壊れたらMedia Creation Toolなどでまっさらな環境にしてガシガシやっていきたいという思いがある
- 上記記事でも言及されているが、macのbrewほどは出来が良くないので、ちょっとインストールしまくるのがマシに慣ればいいかな程度に考えてください
- 新人にconfigファイル渡してこれ読んでインストールしといてね、ができればイイナア…


## Chocolateyおすすめパッケージ(おまけ)
- AutoHotkey
  - 変換/無変換、かなキー、capslockなどを半角全角に変えとくだけで結構ましな気がします。
  - 日本語wikiが古くてキーリストのキー名が更新されていません。(例えばvk1Csc079などはvk1Cだけで大丈夫に[変わった](https://qiita.com/chr/items/47f50e36703d3bb20371)そうです)
- Boostnote
  - Qiitaの下書きはこれを使ってます
  - Electron製なのでマルチプラットフォーム対応
  - 管理者ユーザーじゃないとインストール失敗します(´・ω・｀)
- 7zip
- Audacity
- Git
- Vagrant
- VirualBox
- VScode
- Wireshark
- DiscordとSlackはインストール何回か失敗しました
EKSクラスタのkubeconfigを設定してローカルからkubectlする

# これは何

EKSクラスタをローカルなどから`kubectl`するために`kubeconfig`を設定します。

# 環境など

* ローカル側
    * OS: Windows10
    * コマンドライン: PowerShell
    * awscli:
        * バージョン1 
        * aws-cli/1.16.297 Python/2.7.16 Windows/10 botocore/1.13.33
    * kubectl: 1.14

* EKS側
    * EKS: 1.14

# 前提

* EKSクラスタが既に作成済

# 設定する

## AWS CLIを使えるようにする

* 今回はWindowsだったので、msiでインストールするのみ
* 各OSごとの手順は[公式](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-windows.html
)を参考にする
* `aws eks`コマンドを使用するため、バージョンがそれなりに新しい必要あり
    * [これ](https://docs.aws.amazon.com/cli/latest/reference/eks/update-kubeconfig.html)を見るに、恐らく1.16くらいは必要

## `aws configure`で認証情報を設定する

* **対象のEKSクラスタと同じリージョンを設定すること**

## `kubeconfig`を設定する

```
PS C:\dev> aws eks update-kubeconfig --name クラスタ名
```

* **クラスタ名**はEKSサービスの画面から確認できるクラスタ名
    * ノードのEC2インスタンスのプレフィクスとかではない


## `kubectl`する

```
PS C:\dev> kubectl get pod -o wide
NAME          READY     STATUS    RESTARTS   AGE       IP            NODE                                       NOMINATED NODE   READINESS GATES
cassandra-0   1/1       Running   0          11m       10.0.47.113   ip-10-0-41-23.us-east-2.compute.internal   <none>           <none>
cassandra-1   1/1       Running   0          10m       10.0.32.237   ip-10-0-43-23.us-east-2.compute.internal   <none>           <none>
cassandra-2   1/1       Running   0          8m39s     10.0.50.67    ip-10-0-41-23.us-east-2.compute.internal   <none>           <none>
cassandra-3   1/1       Running   0          7m9s      10.0.50.120   ip-10-0-43-23.us-east-2.compute.internal   <none>           <none>
cassandra-4   1/1       Running   0          5m43s     10.0.52.196   ip-10-0-41-23.us-east-2.compute.internal   <none>           <none>
cassandra-5   1/1       Running   0          4m34s     10.0.50.217   ip-10-0-43-23.us-east-2.compute.internal   <none>           <none>
```

# トラブルシュート

## `kubectl`時にエラーメッセージ

```
error: You must be logged in to the server (Unauthorized)
```

## 公式を参照する

Amazon EKS トラブルシューティング
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/troubleshooting.html#unauthorized

## 原因

> これは、クラスターがAWS 認証情報のあるセット (IAM ユーザーまたはロール) から作成されたが、kubectl は別の認証情報のセットを使用していることが原因である可能性があります。

私の場合、EKSクラスタを作成したIAMユーザと、このローカルに認証情報を設定したIAMユーザは違ったため、まさにそれが原因となる。

## 対応

おおむねはこちらを参照。

クラスターのユーザーまたは IAM ロールの管理
https://docs.aws.amazon.com/ja_jp/eks/latest/userguide/add-user-role.html

```
kubectl edit -n kube-system configmap/aws-auth
```

```
# Please edit the object below. Lines beginning with a '#' will be ignored,
# and an empty file will abort the edit. If an error occurs while saving this file will be
# reopened with the relevant failures.
#
apiVersion: v1
data:
  mapRoles: |
    - rolearn: arn:aws:iam::555555555555:role/devel-worker-nodes-NodeInstanceRole-74RF4UBDUKL6
      username: system:node:{{EC2PrivateDNSName}}
      groups:
        - system:bootstrappers
        - system:nodes
  mapUsers: |
    - userarn: arn:aws:iam::555555555555:user/admin
      username: admin
      groups:
        - system:masters
```

`ConfigMap`内の`mapRoles`か`mapUsers`に`kubectl`を許可したいIAMロール or IAMユーザを追加すればよい。
Beverage Preference Dataset(関係データ) にテンソル分解かけて可視化してみた

この記事は[古川研究室 Advent_calendar](https://qiita.com/advent-calendar/2019/flab) 9日目の記事です。
本記事は古川研究室の学生が学習の一環として書いたものです。内容が曖昧であったり表現が多少異なったりする場合があります。

# はじめに
[Beverage Preference Data Set](http://www.brain.kyutech.ac.jp/~furukawa/beverage-e/) の紹介をかねて記事を描こうと思ったのですが、まだプログラムが動いていないので、随時編集していきます.

## Beverage Preference Data Set

Beverage Preference Data Set は古川研究室が公開している関係データの実データです. 細かい規約等はリンク先を参考にしてください.

604人のユーザーに 14種類の飲料水 を 11のシチュエーションごとにどう評価するのかアンケートをとったデータです.

つまり, (人) x (飲料水) x (状況) の３つの母集団の要素の組み合わせによって観測された関係データです.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154814/7db7c9b4-90a6-ab34-c968-ac875895c111.png)


### import
Beverage Preference Data Setをインポートする手順は以下になります.
download_file と zip_extractのメソッドは
[Python Tips：zip ファイルをインターネットからダウンロードして利用したい](https://www.lifewithpython.com/2015/10/python-how-to-download-extact-zip-file.html)
からお借りしました.

```python
import pandas as pd
import numpy as np

filename = download_file('http://www.brain.kyutech.ac.jp/~furukawa/beverage-e/BeveragePreferenceDataset.zip')
zip_extract(filename)
df = pd.read_table('./BeveragePreferenceDataset/Beverage604.txt', header=None, delim_whitespace=True)
df.shape
# (8456, 11)
```

このDataframeを３次のテンソルデータに変換します.

```python

X = np.zeros((604, 14, 11))
for i in range(X.shape[0]):
  Before = i * 14
  X[i] = df.iloc[Before:(14*(i+1))].values
X.shape
# (604, 14, 11)
```

# テンソル分解

## CP 分解

CP分解については
[先駆者様(pytorchでテンソル分解（CP分解）)](https://qiita.com/kazetof/items/c680ff54950e56379ade)がいらっしゃるので軽く説明してちゃっちゃと実行しちゃいます.

CP 分解は行列分解の率直な一般化で, 3次テンソル$X$ を3つのベクトルを使って 以下のように分解します.

$$X = \sum_{r=1}^R u_r \circ v_r \circ w_r$$

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154814/b599fcbb-8f15-146e-26f4-a98bdd73427e.png)

$R=1$
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154814/9260cd8e-88b0-cbdb-4e58-94d6d691323b.png)

$R=2$
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154814/aa6b9594-f61e-872f-6672-8497b83c7634.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154814/cc0f493b-81fc-da5f-fddf-1c3bfa920046.png)

U(ユーザー)は楕円状に散布してて, V(飲料水)は２種類だけ他と距離が離れて違うものがありそうです.

#　まとめ

HOSVDとかTuckerとかも試してみたいです. 時間が取れたらまた手を入れてみます.
今回は線形なテンソル分解手法を試しましたが、非線形テンソル分解に相当する *Tensor SOM* も存在します.
気になる方は是非以下のリンクでぽちぽち遊んでみてください.

[TensorSOM3Viewer(飲料水データ)ver日本語](http://www.brain.kyutech.ac.jp/~furukawa/tsom-j/)
Microsoft Ignite The Tour Tokyo - Day1

## AFUN40：Azure のセキュリティの基礎
セッション説明
https://tokyo.myignitetour.techcommunity.microsoft.com/sessions/83667?source=sessions

### 特権 ID 管理（PIM）
- 概要
  - 特権を与えられたロールへの時限的なメンバーシップ
  - 特権を昇格するときに MFA 有効化を強制　　　　　　...etc

- ロール
  - 資格のあるロール　（特権持ってるけど、有効化されていない）
  - アクティブなロール（有効化されている）

- アクティブ化（有効化）時の設定
  - 承認行為の有無
  - アクティブ化期間（制限時間設定） JIT：Just in Time


### SQL Database アクセス制御
- Advanced Data Security　　※ SQL Server 版の ATP（Advanced Thread Protection）
- Azure AD
- ファイアウォールと仮想ネットワーク
- TDE（Transparent Data Encryption）


### Azure Sentinel（SIEM）
SIEM 機能とインテリジェンスなセキュリティ分析（やれることはまだ少ない）

- Azure AD の Sign-In に関する脅威ログを表示
- Play Book：Sentinel で検知した情報を Trigger に Action 実行（Logic App ベース）



## APPS50：監視、パフォーマンス、スケーリングによってアプリを次のレベルに進める
セッション説明
https://tokyo.myignitetour.techcommunity.microsoft.com/sessions/83703?source=sessions
### まとめ
  - Application Insights を使用したアプリケーションの把握
  - Monitor を使用したトラブルシューティング・修正
  - Front Door を耐障害性の向上


### Application Insights
- 可視化可能なデータ（言語に依らず利用可能）
  - リクエスト数、応答時間、失敗率、例外
  - ページレビュー
  - パフォーマンス（CPU、メモリ、ネットワーク）
  - カスタムイベントとメトリック


### Azure Monitor
- 収集可能なデータ
  - アプリケーションログ
  - アプリケーションのメトリック
  - コンテナのメトリック

- Azure Monitor for Container
  - クラスタ内で実行中のコンテナを追跡
  - CPU / メモリ / IO / 使用率
  - アラートの設定


### Azure Front Door
- 機能
  - トラフィック負荷分散
  - コンテンツ配信ネットワーク（CDN）
  - ヘルスチェック（最短 1秒～）
FeSSをやってみた話

この記事は[うるる Advent Calendar 2019](https://adventar.org/calendars/4548) 10日目の記事です。

__※発言は個人の見解であり、所属する組織の公式見解ではありません。__

## はじめに
### 自己紹介
社会人歴は干支1周を余裕で超え、もうすぐ世に言うアラフォーになります。
10代の頃に思い描いたアラフォーとはかけ離れた精神年齢です。絶望です。でもエンジョイしてます。
これまで、エンジニアを軸に兼任としてバックオフィスから営業まで多くの職域を経験しておりまして、大切にしていることは**"チームで、楽しく、結果を出すこと"**です。
今年の３月に株式会社うるるへジョインし、組織のマネージャーと複数プロジェクトのスクラムマスターを兼任という状態におります。


### この記事に書かれていること
この記事では、中期経営計画の中核の一つとなっている、自社プロダクトのフルリニューアルプロジェクトにおいて、オリジナルのスクラムフレームワーク**FeSS**を作り、挑戦した（している）話です。

## 背景

### 開発チームの形成期

２０１９年の4月中旬から開発準備をスタートし、新しいプロダクトのコンセプト設定、現行プロダクトの技術的課題の洗い出しを始める。
当時、リニューアルプロジェクトアサインが決まっている開発メンバーは4名。
ルール・文化を形成することや、要件の明確化のため、２０１９年の５月中旬から、開発プロジェクトをスタートしました。

### 開発チームの混乱期から統一期へ

人員計画と大きな乖離もなく、プロジェクトメンバーが増え始めた状況で、それまでの開発チームの中心となっていたエンジニアの退職という大きな壁を乗り越えつつも、チームは出来上がり始めた状況でした。
また、チームの考え方や風土として、社員が決めて、業務委託と派遣は言われた通り実装するといった悶々とするような開発チームではなく、雇用形態に左右されず全員が当事者意識を持ってプロダクトに向き合うチームになれてきていました。

一方、様々なバックボーンを持つエンジニア間で、学習量や知識・経験の差など、いわゆるスキル勾配・スキル傾斜をはじめとする、チーム全体に対する課題感は見え隠れし始めていました。

### 開発チームの拡大により直面した課題
* マイルストーンに対しての漠然とした不安、焦り
* チームの拡大に伴い、意思決定速度の鈍化
* チームの拡大に伴い、情報連携のコスト増加
* エンジニア間でのスキル勾配
* ジョインタイミングの差による、発言者の偏り
* 雇用形態的に離脱リスクの高い業務委託、派遣の皆さんに依存したメンバー構成

### では、どうするか？

スクラムの適した人数を上回る人数となったのでチームを分割することは早々に決めていたのですが、次に課題となったのは、どう分けるか？という点でした。

#### 分け方で検討したこと
* ユーザー側と管理側の"作るもの"で分ける
* インフラ・サーバーサイド・フロントの"職域"で分ける
* 先発隊と後発隊の"役割"で分ける
* 完全にランダムで分ける

#### 進め方で検討したこと
* スクラムオブスクラム
* LeSS
* SAFe
* DAD
* Nexus

#### 検討して思ったこと
* 分け方って、状況に応じて求められるものが変わるんじゃない？
* 固定のチームって、チーム生産性は見えやすくなるけど、スキル勾配解消がしづらくない？
* 世の中に出ているフレームワークって、めちゃくちゃ理想のメンバー構成をベースにしているから、どのフレームワークでもそのままFitするか分からなくない？
    * やり始めると、Fitしないツラミばかり見えてきそうで、モチベーション低下しそう・・・

決め手となったのは、[行動指針](https://blog.uluru.biz/entry/2019/06/12/131854)に掲げた、**失敗を称え、失敗に学べ**という考え方でした。
**新しい挑戦してみたくない？**
そういう、ポジティブな発想から、LeSSやスクラムオブスクラムの良い部分を活用し、新しいフレームワークを作り挑戦する決定をしました。

### 作ったフレームワーク
FeSSの詳細については、[こちら](https://qiita.com/pilot_fish/items/40879f2ea2ddb87e8259)を御覧ください。

### やってみた感想
フレームワーク作るって難しい！！！笑
でも、都度見直したり、改善したりしながら育てていきたい！
（もしかしたら、改善し続けたら世に出ているフレームワークになっちゃうかもしれないけど。。。）


##最後に
チームで大小さまざまな課題に立ち向かっています。
もし、チームやプロダクトにご興味をお持ち頂けましたら、お声がけくださいませ。
是非ディスカッションさせて頂ければと思います。


Advent Calendar 10日目でした。
明日11日目は 若松和憲 さんによる記事を乞うご期待！
https://adventar.org/calendars/4548
git commit --amend でcommitを修正する

#git commit --amend とは
タイトルの通り、「git commit --amend」についての説明です。
最近、ちょっと修正してcommitするということが多いので書いてみます('ω')ノ

##そもそもamendって何？
googleで検索すると、「修正する」と出てきます。
つまり、「commitを修正する」という意味です。

##こんなことありませんか？
「commitコメント間違えた・・・」
「addし忘れたファイルが・・・」

そんな頻繁にあることではないと思いますが、
勢いでEnter押してcommitコメント間違える、ということが僕はたまにあります（笑）

##そんな時に--amend
```
# commitしよー！
$ git commit -m "hogehogeしました"
$ git pu
```
あΣ（・□・；）
今回の修正、「hogehogeしました」じゃねぇ！
「gehogehoしました」だった！ﾊｸｼｮﾝ(＠ゝз)o.:∵;´、


```
# commitコメント修正しよう
$ git commit --amend -m "gehogehoしました"
```
これだけです。
めちゃめちゃ簡単ですね！

addし忘れた場合も同様です。


```
# commitしよー！
$ git commit -m "タイトルの文言修正をしました"
$ git pu
```
あれ、test.phpのcommit忘れたわ

```
# それでは修正しよう
$ git add test.php
$ git commit --amend -m "タイトルの文言修正をしました"
```

##まとめ
addし忘れたファイルがある！
commitコメント間違えた！

そんな時は

```
$ git commit --amend
```
を使ってあげてください。


そして、commitコメントは正確に書きましょう＾＾
良くも悪くも後で見られる可能性があります。
そんな時に修正とは関係ないcommitコメントだと、困りますので(´・ω・`)
OneLang32の話でも

言語実装 Advent Calendar 2019 9日目です。
自作言語 Advent Calendar が埋まらないのでこっちにも参加してみました。

#Oneのレポジトリ

随分と更新していないですが、"One"という自作言語をつくっています。
https://github.com/bg1bgst333/OneLang32
まだ、字句解析器を経て、構文解析器の途中ということで、コンパイルもできないコンパイラです。
(いまのところ、yaccやlexの使用は考えていません。できることに制限をかけたくないためです。)
OneLang32はGUIプログラム用統合開発環境、OneLang32Consoleはコンソール用コンパイラとしていますが、今後どうなるかは未定です。
"One"言語をC++に変換するのが1つ目の目標です。

#Oneの仕様ドラフト

仕様はドラフトを作って提案しています。
https://twitter.com/search?q=%23onelangdraft&src=typed_query&f=live
といっても、Twitterに「#onelangdraft」のタグをつけてつぶやいているだけです。

#Oneのコンセプト

"One"言語は、これまでのプログラミング言語の常識を一切無視して開発しています。
あらゆる言語を超えて、すべてのプログラムを"One"に統一することが最終的な目標です。
今回は、まだ検討段階の仕様の一部を書いていきたいと思います。

#コンソール出力

```
"Hello, world!"
```
これだけです。
改行を入れる場合、

```
"Hello,
world!"
```

とできるようにする予定です。

#Window表示

```
Window
```

staticなウィンドウ表示。右上の閉じるボタンでオブジェクト破棄。タイトル、本文などは無し。
#Windowのインスタンス

```
Window"タイトル"{
    "本文"
} w1, w2
w1"window1"{
    "window1の本文"
}
```

この場合はdynamicなw1, w2がWindow属性で作成され、w1はタイトル"window1"、本文"window1の本文"に変わる。
(詳細はドラフト参照)

#拡張子

".1"を予定。

#各種機能

基本的に変数は宣言不要。
型は自動推論。(型なしかは未定。)
予約語は大量にあり、自由に変数名を使えないような大幅な制限を予定。

基本的に、グラフィックスやHTTPなどのネットワーク系機能などは、ライブラリとして提供されるのが一般的であるが、"One"では各機能ごとに文法が違う仕様にする予定。
たとえば、ダウンロードであれば、

```
http://bgstation0.com/path/to/hoge.txt -> C:\\hoge\path\to\hoge.txt
```

UIも、HTMLやAndroidXMLやXAMLなどに換わるUI定義言語を予定している。
たとえば、

```
-----
|e(100,100)|b|
-----
b->{
 msg(e)
}
```

「ボタンbを押したらエディットコントロールeをメッセージボックスで表示」
という意味である。
((100, 100)は座標。サイズの場合は(100, 100, 300, 200)などを予定。)
同じファイルにUI定義と動作コードを書けるようにする。

#まとめ
こんな感じで適当にいい感じに"1"行で書けるようにしたいから、"One"という名前を付けました。
とはいえ、これを実現するのは極めて難しいとおもっています。
Microsoft Learn 9日目

12月は、毎日 [Microsoft Learn](https://docs.microsoft.com/ja-jp/learn/) を受講していこうという記録。
※受講後に書き込むので公開に間に合わないこと多々あります(アドベントカレンダーの意味ｗ)

12/9 は
**Core Cloud Services - Azure アーキテクチャとサービスの保証**
 - Azure のサービスレベルアグリーメントについて
 - サービス全体の SLA を作成する

を受講。以下、簡易メモ。

# Core Cloud Services - Azure アーキテクチャとサービスの保証
## Azure のサービスレベルアグリーメントについて
Microsoft では、包括的な運用ポリシー、標準、プラクティスに従うことで、ユーザーに高品質の製品とサービスを提供するというコミットメントを維持してくれている。
"サービスレベルアグリーメント"(SLA)という正式なドキュメントで、Azure に適用されるパフォーマンス基準を定義する特定の条件をキャプチャしているぽい。

### Azure 製品およびサービスの SLA
Azure 製品およびサービス用の SLA には 3 つの主な特性がある。
#### 1. パフォーマンスの目標
Azure の製品またはサービス用のパフォーマンスの目標を定義している。
パフォーマンスの目標は各製品別になっている。

#### 2. アップタイムと接続性の保証
対応する Azure の製品またはサービスごとに、99.9%～99.999%の範囲のパフォーマンスの目標のコミットメントを指定している。
これによって、アップタイムや応答時間を加味してサービスに適用することも可能。

#### 3. サービス クレジット
Azure の製品またはサービスが規定の SLA の仕様に沿ったパフォーマンスを実現できない場合の Microsoft の対応方法についても説明している。(手厚い！)

## サービス全体の SLA を作成する
異なるサービス間で SLA を統合する場合、結果として得られる SLA は "複合 SLA" と呼ばれる。
### ダウンタイムの計算
SLA が以下のようになっていると
<img width="191" alt="7-sla-compositesla1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141029/695aa51a-6e2b-483b-3b73-3dc0761aa27e.png">
この複合 SLA は
`99.95 % × 99.99 % = 99.94 %` 
になる。
イコール、障害発生の組み合わせ確率は個々の SLA 値よりも高くなる。
これを改善するには、独立したフォールバックパスを作成する方法が有効。
上記の例だと、SQL Database が使えない場合はトランザクションを Queue に格納...など。
![7-sla-compositesla2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141029/96ab6c14-1535-b4d5-35f5-18710991f605.png)
SQL Database と Queue が同時に障害発生する確率は `0.0001 % × 0.0001 %` なので、この組み合わせの複合 SLA は、
`1.0 − (0.0001 × 0.001) = 99.99999 %`
Queue をこのサービスに追加することによって、合計の複合 SLA は
`99.95 % × 99.99999 % = ~99.95 % ` 
になる。
CentOS8 - Install - VSCode

### キーとリポジトリのインストール 
~~~
sudo rpm --import https://packages.microsoft.com/keys/microsoft.asc
sudo sh -c 'echo -e "[code]\nname=Visual Studio Code\nbaseurl=https://packages.microsoft.com/yumrepos/vscode\nenabled=1\ngpgcheck=1\ngpgkey=https://packages.microsoft.com/keys/microsoft.asc" > /etc/yum.repos.d/vscode.repo'
~~~

### パッケージキャッシュの更新とインストール
~~~
yum check-update
sudo yum install code
~~~

### 日本語化
1. View を選択
2. Command Pallete を選択
3. Configure Display Language を選択
4. Japanese Language Pack for Visual Studio Code を検索
5. インストールボタンを押下してインストールし、VSCodeを再起動

### Python有効化
1. Extensions を選択
2. Python（作成者：Microsoft）を検索
3. インストールボタンを押下してインストール
Linux標準教科書メモ その6

## ローカルエリアネットワーク(LAN)とワイドエリアネットワーク(WAN)

学校や自宅、会社などの閉じられた複数のコンピュータを相互接続したネットワークをローカルエリアネットワーク(LAN)という。離れた場所のLANとLANを結んだネットワークのことをワイドエリアネットワーク(WAN)と呼びます。

## IP
ネットワークが繋がったコンピュータ同士の間では、決まったプロトコルに従ってデータを送受信しています。現在のイーサネット(有線のLAN)規格のネットワークはプロトコルとしてTCP/IPを使っています。IPは送り先とデータからなるパケットを送る役目を担っています。

## TCPとUDP
TCPではデータのまとまりを一つ受け取ると、データの破損などのエラーを確認し、間違っている場合はデータの再送を依頼します。データが到達する信頼性の向上する役目を持っています。
UDPはエラー確認やデータの再送制御は行いませんが、その分データを高速に送ることができます。多少の欠損を気にしなくてもいい映像や小さいデータのような、速度を重視するような通信に適しています。
Firebase + Next.js (React.js + SSR) で遭遇したトラブルの話 & 書籍検索サービスの紹介

この記事は [ドワンゴ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/dwango) の13日目の記事です。

## はじめに

私は趣味で [書籍検索サービス（β）](https://search.riel.live/) というサービスの開発のお手伝いをしております。

このサービスの機能としては

* 検索ワードで書籍の検索ができる
* バーコードリーダーにより、書籍に印刷されたバーコードより書籍情報を取得できる
* 複数のストアの販売ページへのリンクが有る
  * 現在はAmazonとBOOK☆WALKERのみ。他サイトも追加予定。
* OpenBDによる書籍紹介目的で自由に利用できる画像が取得できる
* Twitterに画像として書籍情報を送信するための画像が生成できる

というものがあります。

https://search.riel.live/detail/9784040729558/

![book-9784040729558.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6583/75581a20-9642-4bfc-a3e1-121151ac2c3e.png)

このサービスでは、このような画像を生成することができます。
書籍を紹介する際に、ぜひ使っていただけると幸いです。

# 技術面の紹介

このサービスの、技術面での特徴は以下のとおりです。

* Firebase Hostingでホスティングされている
* Cloud FunctionsとNext.jsでSSRされている
* APIサーバもすべてNext.js上に実装されている
  * CORS実行できない外部APIがあるので、全ての外部通信をNext.jsでプロキシしている
* おすすめ書籍はContentfulで管理されている

Next.jsは開発開始当時の最新である9系列を利用し、最新機能であるAPIサーバ機能を利用して作っております。

![構成図](http://www.plantuml.com/plantuml/png/TOt1YeCm54Nt-Og7gvcDtw0YCnMA2dONiaZrOTF6f2HFB1J_lQrG20ItvrxEoJn9H_EaMQ_jF43ofnoUfKSuM4_AZ0ay6O2n0mAlyK7frOiD0V32sXjqA5r_WRojH41B9AbqG9l_5gf9ZlXbAriPBvnTFBgVhir_1QHfxDpzX0L-MXGHkiySfLZat5vrUOJ6Q6LGx3oQEvgYV0l2O3ndQ8PvqYy0)

# Next.js をFirebaseでホスティングした際に遭遇したトラブル

以上の構成で、起こったトラブルの一覧です。

## 9.0.7 以降の Next.js において(examlpeも含めて)壊れる

[Firebase example: couldn't find a `pages` directory · Issue #8893 · zeit/next.js · GitHub](https://github.com/zeit/next.js/issues/8893)

具体的にどのような問題かというと、Firebase+Next.jsの公式サンプルを使ってアプリケーションを作った場合ですら `couldn't find a pages directory` というエラーを出して、ホスティングに失敗するという不具合です。

私はこれで（9.0.7リリース直後に）休日を１日潰しました。
いくら不具合っぽいところを直しても治らなく、ローカルのdevサーバだけは動くという状況になりました。

この件に関してはIssueがあり、執筆時点(2019/12/07現在)でもまだクローズされていません。
そのため、**現時点では9.0.6にバージョンを固定してNext.jsを使っております。**

## SSR時に react-hooks が使えない

9.0.6に起因する問題なのかもしれませんが、SSR時にreact-hooksを使うとSSRでのビルドに失敗します。

この問題を回避するためにはDynamic Importを使用してhooksを使いたいコンポーネントを分割する方法と、react-hooksを諦めてHoC版のコンポーネントを使う方法の2種類があります。
いまはその2つの手法を併用しております。できればSSRを使用しておきたい箇所には使えないので困っています。
いい解決法があれば教えて下さい。

## `next/config` がうまく引き回されない

`publicRuntimeConfig` にdotenv経由で取り出したContentfulのAPIキーを書いているのですが、他ページから開いて遷移したときにエラーページになります。
これも壊れたままになっているのですが、良い直し方がわからずまだ放置しています。

# まとめ

個人的には、残念ながら「ReactでどうしてもSSRがしたい！」というとき以外に使うと罠に落ちるイメージになりました。

Reactは非常に良いプロダクトですし、このサービスを作ることによってReactへの理解が深まった気がします。
みなさんもぜひReactでプロダクトを作ってみてください。

あと、皆さん本を買って読みましょう！世界にはまだまだ面白い物語が待っていますよ！

以下は、デモを兼ねたこのサービスで生成した画像による自分のおすすめ作品です。

https://search.riel.live/detail/9784041028209/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6583/56bef518-584c-dc52-48e0-9807efe08a6d.png)

https://search.riel.live/detail/9784049126631/
![book-9784049126631.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6583/39004338-51a9-c0e2-2afa-834c962ca58f.png)
（ドワンゴポーカー部推薦図書です）

https://search.riel.live/detail/9784048935142/
![book-9784048935142.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/6583/3a5a2966-5852-059e-0887-8362b2e84abf.png)
zone.jsを使用してexpressでリクエストIDを出力するミドルウェアの作成

## zone.jsを使用してアクセス毎にユニークな識別子をログへ出力する
expressではアクセス毎にリクエストIDを発行する機能はなく、自前で用意する必要があります。
そこで、Nginx or UUIDv4を使用してリクエストID毎にユニークな識別子を用意します。
リクエスト毎に値を保持する必要があるので、zone.jsを使用し持ち回れるようにしておきます。
[nginxでrequest_id](https://qiita.com/toritori0318/items/d82f9beccd76ea8ccb85)
[uuid](https://www.npmjs.com/package/uuid)
[zone.jsについて](https://qiita.com/Quramy/items/83f4fbc6755309f78ad2)

```javascript:logger.js
'use strict';

require('zone.js');
const uuidv4 = require('uuid/v4');
const moment = require('moment');

exports.middleware = function(req, res, next) {
    const prop = {
        name: 'requestId',
        properties: {
            requestId: req.header('x-request-id') || uuidv4()
        }
    };
    Zone
        .current
        .fork(prop)
        .run(next);
};

exports.out = function(text) {
    const reqId  = Zone.current.get('requestId');
    console.log(`[${moment().format("YYYY-MM-DD HH:mm:ss.SS")}(${reqId})] ${text}`);
};

```

```javascript:app.js
const logger = require('./middleware/logger');
app.use(logger.middleware);
```

```javascript:index.js
var express = require('express');
var router = express.Router();

const logger = require('../middleware/logger');

router.get('/', function(req, res, next) {
  logger.out(`リクエスト受信 params => 【${req.query.example}】`);

  // 確認用に遅れてレスポンスを返す
  setTimeout(function () {
    logger.out(`レスポンス送信 params => 【${req.query.example}】`);
    res.json({test: 'Hello'});
  }, Math.floor(Math.random() * 1000));
});

module.exports = router;

```

## 確認
UUIDをリクエストパラメータにつけて複数アクセスをしてログを確認してみる。

```
[2019-12-09 23:34:05.76(8355c676546235af1cac5d31989d5e5a)] リクエスト受信 params => 【d951a794-11cd-45c8-966f-07f20594de2f】
[2019-12-09 23:34:05.79(30cd941018ec1a704c68177a49f746d2)] リクエスト送信 params => 【ab255a13-83fb-4bf2-9264-525524a5080b】
~~~~~~~~~~~~~~~~~省略~~~~~~~~~~~~~~~~
[2019-12-09 23:34:06.35(4de3ed283bbab693587359c7a53166b7)] リクエスト受信 params => 【e923b5b4-c07b-42e4-a050-56cc3526ddd3】
[2019-12-09 23:34:06.35(63cfc0e59444a18e5858e6b8cb53b6ff)] リクエスト受信 params => 【ea76cd1f-ca91-4d2d-88ad-158fdd31fc37】
[2019-12-09 23:34:06.40(8355c676546235af1cac5d31989d5e5a)] リクエスト送信 params => 【d951a794-11cd-45c8-966f-07f20594de2f】
```

`8355c676546235af1cac5d31989d5e5a`のリクエストがパラメータのUUID一致で表示されています。
【特性関数】確率変数の和の従う分布の計算

# 背景
数理統計学に特性関数というものが出てきます。これを利用すると確率変数の和の従う分布を簡単に計算できます。教科書を読んでいるだけだとなかなか身につかないので手を動かしてみます。

# 特性関数とは
定義は

```math
\phi(t) \equiv E[e^{itX}]
```

です。所見では意味がよくわからないのですが、実のところ、特性関数というのはフーリエ変換そのものです。上のように書くことで、連続分布と離散分布を統一的に定義出来るのが面白いですね。

# ガウス変数の和の従う確率分布を計算してみる
$W,X,Y$がそれぞれ独立に標準正規分布に従うものとします。このとき、それぞれの特性関数は

```math
\phi_X(t) = \int e^{itX}\frac{1}{\sqrt{2\pi}}e^{-x^2/2}dx = e^{-t^2/2}
```

となります。フーリエ変換そのまんまですね。それでは

```math
z = w+x+y
```

の従う分布を考えます。$(w,x,y)\to(z,x',y')$という変数変換を考えます。これらは

```math
\begin{eqnarray}
z &=& w+x+y\\
x' &=& x\\
y' &=& y
\end{eqnarray}
```

という関係とします。ヤコビアンは

```math
\frac{\partial(w,x,y)}{\partial(z,x',y')} = \left(
\begin{array}{ccc}
1 & -1 & -1\\
0 & 1 & 0\\
0 & 0 & 1
\end{array}
\right)
```

です。行列式は$1$となることが簡単にわかります。和をとる確率変数の数が増えても一般に行列式の絶対値は$1$です。余因子展開で容易に確認できます。

```math
\left(\frac{1}{\sqrt{2\pi}}\right)^3 e^{-w^2/2}e^{-x^2/2}e^{-y^2/2}dwdxdy = \left(\frac{1}{\sqrt{2\pi}}\right)^3 e^{-(z-x-y)^2/2}e^{-x^2/2}e^{-y^2/2}dxdydz 
```

より、余分な変数を積分してやって

```math
f_z(z) = \left(\frac{1}{\sqrt{2\pi}}\right)^3\int e^{-(z-x-y)^2/2}e^{-x^2/2}e^{-y^2/2}dxdy
```

となります。特性関数は

```math
\phi_z(t) = \left(\frac{1}{\sqrt{2\pi}}\right)^3\int e^{-(z-x-y)^2/2}e^{-x^2/2}e^{-y^2/2}e^{itz}dxdydz
```

です。ここで$z-x-y=w$を代入すれば

```math
\phi_z(t) = \left(\frac{1}{\sqrt{2\pi}}\right)^3\int e^{-w^2/2}e^{-x^2/2}e^{-y^2/2}e^{it(w+x+y)}dwdxdy = \phi_X(t)^3
```

と、特性関数の積になることがわかります。畳み込みの定理ですね。これを逆変換すれば

```math
f_Z(z) = \frac{1}{2\pi}\int e^{itz}\phi_z(t)dt = \frac{1}{\sqrt{2\pi\cdot 3}}e^{-z^2/6}
```

となります。ガウス変数の和もまたガウス分布に従うことがわかります。和の統計性が特性関数の積から計算出来ることは便利で、中心極限定理の証明でも利用されます。

# ポアソン変数の和の従う確率分布を計算してみる
一応離散分布でも同じようにして出来ることを確認しておきます。一変数の特性関数は

```math
\phi_X(t) = \sum_x e^{itx}\frac{e^{-\lambda}\lambda^x}{x!} = e^{-\lambda}e^{\lambda e^{it}}
```

となります。ここで$z=x+y$の従う分布を計算してみます。$x,y$の同時分布は

```math
p(x,y) = \frac{e^{-\lambda}\lambda^x}{x!}\frac{e^{-\lambda}\lambda^y}{y!} = \frac{e^{-\lambda}\lambda^x}{x!}\frac{e^{-\lambda}\lambda^{z-x}}{(z-x)!} 
```

であり、余計な変数について和をとってやれば

```math
p_Z(z) = \sum_{x}\frac{e^{-\lambda}\lambda^x}{x!}\frac{e^{-\lambda}\lambda^{z-x}}{(z-x)!} 
```

となります。これの特性関数は

```math
\phi_Z(t) = \sum_z e^{itz}p_Z(z) = \sum_z e^{itz}\sum_{x}\frac{e^{-\lambda}\lambda^x}{x!}\frac{e^{-\lambda}\lambda^{z-x}}{(z-x)!} 
```

となります。$z=x+y$を代入すれば

```math
\phi_Z(t) = \sum_z e^{itz}p_Z(z) = \sum_z e^{it(x+y)}\sum_{x}\frac{e^{-\lambda}\lambda^x}{x!}\frac{e^{-\lambda}\lambda^{y}}{y!} = \phi_X(t)^2 
```

と、一変数の特性関数の積で書けます。これを逆変換してやります。

```math
\begin{eqnarray}
p_Z(z) &=& \frac{1}{2\pi}\int_{-\pi}^\pi \phi_Z(t)dt\\
&=& \frac{1}{2\pi}\int_{-\pi}^\pi e^{-2\lambda}e^{2\lambda e^{it}}e^{-itz}dt\\
&=& \frac{1}{2\pi}\int_{-\pi}^\pi \sum_y e^{ity}\frac{e^{-2\lambda}(2\lambda)^y}{y!}e^{-itx}dt
\end{eqnarray}
```

となり、$y=x$以外ゼロなので

```math
p_Z(z) = \frac{e^{-2\lambda}(2\lambda)^x}{x!}
```

となり、やはりポアソン分布に従うことがわかります。

# まとめ
畳み込み計算にフーリエ変換を使うことは常識で、数理統計学においても重要な役割を果たすということですね。
ピボットテーブルで日単位の工数集計を行う

# ピボットテーブルで日単位の工数集計を行う

　以下のような生データを、特定の1日だけカテゴリ別に集計して分析するときに、ピボットテーブルを使ってまとめてみたのだけれど、そこでハマったこと（将来忘れそうなこと）のまとめ。

【生データ】

|開始|終了|摘要|
|:---------|:----------|:--|
|12/01 8:00|12/01 9:00 |出勤|
|12/01 9:00|12/01 10:00|会議|


## やりたいこと

1. 日付ごとにその日の時間の使い方を表示させる
1. 各項目が繰り返し表示されるようにし、第一正規形にする
1. 各項目の時間は、「1.5時間」などの表記とする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/0de8ba10-d136-ca13-48d4-1c9d426db956.png)


## 工数を*.*時間表記にする

　生データからは1:00のような表記で差が取れるが、それを時間単位に修正するのに意外と手間取った。
対策は非常に簡単。**Excel上で時刻表記されているものに対して×24し、表示形式を数値とすれば良い。**


## ピボットテーブルの設定

　次のような設定を実施。

- 各項目に対して、「アイテムのラベルを表形式で表示する」「アイテムのラベルを繰り返す」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/db5425e9-d6c1-5cdd-c94b-86d398da369b.png)

- **日付フィールドを一旦行か列に配置し、**右クリック→「グループ化」を選択。図のように「単位」から「日」以外のチェックをすべて外す。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/fbcd76e7-75a5-5139-2310-9ff44d989f7a.png)

- 日付のグループ化を解除した後で、日付フィールドをフィルタに移す（デフォルト年や四半期などにチェックが入っているが、最初からフィルタに日付を置くとこのグループ化が選択できない）

- 小計が邪魔なので、ピボットテーブルをクリックし、リボン右端の「デザイン」を選択。左端の小計より「小計を表示しない」を選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/151198/c4c2befb-0b6c-c0d5-e90a-14408ec8b16b.png)



## 参考文献

- [時刻表示（0:30）を数値表示（0\.5時間）に変換する](https://www.offinet.com/news/entry_74400.html)
- [ピボットテーブルでアイテムのラベルを繰り返す](https://support.office.com/ja-jp/article/%E3%83%94%E3%83%9C%E3%83%83%E3%83%88%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%A7%E3%82%A2%E3%82%A4%E3%83%86%E3%83%A0%E3%81%AE%E3%83%A9%E3%83%99%E3%83%AB%E3%82%92%E7%B9%B0%E3%82%8A%E8%BF%94%E3%81%99-882bdb55-9cdc-4d8d-b531-8e96e41dea31)
- [ピボットテーブル　フィルター　日付ごとに集計したいが月ごとになる](https://answers.microsoft.com/ja-jp/msoffice/forum/all/%E3%83%94%E3%83%9C%E3%83%83%E3%83%88%E3%83%86/716391e1-03dc-43f2-9323-893dace202f3)
- [ピボットテーブルで小計と合計の表示と非表示を切り替える](https://support.office.com/ja-jp/article/%E3%83%94%E3%83%9C%E3%83%83%E3%83%88%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%81%A7%E5%B0%8F%E8%A8%88%E3%81%A8%E5%90%88%E8%A8%88%E3%81%AE%E8%A1%A8%E7%A4%BA%E3%81%A8%E9%9D%9E%E8%A1%A8%E7%A4%BA%E3%82%92%E5%88%87%E3%82%8A%E6%9B%BF%E3%81%88%E3%82%8B-fc4d8406-f230-4762-aa2f-310826f3e5e2)


## 余談

　なぜこういう記録を付けるようになったかというと、朝なかなか早く起きれず悩んでおりまして。
『人生の主導権を取り戻す「早起き」の技術』という本の中に、「時間簿をつけて自分の時間の使い方を分析してみると良い」というアイディアがあり、それを実践してみたところ、夜のスマホ利用が多いことが判明。
　スマホを寝室に持ち込まないようにした結果、そこそこ改善されてきたので続けています。

　正確に時間付けようとすると絶対長続きしないので、ざっくりつけるルールを自分の中で決めると良いです。
bash , zsh等の確認・変更

　Mac OSでのbash等の確認について、メモしておく

#●現在の状態

　ターミナルを開く


```
echo $SHELL
```


#●使用可能なもの


```
cat /etc/shells
```


例：/bin/bash　，　/bin/zsh　等が表示される


#●変更


```
chsh -s /bin/bash
```


　※変更時にパスワードを聞かれる
　※変更後、ターミナルを切り、もう一度ターミナルを起動する
　 echo〜で現在の状態を確認すると、変更が適用されている
InternetExplorerを拒否するサイトの作り方

# InternetExplorerの対応が面倒くさい

ええい！面倒くさい！IEを拒否してしまえ！！ということで、IEを拒否する方法です。

※IEを拒否するとサイトのアクセス数が減ったり、UXを下げたりする可能性があるので注意が必要です。

# 方法

方法としては、JavaScriptを使って、IEでアクセスするとIEに対応していない旨が書かれたページにリダイレクトされ、Google Chromeのインストールを促すというものです。

# プログラム

```JavaScript:IE_boycott.js
var userAgent = window.navigator.userAgent.toLowerCase();
if(userAgent.indexOf('msie') != -1 ||
    userAgent.indexOf('trident') != -1) {
        window.location.replace("do_not_use_ie.html");
}
```

userAgentでIEか判定し、IEなら強制的にdo_not_use_ie.htmlにリダイレクトしています。

userAgentを書き換えてあったらリダイレクト回避されてしまいますが、そんなことをするような人はとっくに別のブラウザーに乗り換えているでしょう（たぶん）。

# リダイレクト先

正直リダイレクト先は何でもよいですし、直前まで見ていたところに戻すこともできますが、一応メッセージを表示します。

```HTML:do_not_use_ie.html
<h1>Boycott Internet Explorer</h1>
<p>
    このサイトは、Internet Explorer向けには作られていません。Internet Explorerでは、このサイトのレイアウトが最悪な状態になるでしょう。これは、Internet Explorerを考慮せず、最新のブラウザ向けにこのサイトが作られている為です。<br>
    正しい状態でこのサイトを閲覧したい場合は他の最新のWEBブラウザを使用してください。このサイトでは、Internet Explorerを完全に切り捨てます。
</p>
<p>
    はっきり言ってしまいましょう。Internet Explorerは、<strong>時代遅れ</strong>です。開発したMicrosoftも使用中止を呼び掛けています。<br>
    しかし、Internet Explorerを使っている人がなんと多いことか。そのおかげでWEBデザイナーの人たちが非常に苦労し、迷惑しているんです。最新の技術に対応していない時代遅れでも表示できるようにと。<br>
    本来、これは無駄な労力です。Internet Explorerを使う人が少しでも減れば、彼らが苦労せずに済みます。しかも、あなたも最新の技術で最高のネットサーフィンができます。<br>
    Internet Explorerを使い続けることは、デメリットしかないのです。
</p>
<p>
    この際ですから、あなたのせいで苦労している人たちのために、以下のリンクから最新のカッコいいWEBブラウザ「Google Chrome」（無料！シェア率トップ！)をダウンロードしてしまいましょう！！あなたもWEBデザイナーもWin Winです。
</p>
<p>
    <a href="https://www.google.com/chrome/" target"_blank">あなたのせいで困っている人を助ける！</a>
</p>
```

超手抜きです。もはやDOCTYPE宣言もしていません...。適宜書き換えてください。

一番下の「あなたのせいで困っている人を助ける！」というリンクを押すと、Google Chromeのダウンロードページに飛びます。

↓実際の画面です。表示にはEdgeを使っています。また、プライバシー保護のためモザイクをかけています。

![do_not_use_ie.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420120/f31d4978-6012-958c-0d35-006e6825f7f0.png)

手抜き過ぎて怪しいサイトに見えますね...。

ということで、IEを拒否するサイトができました。めでたし、めでたし。
自分の開発環境にSQLを入れてみる_1


progateもある程度進めた今日この頃。
自分のPCでSQLを叩いてみたい。そう思ったのだが、自宅にあった参考書にはなぜかWindowsでのSQL開発環境構築方法しか書いていなかった。

なのでGoogle先生の力と先人たちの力を借りて自分のMACにSQLをインストールしてみた。

##① MySQLのインストール
まずmacにhomebrewがインストールされていることが大前提となる。
ここではあまり深く言及しないがHomebrewとはMacOS専用のソフトウェア管理ツールです。
（知見が溜まってきたらこの辺りも記事にしたいな。）
他のわかりやすい記事をたくさん書かれているので今はそちらを参考にしてください。
Macのターミナルにて以下のコマンドを入力します。10分ほどでインストールが完了します。

```
$brew install mysql
```

##② 練習で使用するサンプルデータをダウンロードする
[こちら](https://dev.mysql.com/doc/index-other.html) データベースの元となるデータをダウンロードします。
このデータのアレを取得したり加工したりするデータの元となる物です。

##③ ターミナルにてMySQLを起動し、以下のコマンドを実行
`... SUCCESS!`が出れば接続成功です。

```
$mysql.server srart
~
... SUCCESS!
$mysql -uroot
```

##④ 使用するDBのソースファイルをインポートする

```
mysql > SOURCE ファイルのディレクトリ
```

##⑤ インポートが完了したら、使用するデータベースを指定する

```
mysql > USE hogehoge;
```

##⑥ 適当にクエリを叩いてみる!
![スクリーンショット 2019-12-09 23.19.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/485002/70a52b9f-5c67-f327-3b66-282d7fb9e613.png)

##⑦ SQLの終了
SQLの実行モードを終了するには以下のコマンドを実行します。

```
mysql > exit
$mysql.server stop //SQLへの接続終了
```


こんな感じでいかがだったでしょうか？
次はもう少し深掘りした記事を書きたいと思います。（余裕があれば）
Next.jsで画像の表示

# 解決策
- rootディレクトリにstaticフォルダを作成、そこに画像を入れておく。
読み込む際は、srcにstaticをつけてあげればオッケー

```html
<img src="/static/image.png"/>
```

ドキュメントだとpublicフォルダ作って画像入れておくといいと書いてありましたが、うまくいきませんでした。
[Android]デバッグ中のアプリのSQLiteデータベースのファイルを取り出して中身を見たい

# 環境

Android Studio 3.5.3

※[Android Studio 4.1](https://android-developers.googleblog.com/2020/10/android-studio-41.html)でデータベースインスペクターが実装されたため、この記事はdeprecated。

# 方法

Android Studioの右下にある `Device File Explorer` を開く。
<img width="324" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9104/58c371b2-9444-a381-5dc8-64fcee5c069c.png">

すると以下のような画面が出てくるので、 `/data/deta/(バンドルID)/databases/` とたどる。
<img width="336" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9104/3c619243-a693-8fa3-2722-96777ff2fc3c.png">

するとSQLiteのデータベースファイルの一覧が現れるので、右クリックして「Save As...」などする。
<img width="336" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/9104/dc833240-cbab-6390-2223-3ce1ec29dea9.png">

あとは[DB Browser for SQLite](https://sqlitebrowser.org/)などで開いて見るとよい。

# 参考

- [android - How do I pull a room db from my device? - Stack Overflow](https://stackoverflow.com/questions/49824822/how-do-i-pull-a-room-db-from-my-device)
railsのlow level cache

# low level cache

## RailsGuideより
> lowレベルキャッシュの最も効果的な実装方法は、Rails.cache.fetchメソッドを利用することです。このメソッドは、キャッシュの書き込みと読み出しの両方に対応しています。引数が1つだけの場合、キーを読み出し、キャッシュから値を取り出して返します。ブロックを引数として渡すと、キャッシュにヒットしなかった場合にブロックが実行されます。ブロックの戻り値は、指定のキャッシュキーの下にあるキャッシュに書き込まれます。キャッシュにヒットした場合は、ブロックを実行せずにキャッシュの値を返します。

```ruby
def cache_users
  key = "cache_users"

  Rails.cache.fetch(key, expired_in: 60.minutes) do
    User.all.to_a
  end
end
```

### オブジェクトをキャッシュしたい場合

```
class User < ApplicationRecord
  def cache_users(user_id)
    key = "#{cache_key}/cache_users"

    Rails.cache.fetch(key, expired_in: 60.minutes) do
      User.find(user_id)
  end
end
```

cache_keyメソッドを使っているので、キャッシュキーは233-20140225082222765838000/cache_usersのような形式になります。cache_keyで生成される文字列は、モデルのidとupdated_at属性を元にしています。
その為userが更新されるたびにキャッシュを無効にできるので、古いデータが返される心配がありません。

## 注意
キャッシュする値は、ブロックの中の値です。
`User.all`や`User.where()`などの返り値は`ActiveRecord_Relation`クラスのオブジェクトなので、
このオブジェクトをキャッシュしても、DB問い合わせは発生してしまいます。
DB問い合わせ結果をキャッシュしたい場合は`to_a`する事で、DB問い合わせ行い、問合せ結果を`Array`にした値をキャッシュさせます。

# 参考
https://railsguides.jp/caching_with_rails.html
https://qiita.com/srockstyle/items/3f1dad0c88c9ef4c5288
https://qiita.com/yamashun/items/bf9a3d29de749cf18f2e
Dashにおける@app.callbackの繰り返しInput,Stateをきれいに書く方法

# DashのInput,Stateの変数による書き方
* DashのInputやStateの第1引数には、id名を入れる必要がある。
* id名を連番にしたり、特定の名称+Noみたいな書き方をするとすっきりかけます。
* 繰り返しのInput,Stateがある場合は、下記の方法が良いと思います。

```python

# nは適当ですが、下記のように適当にFOOSを作り、
# STATESとして、リストを作ってあげることで、@app.callback内のStateに置き換えることができます。
# この方法でInputも作ることができます。
n = 5
FOOS = ['foo' + str(i) for i in range(n)]
STATES = [State(foo, 'value') for foo in FOOS]
@app.callback(
    Output('plot', 'children'),
    [Input('button', 'n_clicks')],
    STATES)
def update_contents(clicks, *args):
    print("click_num:{}".format(clicks))
    foo_args = args[0:len(FOOS) - 1]

    return foo_args[0]
```

# 知らなかったときの、Input,Stateの書き方
* このやり方を知らなかったときは、下記のように書いていました。
* 冗長性だったものをきれいに書くことができました。

```python

@app.callback(
    Output('plot', 'children'),
    [Input('button', 'n_clicks')],
    [State('foo1','value'),State('foo2','value'),State('foo3','value'),State('foo4','value'),State('foo5','value')]
def update_contents(clicks, *args):
    print("click_num:{}".format(clicks))
    foo_args = args[0:len(FOOS) - 1]

    return foo_args[0]
```
フィボナッチ数列を計算する

計算量について考えるネタとして、[フィボナッチ数列](https://ja.wikipedia.org/wiki/%E3%83%95%E3%82%A3%E3%83%9C%E3%83%8A%E3%83%83%E3%83%81%E6%95%B0%E5%88%97)を取り上げます。なお、多倍長整数など環境的にちょうどいいのと、作者が慣れているという理由で、コードはRubyで書きます。

## いちおう、紹介

改めて説明するまでもないかもしれませんが、フィボナッチ数列とは以下のようなものです[^1]。

$F_1 = F_2 = 1,\ F_{n + 2} = F_n + F_{n+1}\ (n \ge 1)$

具体的に書き出すと、1、1、2、3、5、8、13、21のようになります。

## ナイーブに実装

いちばんシンプルにやるなら、定義どおりに再帰的に実装することも可能です。

```ruby
def fib(n)
  return 1 if n <= 2
  fib(n - 1) + fib(n - 2)
end
```

もちろんこれでも実行はできますが、文字通りねずみ算式に`fib`を呼び出し続けるため、計算量は $O(2^n)$ となってしまいます[^計算量]。大きい数については実用的ではありません。

## メモ化を行う

いちばんシンプルには、すでに計算した分をメモ化すれば、残りの計算が不要となるので、計算量は $O(n)$ まで下がります[^計算量]。

Rubyの場合、ブロックつき`Hash`を使えば、物凄くシンプルにメモ化を書けます（[参考](https://qiita.com/bloody_snow/items/31e32770514b2b4c28f3)）。

```ruby
fib = Hash.new do |h, n|
  if n <= 2
    1
  else
    h[n] = h[n-1] + h[n-2]
  end
end
```

## 一般項で計算する

$x^2 + x - 1 = 0$ の解となる $\phi = (-1 +\sqrt{5})/2$ という値を使うと、$\phi(1 + \phi) = 1$ なので、漸化式は以下のように書き直せます。

```math
\begin{align}
F_{n + 2} &= F_{n+1} + F_n \\
F_{n + 2} + \phi F_{n + 1} &= (1 + \phi)F_{n+1} + F_n\\
&= (1 + \phi)(F_{n+1} + \phi F_n)\\
&= (1 + \phi)^{n} (F_2 + \phi F_1)\\
&= (1 + \phi)^{n+1}
\end{align}
```

同様に、 $\phi' = (-1 -\sqrt{5})/2$ についても、 $F_{n + 2} + \phi' F_{n + 1} = (1 + \phi')^{n+1}$ となります。よって、この2式から $F_{n + 2}$ を消去して、

```math
\begin{align}
(\phi - \phi') F_{n+1} &= (1 + \phi)^{n+1} - (1 + \phi')^{n+1} \\
F_{n+1} &= \frac{(1 + \phi)^{n+1} - (1 + \phi')^{n+1}}{\phi - \phi'}\\
&= \frac{1}{\sqrt{5}}\left\{\left(\frac{1 + \sqrt{5}}{2}\right)^{n+1} - \left(\frac{1 - \sqrt{5}}{2}\right)^{n+1}\right\}
\end{align}
```

さらに、 $((1 - \sqrt{5})/2)^n / \sqrt{5}$ の項の絶対値は0.5以下なので、1項目だけ計算して四捨五入すれば正しい値が出ます。

もっとも、大きなフィボナッチ数を計算する場合、概数はこれで見積もれますが、大きな数の計算精度に限界があるので、1の位まで正確な値を出すには向かない方法です。

## 行列で計算する

フィボナッチ数列の漸化式を行列で表すと、以下のようになります。

```math
\begin{pmatrix}
F_{n + 1} \\ F_n
\end{pmatrix} = 
\begin{pmatrix}
1 & 1 \\
1 & 0
\end{pmatrix} 
\begin{pmatrix}
F_{n} \\ F_{n - 1}
\end{pmatrix} 
```
ということで、繰り返し展開を続けると、

```math
\begin{pmatrix}
F_{n + 1} \\ F_n
\end{pmatrix} = 
\begin{pmatrix}
1 & 1 \\
1 & 0
\end{pmatrix}^{n - 1}
\begin{pmatrix}
F_{2} \\ F_{1}
\end{pmatrix} 
```

となります。あとは行列の冪を計算するだけですが、これは $O(\log n)$ で片付きます[^計算量]。

```ruby
require 'matrix'

base = Matrix[[1, 1], [1, 0]]

p base ** 10
```

[^1]: 0からスタートする流儀と1からスタートする流儀があるようです。
[^計算量]: 厳密にいえば、桁数が増えると加算・乗算の計算量自体も増えていきますので、このとおりではないです。
可視化してよかったメトリクス表

**※本エントリーでの「不具合」は、テスト中に検知されたものだけでなく、リリース後に検知されたものも含みます**

#この記事の概要
 - 読了までの時間：**4分**
 - リリース後に発生する不具合の削減を進める上で、どんな対策が有効か考えるために、不具合の分析を行うことが多いのですが、その中で可視化してよかった思うメトリクス表の例をいくつか紹介できればと思います

**メトリクス表の一例**
![メトリクス一覧.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312027/e85d4a65-3d69-b333-5b9e-cd41ee34d67b.png)

 - 以下で、それぞれのメトリクスについて、どのようなシチュエーションで使えるのか、また使用時の注意点を書いていきます

#発生箇所と不具合件数
![施策カテゴリと発生箇所.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312027/03d9b12e-fd84-fb8f-8865-7a301f624b7f.png)
**利用シチュエーション**

- 不具合は具体的にどの辺りで多いのか？を知りたいとき
- こちらは頻繁に使われるメトリクス表かもしれませんが、**発生箇所を特定**する際に有効です

**注意点**

- 発生箇所の粒度は、あまり細かすぎても傾向が見えづらくなるので、**画面単位くらい**がちょうどいい気がします

#各工程と不具合件数
![20191210_162830.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312027/d191b8d0-f93f-b85e-66e5-46b8d2f11866.png)
**利用シチュエーション**

- テコ入れすべきはテストケースなのか、開発の実装なのか？を知りたいとき
- フェーズごとに件数を可視化することで、がんばってテストでせき止めているところと、逆にテストが薄くて不具合が漏れ出ている箇所が見えてきます
- **テスト中の不具合が多い場合は実装改善の提案**を行ったり、逆に**リリース後の不具合が多くてテスト中の不具合が少ない場合は、テスト項目の見直し**などのNextActionにつなげられます

**注意点**

- テスト中の不具合とリリース後の不具合で、発生箇所のラベルを統一しておく必要があります

#テストケース項目と不具合数
![TC項目と不具合件数.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312027/4cf59828-47f6-7031-5556-37cdd1e0fbba.png)
**利用シチュエーション**

- 実装品質の弱いところを、しっかりと補えるテストケースになっているか？を知りたいとき
- さらに、市場に出てしまうと影響の大きな不具合に絞って見ることで、**リスク度合いに応じてテストケースが作られているか**を確認することができます
- 列にテストケース項目ごとのテストケース数を追加することで、**テスト粒度の強弱**についても確認することができます

**注意点**

- テストケースの項目は、機能の重要度によって増減する傾向があるため、テスト内容もあわせて確認する必要があります

#さいごに
- 上記のメトリクスを使用することで、大きく以下3点につなげることができました
 1. 弱点機能/範囲のテスト強化および開発チームの再発防止導入
 2. テストケースの改善
 3. テスト工数の妥当性の見直し
- 今回ご紹介したメトリクスはあくまで一例で、現場ごとに組み合わせるメトリクスなども異なりますが、うまくデータを使うことでより効果的な改善アプローチにつながると思いますので、引き続き良いアプローチを模索していきたいです。