OmniAICreator/Qiita-1.07M huggingface dataset:
EC2の削除保護を無視してterminatedなる状況を発生させてサービスダウンさせてしまった

ECS on EC2での話です。

# 結論

- ECSのスケールインはマルチAZを優先にスケールインさせる
- ECSのスケールインは条件によってはEC2の削除保護を無視してスケールインされる
- インスタンスタイプ選択時は立てれるアベイラビリティゾーンは確認しよう

# 再現方法

簡略化させて発生させる再現手順を記載します。

1. アベイラビリティゾーンに偏りがある状態でECSのEC2インスタンスを管理する
2. 片側のアベイラビリティゾーンだけを対象にEC2の削除保護を設定する
3. ECS（CloudformationもしくはAuto Scalingで）の最大台数を減らす
4. 削除保護されたEC2がterminatedになる

手順はわかったところで、スクショを交えて手順の説明の実施と再現させます。

## ECSインスタンスの状況

まずは前提となる状況を作り出します。

### ECSのアベイラビリティゾーンの設定

ECSのアベイラビリティゾーンを2つとします。今回はcとd。

![image url.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70363/ae7efbcd-c11b-150d-96e7-89866e709492.jpeg)

### ECSインスタンス達

アベイラビリティゾーンを2ゾーンしか設定していなければ、奇数台数のインスタンスを立てれば偏りが出ます。
このインスタンス達の **削除保護** の状態はこんな感じに片側だけ保護するようにする。

![image url (1).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70363/71f70675-cd10-360d-a847-cfc824c0a563.jpeg)

![image url (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70363/709132e0-b5ac-d20b-7d7b-05033267b814.jpeg)


## スケールインの実施

ここはCloudformationを変更してもいいし、Auto Scalingグループの変更でもどっちでもいいですが、最大台数を落とします。
今回は3台→2台への変更とします。

![image url (3).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70363/4420a400-e7c2-460a-1a16-ae1cacb77c56.jpeg)

すると、あら不思議！削除保護したインスタンスがterminatedになる。

![image url (4).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/70363/f5ca1a67-7f9a-9989-cc67-03af416c76a4.jpeg)


# 実業務で発生した状況

グダグダ書きましたが、私自身が実際に起きた状況は以下です。

## 前提条件

1. 該当のECSの **アベイラビリティゾーンはaおよびc** しか設定されていない

## 状況

1. EC2インスタンスタイプを変更するために最大台数（2→4）とEC2インスタンスタイプを **R5a** に変更する
2. **R5aは現状アベイラビリティゾーンaとdしか対応していない** ため今回はaに偏って立つ  
→この時点で状況を理解していたが、 **気にせず次のオペレーションを実施した** が最大のミス
3. 作成された新インスタンスの削除保護を実行
4. 旧インスタンスに乗っているコンテナのdrainingを開始
5. 旧インスタンスに乗っているコンテナがないことを確認後、Cloudformationで最大台数を戻す（4→2）
6. 旧インスタンスの1台はdrainingにも関わらず、アベイラビリティゾーンcであるがゆえに残されて、新インスタンス1台がterminatedになる
7. 晴れてterminatedとなった新インスタンスで動いていたコンテナ達は無情にも落とされて、サービスダウンとなる😭

正直ここからサービス復旧には30分もかかってないけど（長いと見るか短いと見るかは人それぞれだが、私に長い）、まぁ落ちたのは凹んだ。
最悪なのはECSのCloudformationのアベイラビリティゾーンの設定にdを足しても復旧しなかった。理由はアベイラビリティゾーンdに立ったインスンタンスでコンテナが立ち上がってもALBからのヘルスチェックが通らなかったため。
なぜならECSだけでなく、ALBのアベイラビリティゾーンもdの設定がなかったためです。
急遽ALBにもアベイラビリティゾーンdを足してコンテナを立ち上げたけど、時すでに遅し。

# 最後に

ECSのすべての動作を理解できてなかった検証不足と今後このような悲劇を生み出さないようにと自分への戒めとしてこの記事を書きました。
【Swift】RxSwiftを使ったTableViewの実装（Delegate/reloadDataは使わない！）

## Delegateで実装したくない！
`TableView`を実装しようとすると、Delegateで結構ソースの幅を取るのが嫌いです。
しかも`TableView`の元データに変更が会った時、わざわざ`.reloadData()`をしなければならない。。

そんなことしなくても、元データを監視して自動で`TableView`をリロードして欲しい！

そんな方法を *RxSwift* を用いて紹介しちゃう会。

##　実装
```swift
// 元データ
var list: Variable<[String]> = Variable([])

// viewDidLoadとかで読み込み
private func observeList() {
  list.asDriver()
    .drive(rx.items(cellIdentifier: "cell", cellType: CustomCell.self)) { (row, element, cell) in
      // cellの描画処理
      cell.setup(element)
    }.disposed(by: disposeBag)
}
```

これで`list`の値が更新されると、`TableView`がリロードしてくれます。
ソースも減って、元データの監視もできて、この書き方覚えたら元には戻れない。

##### RxSwiftに関する記事
[【Swift】RxSwiftでボタンのタップイベントを拾う](https://qiita.com/_asa08_/items/a9492b760a48965ecd9e)
HTML＆CSS：リンクの設定と画像の表示

リンクや画像の基本的なマークアップの知識についてまとめました～！

##別のサイトへリンクする（別タブで開く）
別のサイトへのリンクを指定するには、

```html
<a href="http://www.sbcr.jp">SBクリエイティブ社のWebサイトへ</a>
```
これだけ。
`<a>`タグに「target="_blank"」を追加すれば、リンクをブラウザの別タブ、または別ウィンドウで開かせることができる。

```html
<a href="http://www.sbcr.jp" target="_blank">SBクリエイティブ社のWebサイトへ</a>
```

##ページ内の特定の場所へリンクする
**ページ内リンクを設定する方法**
ページ内リンクを設定するには、移動先のタグにid属性を追加しておく必要がある。

```html
<h2 id="headline1037">アベンジャーズ</h2>
```
次に、リンクの`<a>`タグのhref属性には「＃」に続けて移動先要素のid名を書く

```html
<a href="#headline1037">アベンジャーズ</a></li>
 ```
また、href属性が「＃」だけのリンクは、クリックすると常にページの最上部に移動する

```html
<a href="#">ページトップに戻る</a>
```


##テキストリンクにCSSを適用する
リンクテキストにマウスが重なったとき（ホバー状態）や、クリックしたとき（アクティブ状態）にテキスト色を変えたり、下線の表示・非表示を切り替えたり、CSSでスタイルを操作することが可能

**リンクの状態に合わせて表示を変える**
リンクやマウスポインタの状態によって適用されるスタイルを指定するセレクタは全部で4つある。
「：」で始まるクラスは「疑似クラス」と呼ばれる

| セレクタ | 説明 |
|:-:|:-:|
| a  |疑似クラスなしの「a」はすべての`<a>`タグにスタイルが適用される。   |
|:link   | `<a>`タグで、かつhref属性がついている要素にスタイルが適用される。  |
| :visited  |`<a>`タグで、かつリンク先が訪問済みのときにスタイルが適用される。   |
|:hover   |その要素にマウスボタンが重なっているときにスタイルが適用される。   |
|:active   |その要素の上でマウスボタンがクリックされているときにスタイルが適用される。 |

※実際には:linkと:visitedは省略されることが多い

```css
a{
 color:#0073bc;
}
a:hover{
 color:#b7dbf2;
}
a:active{
 color:#4ca4e8
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/443245/bdac4678-6d2f-07ac-a48c-bf1f5d9d1303.png)
青いところの色が変わる


##画像を表示させる
HTMLに画像を表示する`<img>`タグは。次のようにして使用する。

```html
<body>
<img src="../../images/image1646.jpg" width="904" height="572" alt="陽が沈む">
</body>
```
この書式は 
`<img src="表示させたい画像ファイルのパス" width="画像の表示サイズ（幅）" height="画像の表示サイズ（高さ）" alt="画像が表示されないときのテキスト">`
となっています～～

##オリジナルとは異なるサイズで表示する
レスポンシブWebデザインでページのレイアウトを組んでいるときには、ウィンドウ幅に合わせてレイアウトを変化させるだけでなく、CSSを使えば`<img>`タグを無視して画像を伸縮させることができる。

```css
<style>
.img-responsive{
 display:block;
 max-width:100%
 height:auto;
}
</style>
</head>
<body>
<img src="../../images/image1646.jpg" width="904" height="572" alt="陽が沈む" class="img-responsive">
</body>
```
これの応用として、この画像をそのままサムネにすることもできる。
①`<img>`にクラス名「img-responsive」を付ける。
②`<img>`を`<div>`タグで囲み、その`<div>`の幅をCSSで200pxに固定する

##画像にリンクを付ける
画像にリンクを付けるには、`<img>`を`<a>`タグで囲むだけ。
画像の下にリンクを付けて、画像もテキストもクリックできるようにするには次のようにする。

```html
<a href="http://studio947.net">
 <div>
  <img src="../../images/image0320.jpg" width="396" height="292" alt="積み木">
 </div>
 <p>カラフルな積み木のセット</p>
</a>
```

##最後に
ふい～～～そろそろ難しくなってきたぞ、、、だれずに頑張ろう
2回目で合格したデータベーススペシャリスト試験 (デスペ) のFAQ式振り返り

<img width="180" alt="データベースアイコン1.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/1161f48a-7134-7b5c-5334-f7f2fdf822d5.jpeg">

# はじめに
平成31年度春期データベーススペシャリスト試験（デスペ）に合格しました。
自分の振り返りの意味も込めて記事を書きます。
主観で書いています。ご了承ください。

# 本記事の想定読者

- データベーススペシャリスト試験を受けようかと思っている人。
- データベーススペシャリスト試験を受けることの温度感を知りたい人。

# 結果編
### 何回目で合格しましたか？

- 2回目(2018年春と2019年春)

### 合格した際のスコアを教えてください。
![Screen Shot 2019-06-28 at 22.44.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/7664c7a7-d1a6-3e16-9a31-adc42d1b43fd.png)


# 1回目の振り返り編
### 1回目のスコアを教えてください。

- ちゃんと覚えていないけど、午後Ⅰが60点台、午後Ⅱで不合格に。

### 1回目と2回目の受験でどのような変化がありましたか？

- 1回目
    - とても難しく感じた。勉強で午後Ⅱの問題を解くのが苦痛でしかなかった。

- 2回目
    - ほとほどに難しく感じた。ある程度問題のパターンがわかってきた。

### 1回目受験時の反省点を教えてください。

- もっと過去問を繰り返し解くべきだった。
- どういうテーマの問題が多いのか、先に把握しておくべきだった。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/9c6bb667-08b1-d269-8214-c964a51cd955.png">




# 勉強編
### どれくらいの期間勉強しましたか？

- 1回目も2回目もおおよそ試験の1ヶ月前から。

### 勉強時間はどれくらいですか？

- 平日は1時間ちょい。週末はできる限り(3〜5時間くらい)。

### 具体的な勉強方法を教えてください.

平日の場合は以下の通り。

- 1ヶ月前から3週間前くらいまで
    - 後述の本読む。通勤時間に午前Ⅱの問題を解き始める。

- 3週間くらい前から2週間くらい前まで。
    - 午後Ⅰを1日2問。
    - 朝に30分で1問解く。
    - 会社から帰って来てから朝解いた1問目の答え合わせ、2問目解いて答え合わせ。

- 2週間くらい前から本番まで
    - 夜に午後Ⅱを1問解く。次の日の朝に答え合わせ&解説読む。
    - 夜に午後Ⅰを2問解く。朝はひたすら午前Ⅰ解く。

休日は適当に問題を解く。


### 参考にした本を教えてください。

- [失敗から学ぶRDBの正しい歩き方 (Software Design plus)](https://www.amazon.co.jp/dp/4297104083)
- [2018 データベーススペシャリスト「専門知識+午後問題」の重点対策 (専門分野シリーズ)](https://www.amazon.co.jp/dp/4865751149)

### 覚えるべき知識は多いですか？

- 少ないと思う。ネットワークスペシャリスト試験に比べれば。


### どんな勉強方法をオススメしますか？

- ひたすら過去問を解くこと。
- ３回は同じ問題を解くこと。


### 勉強で心がけるべきことは何ですか？

- 全般
    - 時間制限を設けながら問題を解くこと。
- 勉強開始初期
    - 分からないなら早々に諦めて、答えをみて勉強すること。
- 試験間近
    - 問題文を読みながら「〇〇が問題になりそうだな」と、設問を想像しながら読むこと。

<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/f3a7509e-1c7b-21df-ca38-ee7637c56ab9.png">




# 受験しようと思う編
### どうしてデータベーススペシャリスト試験を受けようと思ったのですか？

- IPAの高度試験の中で一番簡単だと思ったから。
- 会社から奨励金が出るから。
- 周りにもデスペ合格した人が多いから。


# バックグラウンド編
### 受験時の業務経験を教えてください。

- ほぼ未経験から新卒でSIerに入って2年過ぎたところ。
- AWSが主戦場。

### データベースに関連する業務経験は受験時にありましたか？

- ほとんどない。
- AWSのRDSで、バックアップからリストアするくらいしかやったない。
- 業務でSQL書いたことほとんどない。


<img width="200" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/237882/d1e9a980-c0c6-84a7-6a4b-8a2df9bfb75b.png">



# コメント編
### 受験して良かったと思うことを教えてください。
- 要件からデータベースを設計・構築・運用していくことのざっくりした理解が出来たこと。

### 受験して悪かったと思うことを教えてください。

- まとまった時間を作らないと過去問を解けなかったこと。



# その他編
### なぜFAQ形式で記事を書こうと思ったのですか？

- 職場の先輩がFAQ風の解説をやってて真似したくなったため。

### 何回目の受験で合格する人が多いのでしょうか？

- 分かりません。ただ自分の周りでは１回目の受験で合格した人がほとんど。

### データベーススペシャリスト試験に合格して何か変化はありましたか？

- 特にない。給料もそのまま。

### 今後データベースを得意に出来そうですか？

- いいえ。
- 試験に合格するだけではまだまだ。実際に自分で手を動かさないと。

### 他に資格を取ったりしていますか？

- ネスペは取った。よかったら下の記事も見て。
    - [ギリギリでネットワークスペシャリスト試験 (ネスペ) に一発合格した私の勉強方法](https://qiita.com/tr_ikym/items/8eb9010d066f4bfdd541)
チケットでタスク管理するときに気をつけたいこと

# はじめに
4月からシステムディレクション業務をしており、[Backlog](https://backlog.com/ja/)や[Redmine](http://redmine.jp/overview/)のチケットを使ってタスクを依頼したり問い合わせしたりすることがよくあるので、
チケットを使う上で自分が個人的に心がけていること、こうしたらいいんじゃないかなーと思っていることを書いてみました。
チケットは、タスクの内容、量、優先順位を把握しやすくするためのものであるという個人的な考えに法っています。

# チケットの心得
1. １チケット１依頼（タスク）
2. チケットタイトルは内容がわかるものにする
3. 期限、進捗、担当者は変化があれば随時変える
4. 終わったチケットのクローズは忘れずに

## １チケット１依頼（タスク）
- チケット一覧を見たときに、各々のタスクの量がわかりやすくなる。
- 1つのチケットに複数の異なる依頼があると煩雑になり、チケット一覧を見ても各自のタスクがわかりづらい（ただし粒度が細かすぎても煩雑になるので注意）。
- やり取りの中で新たに依頼（タスク）が生まれたら、別チケットを新たに作成し、そのチケットはクローズするようにする。

## チケットタイトルは内容がわかるものにする
- いちいちチケットの中身を確認する手間が省ける。
- 相手がタスクをすぐに把握しやすくするため、基本的にチケットタイトルと異なる内容の依頼はしないようにする（１チケット１タスクの原則）。

## 期限、進捗、担当者は変化があれば随時変える
- 特に期限は優先順位を決めるために必要であるため、期限設定は重要。だが忘れがち。

## 終わったチケットのクローズは忘れずに
- 後からチケットを見た人が、このタスクは終わっているものかどうか判断できなくて困る。余計な仕事が増える。
- 保留にしているのであればその旨をコメントに残す。

# 最後に
自分がプロジェクトを抜けてもチケットは残っていくものであり、そのプロジェクトを引き継ぐ人にとっては重要な情報の一つとなるため、きちんと運用していく必要があるのではないかと思います。

チケットでも、ドキュメントでも、コードにしても、
**他人は自分の考えていることや背景を全く知らない。**
**未来の自分もほぼ他人である。**
ということを忘れなければ、多くの人にとってよりわかりやすいものが作成できるのではないかなと思いました。
自治体単位で色分けした、動かせる地図を作成する

# 自治体単位で色分けした地図を作りたい
**行ったことのある町**一覧、**過疎自治体**一覧、**被災地**一覧など、自治体単位で色を塗り分けした地図を作りたい、という場合に、実現する方法を調査して実装した。

# 利用するAPI
Googleの[GeoChart](https://developers.google.com/chart/interactive/docs/gallery/geochart)は都道府県単位での色分けしか対応してなかったので、[Yahoo! JavaScriptマップAPI](https://developer.yahoo.co.jp/webapi/map/openlocalplatform/v1/js/)を使う。
事前に[アプリケーション登録](https://e.developer.yahoo.co.jp/register)を行い、APIキーを取得しておく。アプリケーションの種類は`サーバーサイド（Yahoo! ID連携 v2）`でも`クライアントサイド（Yahoo! ID連携 v2）`でもOK。

# コード

```html
<script type="text/javascript" charset="utf-8" src="https://map.yahooapis.jp/js/V1/jsapi?appid=APIキー"></script>
<div id="map" style="width:100%; height: 800px;"></div>
```

```javascript
var map = new Y.Map('map');
map.addControl(new Y.LayerSetControl());
map.addControl(new Y.SliderZoomControlHorizontal());

// 白地図レイヤーを作成
var blankmap = new Y.BlankMapLayer();
var style = {
	area: {
		default: 'dcdcdc',
		'01205': 'ffff22',
		'01208': 'ffff22',
		'01210': 'ff4444',
		'01233': '44ff44'
	},
	label: {
		default : '696969'
	},
	border: {
		default : 'aaa'
	},
	bg: 'b0c4de'
};
blankmap.setStyle(style, true);

// レイヤーセットを作成
var layerset = new Y.LayerSet('白地図', [blankmap], {maxZoom: 20, minZoom: 9});
// Mapオブジェクトにレイヤーセットを追加
map.addLayerSet('blankmap', layerset);
// 地図を描画します。
map.drawMap(new Y.LatLng(36.2, 136.73100), 9, Y.LayerSetId.NORMAL);
// 表示を白地図にする
map.setLayerSet('blankmap');
```

areaオブジェクトに[全国地方公共団体コード](http://www.soumu.go.jp/denshijiti/code.html)をキーに、色を値にした情報を入れる。

# 結果
ズームレベルによって表示のされ方が異なる。

### ズームレベル10
自治体名まで表示される。
![map10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416295/6330231d-89a0-cb08-10dd-79f3ce4f1835.png)

### ズームレベル9
都道府県名までしか表示されない。
![map9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416295/ee2bd558-6684-7645-9dfa-6e3fcccedba3.png)

### ズームレベル8
都道府県単位でしか色分けされない。
![map8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416295/2e15f364-c40c-b288-2be1-a728111066cf.png)

# しかし

色を塗る自治体の数が多くなりすぎると地図が表示されなくなってしまう模様…。
どうやらAPIの処理の内部で色塗り用の画像URLを動的に生成しているようなのだが、自治体が多いとURLが長くなりすぎて、`414 URI Too Long`になってしまい、描画に失敗してしまう。
大体、300自治体ぐらいを超えてくるとうまくいかなそう。
超小ネタ 引数に渡した複数の数値が0を除き同じ符号かを判定する

# コード
```python
def is_same_sign(*numbers) -> bool:
    return len({x > 0 for x in numbers if x != 0}) <= 1
```

# テスト
```python
assert is_same_sign(*[1, 5, 0])
assert not is_same_sign(*[-1, 5, 0])
assert is_same_sign(*[0, 0, 0, 0])
```

# 解説
関数`is_same_sign`は、`set`内包表記を用いて、
- 引数の中で0でない要素のみを絞り込み、
    - 0より大で`True`
    - 0より小なら`False`

とする`bool`の`set`を作る。

この`set`は
- `set()`: 長さ0の空`set`
- `{True}`か`{False}`: 長さ1の`set`
- `{True, False}`か`{False, True}`: 長さ2の`set`
となり、**全て符号が同じ = `set`の要素数が0または1 = 要素数が1以下**ということができる。

以上。
ローカル環境吹っ飛ばしかけてゴタゴタして復旧するまでの道のり

どーも。ゼロです。　
今日はタイトルにある通り、C言語の開発をしようとして仮想マシンが一時使えなくなりかけ、復旧するまでの過程を紹介します。

#経緯
VirtualBoxのアプデでローカル開発環境が一時使用不能に。。。
これは私の勘違いだったのでことなきを得たんですが、一回仮想サーバを最初から立ち上げたので復旧までに時間を要するハメに。
検索してもあまりいいソースがなかったので自分の記録も兼ねてここに残すことにしました。

###補足事項
C言語は大学で履修しているのですが、講義の使用ソフトがWindows専用なのでローカル開発環境を作ってPHPと同じ環境でやることにしました。

#開発環境
OS：macOS Mojave(10.14.5)
VirtualBox　6.0.8
Cyberduck　7.0.1

#復旧までの道のり
文章で書くと長くなりそうなのでコードを貼ります
前提環境はこんな感じ。

```
zer0sMBP:~ zer0$ cd MyVagrant/
zer0sMBP:MyVagrant zer0$ cd MyCentOS/
zer0sMBP:MyCentOS zer0$ vagrant  up
Bringing machine 'default' up with 'virtualbox' provider...
==> default: Checking if box 'bento/centos-6.8' version '2.3.4' is up to date...
==> default: Machine already provisioned. Run `vagrant provision` or use the `--provision`
==> default: flag to force provisioning. Provisioners marked to run always will still run.
[vagrant@localhost ~]$ cd c_lessons/
[vagrant@localhost c_lessons]$ ls
hello  hello.c
[vagrant@localhost c_lessons]$ 
```
##コードの解説
今回は、[こちらのサイト](https://dotinstall.com/lessons/basic_localdev_mac_v2)を参考に開発環境を整えました。

無事にvagrant sshまでは行きました。

そして今回はc_lessonsというフォルダにhello.cというファイルを作成しています。
それが上記のコードの下から3番目です。
コンパイルできているのでlsで中身を見ると、hello hello.cというふたつのファイルがありますね。

##コンパイル成功してHello Worldまでの道のり

C言語はJavaScriptなどと違いコンパイル言語なのでコンパイルという作業が必要です。
簡単に言えば、コードをコンピュータが読める言葉に変えることですね。

コンパイルといえばgcc
ただ、これをインストールする必要がある。。
ちなみに私はコードを書いて、コンパイルする時にコマンドを打って実行してエラーが出るまでインストールしていないことに気づかなかった。
こんなことがないようにして頂きたいです。

話のメイン部分ではないので、今回は参考になったサイトのみを紹介します。
[参考サイト](https://blog.kobunata.xyz/archives/2967)

少し補足
上の記事の中にMore Downloads for Apple DevelopersにアクセスしてコマンドラインコンテンツをDLするのだが、下のベータ版ではない方をインストールして開こうとしたらイメージが対応していないというエラーが出たので私はベータ版を入れました。

<img width="1095" alt="スクリーンショット 2019-06-27 23.44.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/372171/d58b329e-0f74-15af-616e-83451c6e832c.png">

#問題発生
コマンドラインの環境も揃いこれでコンパイルできると思ったら出来ませんでした。。。

gcc コマンドが見つかりませんのエラーが出てきました。。。
あれ？

gccのバージョン確認をするとちゃんとバージョンが出るんですがね。
ググってみると、yumコマンドでgccがインストールされるらしいので[これ](http://hensa40.cutegirl.jp/archives/2084)をやってみることに。
自分はCentOSだったのでこれをやりましたが、他のものを使っている方は違うかもしれないのでご注意ください。

```
yum -y install gcc
```
まずこのコマンドを打つのですがあれ？
root権限じゃないと使えないみたいなエラーが出ました。。。

今まではuser権限だったんですよね。
root権限全ての仕様変更が可能になります。割とこれ使い方に気をつけないとヤバいみたいです。

root権限にするのはこんな感じでできます。

```
[vagrant@localhost c_lessons]$ su - root
パスワード:
[root@localhost ~]# 

```
パスワードを入れればシャープがつきます。パスワードは表示されないので注意

これで

```
yum -y install gcc
```

このコマンドを打って、Complete！が表示されたら完了

root権限終了はexitで終了できます。

これでコンパイルできますね〜

```
[vagrant@localhost ~]$ cd c_lessons/
[vagrant@localhost c_lessons]$ gcc -o hello hello.c
[vagrant@localhost c_lessons]$ ./hello
Hello World
Hi! zer0
[vagrant@localhost c_lessons]$ 
```
これで完了ですね〜！
めっちゃ嬉しいですよね。この瞬間って。

ソースは少なかったですが、パーツごとにググってここまでできたのでいい経験になったと思います。
この記事が誰かの参考になったら嬉しいです。
python学習の進捗状況

今日はpaizaラーニングのpythonをレッスン2まで終了しました！

以前にprogateでHTMLを勉強しましたが、その時と違い計算や数字に特化した言語なのかなという印象です！

取っ掛かりやすく初心者の私には非常にわかりやすいので明日からも頑張っていきたいと思います！

基本情報技術者試験の方はテキスト3章まで終わりました！

2進数の計算が慣れず少し苦労したので、反復あるのみです！
[WPF]子要素のBindingを忘れて親要素が勝手にBindingされる問題

# 問題
ビジュアルツリー上の親子関係があり親子で同名のプロパティをBindingしていた時、子要素のBindingがされていないと親要素のプロパティがBindingされて表示されてしまいました。

具体的にコードで示してみます。
まず、親要素MainWindowに子要素SubWindowを表示します。

```xml:MainWindow.xaml
<Window x:Class="WpfSample.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="clr-namespace:DoubleLoadWpf"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Vertical">
            <TextBlock Grid.Row="0" Text="MainWindow" Foreground="Red"/>
            <TextBlock Grid.Row="0" Text="{Binding Message}" Foreground="Red"/>
        </StackPanel>
        <local:SubWindow Grid.Row="1"/>
    </Grid>
</Window>
```
子要素SubWindowには、親要素のMainWindowと同名のプロパティMessageをBindingしておきます。

```xml:SubWindow.xaml
<UserControl x:Class="WpfSample.SubWindow"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid>
        <StackPanel Orientation="Vertical">
            <TextBlock Grid.Row="0" Text="SubWindow" Foreground="Blue"/>
            <TextBlock Grid.Row="0" Text="{Binding Message}" Foreground="Blue"/>
        </StackPanel>
    </Grid>
</UserControl>
```

親要素MainWindowのみBindingします。
コードビハインドでDataCotextとMainViewModelを紐づけます。

```c#:MainWindow.xaml.cs
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new MainViewModel();
        }
```

MainViewModelではプロパティMessageに値を入れておきます。

```c#:MainViewModel.cs
    internal class MainViewModel
    {
        public string Message { get; } = "MainWindow";
    }
```

■実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/245399/94816744-4260-dd58-e0bf-e9055dfbb784.png)

# 原因
SubWindowのMessageでは、親要素MainWindowのMessageがBindingされて「MainWindow」が表示されていることが分かります。
これは、SubWindowでDataCotextがBindingされていないため、親要素MainWindowのDataContextがBindingされてしまったためです。

# 因みに
DataContextが継承される件は、[WPF、怒りのツリー外DataContext伝播](https://qiita.com/ugaya40/items/58e9e3c3340cc1f61b4f)によると、WEPerには常識のようです・・・。悲しい。

PrismのRegionManagerで画面遷移していたりすると気づきにくく発見が遅れました。改めて基礎大事。
flutter_web から JS の WebWorkers を呼んでみた

[Flutter web でアプリを試作してみた](https://qiita.com/emaame/items/630564bed6c4ddb8d7c5) の処理部分を 生 JS の `Web worker` にくくりだしました。

* `JavsScript` の [`Function`コンストラクタ](https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function) を使いたかった
* 生だとどういう型が動くのか知っておきたかった

からです。この文章は、主に後者のメモです。

## まとめ

* `Web worker` へは、`JSON` で渡した（思考停止）
* `Web worker` から `Uint8Array` を返すと、[`ByteBuffer`](https://api.dartlang.org/stable/2.4.0/dart-typed_data/ByteBuffer-class.html) にキャストできる形で返ってくる。
* [`ByteBuffer`](https://api.dartlang.org/stable/2.4.0/dart-typed_data/ByteBuffer-class.html) を `asInt8List` で `Int8List` にし、
必要に応じて `sublist` で `List<int>` を切り出して使用した。

## 今回の `Web worker` の入出力

* 入力： 試行回数と、フィルタの構成（JSON）
* 出力： フィルタをパスした回数と、そのサンプル群

## `Web worker` 部（処理側）

`web/filter.js` を置いておくと、`webdev serve` で参照でき、`webdev build` 時に `build/filter.js` にコピーしてくれます。

入力は、`Enum` の `index` への変換などが必要で、JSONで渡すことにしました。
処理は、汎用的な話ではないのでざっくり載せておきます。

```web/filter.js
/* 前略 */
self.addEventListener('message', function (e) {
  // 指定された試行回数と、フィルタを元に、ランダムな局面を生成しパスする回数を数える
  const param = JSON.parse(e.data);
  const trials = param.trials;
  const filters = param.filters;
  const testFunc = makeTestFunc("yama", filters);
  var samples = [], passedCount = 0;
  const yama = Array.from(initYama);
  for (var i = 0; i < trials; ++i) {
    yama.shuffle();
    if (testFunc(yama)) {
      ++passedCount;
      if (samples.length < 100) {
        samples.push(Array.from(yama));
      }
    }
  }
```

それで、`flutter_web` に結果を返すのがこちらの部分。
配列をそのまま返すと、プロセス間のコピーが生じて遅くなるので、`Transferable` な形で返す。
所有権の移動だけになるらしい。`shared` なのは未だ無さそう。

最初、パスした回数などもバイナリに埋め込まないと駄目かと思ったのですが、
普通にオブジェクトを渡せば、`flutter` 側で `Map` で受け取れるので、
重たいデータだけ変換してやると良いと思います。

```web/filter.js
  // Transferable に変換してコピーのロスを減らす
  const result = new Uint8Array(samples.length * 32);
  var offset = 0;
  for (var i = 0; i < samples.length; ++i) {
    const yama = samples[i];
    for (var j = 0; j < 32; ++j) {
      result[offset + j] = yama[j];
    }
    offset += 32;
  }
  self.postMessage({ passedCount: passedCount, samples: result.buffer }, [result.buffer]);
}, false);
```

この文章を書いていて、最終的に `Uint8Array` が固定長で良くなったので、`Array` に `push` してるのを直接、
`Uint8Array` に保存すれば無駄が無くなることに気がついた。

## `Flutter` 部（呼び出し側）
呼び出しは `postMessage`、結果の受け取りは `onMessage.listen` で行う。

配列の結果は [`ByteBuffer`](https://api.dartlang.org/stable/2.4.0/dart-typed_data/ByteBuffer-class.html) にキャストすれば良かった。`print(msg.data["samples"])` すると `NativeByteBuffer` だと言われましたが、問題なくキャストできているようなのでこれ以上深堀りしていない。

`ByteBuffer` を `asInt8List` で `Int8List` にしておき、
必要に応じて `sublist` で `List<int>` を切り出して使用した。

```lib/main.dart
final w = Worker("filter.js");
w.onMessage.listen((msg) {
  final passedCount = msg.data["passedCount"] as int;
  final samples = msg.data["samples"] as ByteBuffer; /* NativeByteBuffer */
  setState(() {
    _passedCount = passedCount;
    _samples = samples.asInt8List();
    /* （中略） */
w.postMessage(jsonEncode({"trials": _trials, "filters": _filters}));
```
初心者でも簡単にGoogle Apps ScriptでSlackにリマインダーを送る

## 参考にした記事一覧
Google Spread Sheetを読み込む方法:
https://kujirahand.com/blog/index.php?GAS%E3%81%A7%E4%BB%BB%E6%84%8F%E3%81%AE%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%88%E3%82%B7%E3%83%BC%E3%83%88%E3%81%AE%E5%80%A4%E3%82%92%E8%AA%AD%E3%81%BF%E8%BE%BC%E3%82%80 

Slackに通知を飛ばす方法:
https://qiita.com/chihiro/items/c7b11abc78f5d806c3a8

## 概要
毎朝行う朝会で日毎にファシリを決めているのだが、「今日のファシリ誰だっけ？」と思い出している時間が勿体無いので、あらかじめ作成してあったSpread Sheetを活用し、Slackにその日のファシリは誰かを通知してくれるbotが欲しかったので実装してみました。ちなみに今回が初めてGAS(Google Apps Script)なるものを触りました。

## 実装したスクリプト
```js

// スプレッドシートの読み込みに必要な変数群
var sheet = SpreadsheetApp.openByUrl('<あらかじめ作成してあったSpread SheetのURL>');
var rows = sheet.getDataRange();
var numRows = rows.getNumRows();
var values = rows.getValues();

// 曜日の取得に必要な変数群
var date = new Date();
var dayOfWeek = date.getDay();
var dayOfWeekStr = ["日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"][dayOfWeek];

// Slack通知に必要な変数群
var postUrl = '< Slack通知の際に必要なIncoming WebHooksのWebhook URL >';
var username = 'reminder';
var icon = ':ghost:';

function myFunction() {
  for (var i = 1; i <= numRows - 1; i++) {
    var weekdays = values[i][1];
    if (dayOfWeekStr === weekdays) {
      var message = '今日のファシリテーターは '+ values[i][2] + ' だす!';
      var jsonData = {
          "username": username,
          "icon_emoji": icon,
          "text" : message
      };
      var payload = JSON.stringify(jsonData);
      
      var options = {
          "method": 'post',
          "contentType" : "application/json",
          "payload" : payload
      }
      
      UrlFetchApp.fetch(postUrl, options);
    }
  }
}
```

## 処理の流れ
### ファシリ担当Spread Sheet
<table>
  <tr>
    <td>番号</td>
    <td>曜日</td>
    <td>担当</td>
  </tr>
  <tr>
    <td>1</td>
    <td>月曜日</td>
    <td>社員A</td>
  </tr>
  <tr>
    <td>2</td>
    <td>火曜日</td>
    <td>社員B</td>
  </tr>
  <tr>
    <td>3</td>
    <td>水曜日</td>
    <td>社員C</td>
  </tr>
  <tr>
    <td>4</td>
    <td>木曜日</td>
    <td>社員D</td>
  </tr>
<tr>
    <td>5</td>
    <td>金曜日</td>
    <td>社員E</td>
  </tr>
</table>

### アウトプットイメージ
Slackに曜日に応じて「今日のファシリテーターは 社員Hoge だす!」と通知される

### 実装の説明
関数内の処理について主に説明します。
- Spread Sheetを一行ずつ読み込む
- Spread Sheetに記載してある曜日と本日の曜日を比べる
- 曜日に応じてメッセージに曜日に適した社員名を追加
- JSON.stringifyでJavaScriptの値をJSON文字列に変換
- Slack通知の前にSlack通知に必要なoptionsを作成
- Slack（外部サービス）を使用する場合、Web APIを利用し、「HTTPリクエストを送る」必要があるため、以下のメソッドを使用する必要があったので実装

```js

UrlFetchApp.fetch(URL,[options]);
```

### 完成形（アウトプット）
無事Slackに通知を送ることができました！（金曜日に実行した場合）
<img width="425" alt="スクリーンショット 2019-06-28 14.59.47.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/290209/901c6065-b3c3-9e2b-f0b4-23d2e431ce09.png">
MongoDBのdb.Collection.aggregateを使うお話

# はじめに
__この記事を書き終える直前に「もしかしてDBサーバのスペックのせいじゃね？」と思ってしまったので数値の類は真に受けないでください。__
aggregateを使うとこんなことができるんだー程度でお願いします。
大人の事情でデータ構造やコードなどをかなり改変しています。
この記事は私の個人ブログの記事を再編成して持ってきたものです。
# 事の発端
他のサーバエンジニアの方「データを抽出するためのMongoShell書いてるけどパフォーマンス出ない」
# 抽出対象のデータ
実際のサービスのコレクションのバックアップを展開したもの
## データ構造(1ドキュメントあたり)
```json:item
{
    "inventory": {
        "item1": {
            "time": 1212121212121
        },
        "item2": {
            "time": 1212121212121,
            "count": 2
        } ...
    },
    "used": {
        "item3": {
            "time": 1212121212121
        },
        "item2": {
            "time": 1212121212121,
            "count": 1
        } ...
    } 
}
```
## 抽出したいもの
ユーザがアイテムおよび過去に使用したアイテム(`used`以下)の合計個数
各アイテムの個数は`count`、ただし`count`が存在しない場合は1とみなす
# コード
## 普通のコード
``` javascript
db.Item.find({}, {used: true}).forEach(function(doc) {
    var used = doc.used || {};
    var items = Object.keys(used);
    var len = items.length;
    var count = 0;
    for (var i = 0; i < len; i++) {
        var code = items[i];
        count += used[code].count || 1;
    }

    print(doc._id + ',' + count);
});
```
## aggregateを使ったコード
``` javascript
db.Item.aggregate([
    {$match: {used: {$exists: true}}},
    {$project: {usd: {$objectToArray: '$used'}}},
    {$unwind: '$usd'},
    {$project: {usdLen: {$ifNull: ['$usd.v.count', 1]}}},
    {$group: {_id: '$_id', count: {$sum: '$usdLen'}}},
    ],
    {allowDiskUse: true}
    ).forEach((doc) => {
        printjson(doc);
});
```

# 実行時間
上記のコードをそれぞれ`extract.js`として保存し、timeコマンドで計測してみた
`time mongo ${HOST}:${PORT}/${DB} extract.js > result.txt`
## 普通のコード
```
real    1555m5.464s
user    1550m3.492s
sys     1m0.109s
```
## aggregateを使ったコード
```
real    57m14.554s
user    6m7.054s
sys     0m25.907s
```
# 解説
aggregateに配列で渡すOperatorを順番に実行する。
JavaのStreamAPI的なやつ

``` javascript
db.Item.aggregate([
    {$match: {used: {$exists: true}}},    // usedが存在するものだけピックアップ
    {$project: {usd: {$objectToArray: '$used'}}},    // usdにusedをArrayにしたものを詰める
    {$unwind: '$usd'},    // usdをunwindする(下記参照)
    {$project: {usdLen: {$ifNull: ['$usd.v.count', 1]}}},    // usd.v.countがnullであれば1を、nullでなければusd.v.countをusdLenに入れる
    {$group: {_id: '$_id', count: {$sum: '$usdLen'}}},    // _idが同じものを集約する、countにはusdLenを合計したものを入れる
    ],
    {allowDiskUse: true}    // メモリだけで集計すると死ぬことがあるのでtmpファイルを作成することを許可
    ).forEach((doc) => {
        printjson(doc);
});
```

## $unwind
配列を展開して複数のオブジェクトにしてくれる
これが

```json
[
    {
        "name": "team1"
        "member": ["suzuki", "sato"]
    },
    {
        "name": "team2",
        "member": ["tanaka"]
    }
]
```
↓こうなる

```json
[
    {"name":"team1", "member": "suzuki" },
    {"name":"team1", "member": "sato" },
    {"name":"team2", "member": "tanaka" }
]
```
# 考察
DBサーバとMongoShellを動かしてるサーバのスペックの違いな気がする
環境変数を設定してPHPファイルをコマンドラインから実行する方法



PHPファイルをコマンドラインから実行する際、環境ごとに動作を変えるために変数を設定する。

バッチ処理などの開発で多用するのでメモ。

#シェル変数に設定

```ex)
ENV=master php index.php
```

`ENV=master`と書くことで、シェル変数を設定できる。
シェル変数とは、そのプロセスのみ有効な変数。


ちなみにPHPで変数の取得方法はこちら

```php:index.php
$env = getenv("ENV");

//これでも取れる
$env = $_SERVER["ENV"];
```

#コマンドプロンプトの場合は？
上記の環境変数の設定方法はLinuxコマンドなので、コマンドプロンプトだとエラーがでる。

コマンドプロンプトの場合は、こちら。

```
set ENV=master&php index.php
```

コマンドプロンプトでは```set```　を使用することで、環境変数の設定が可能。



かつコマンドを複数同時に実行するときは```&``` でつなげてやる必要がある。

プロセスごとの変数はどうやって設定するのか？そのあたりの理解がまだまだ足りない。
gradleプロジェクトの時IntelliJのコンソールが文字化けする

自宅WindowsのIntelliJで発生。
会社でも同じようにIntelliJを使っているのだがそちらはちゃんと変換される。

```java:Hoge.java
public class Hoge {
    public static void main(String[] args) {
        System.out.println("あああ");
    }
}
```

```:実行結果
あああ

プロセスは終了コード 0 で完了しました
```
## ちゃんと動く方の情報
変換できている方の設定関連を調べてみた。

### バージョン情報
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298626/f00707ae-6ad3-c5aa-80c7-4993e2b4896c.png)

### IntelliJ設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298626/d174a78f-1f20-c9c6-dc88-396de88d7c4c.png)

### カスタムVM

```:.IdeaIC2019.1/config/idea64.exe.vmoptions
# Custom VM options (Generated by Pleiades Installer)
# See https://pleiades.io/pages/pleiades_jetbrains_manual.html
#-Xms128m
#-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
-Xverify:none
-javaagent:C:\Users\*******\.IdeaIC2019.1\config\jp.sourceforge.mergedoc.pleiades\pleiades.jar
-Dconsole.encoding=UTF-8
-Dfile.encoding=UTF-8
```

### 設定ファイルらしきモノ

`JetBrains\IntelliJ IDEA Community Edition 2019.1.2\bin\idea64.exe.vmoptions`

```:bin\idea64.exe.vmoptions
-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseConcMarkSweepGC
-XX:SoftRefLRUPolicyMSPerMB=50
-ea
-Dsun.io.useCanonCaches=false
-Djava.net.preferIPv4Stack=true
-Djdk.http.auth.tunneling.disabledSchemes=""
-XX:+HeapDumpOnOutOfMemoryError
-XX:-OmitStackTraceInFastThrow
```

### 調べる
ユーザフォルダに何やら怪しそうなやつがいる。
`C:\Users\*****\.IdeaIC2019.1\config`

キャッシュの削除も検討する。
[Qiita - IntelliJ Ideaのキャッシュを消す方法](https://qiita.com/kmdsbng/items/705b8637b9b367040b01)

### 試した結果
ここまでやってもだめ。
なんで？？？同じじゃん。

### ビルド方法が違った
ふとコンソールに目をやると

```
> Task :compileJava
> Task :processResources NO-SOURCE
> Task :classes
…
```

こんなのが出力されていた。
（これgradleプロジェクトで作ったなあ…。会社のは普通のプロジェクトだったなあ…。）

ググってみたら以下のサイトにあたった。
[Gradleで文字エンコーディングを指定する方法](http://nobeans.hatenablog.com/entry/20091104/1257344503)

**build.gradle**に以下を追記。

```gradle:build.gradle
plugins {
    id 'java'
}

group 'com_tutorial'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    // https://mvnrepository.com/artifact/org.projectlombok/lombok
    compile group: 'org.projectlombok', name: 'lombok', version: '1.18.8'

    testCompile group: 'junit', name: 'junit', version: '4.12'
}

// 以下の行を記載
tasks.withType(AbstractCompile)*.options*.encoding = tasks.withType(GroovyCompile)*.groovyOptions*.encoding = 'UTF-8'
```

ビンゴ。変換された！

```:実行結果
あああ

プロセスは終了コード 0 で完了しました
```


### 参考になりそうなリンク集
~~結局全部違ったけど。~~

IntelliJ IDEA でコンソールのTomcatログが文字化けしたときに設定した3点
https://qiita.com/qurage/items/cb57bb9c942e55ed06d1

intellij-ideaのコンソールでの文字化けの原因について
https://ja.stackoverflow.com/questions/42721/intellij-idea%E3%81%AE%E3%82%B3%E3%83%B3%E3%82%BD%E3%83%BC%E3%83%AB%E3%81%A7%E3%81%AE%E6%96%87%E5%AD%97%E5%8C%96%E3%81%91%E3%81%AE%E5%8E%9F%E5%9B%A0%E3%81%AB%E3%81%A4%E3%81%84%E3%81%A6

公式ヘルプ
https://pleiades.io/help/idea/configuring-individual-file-encoding.html
レポート（応用数学）

第１章：線形代数
・固有値、固有ベクトルの求め方
行列Ａに対して、Ａｘ＝λｘ（λ：スカラー）となるようなλとｘを求め、λを固有値、ｘを固有ベクトルという。
求め方は、上記から、（Ａ－λＩ）ｘ＝０　（Ｉ：単位行列）であるから、Ａ－λＩ＝０のを展開して、二次方程式から解λを求める。λを代入して、固有ベクトルｘを求める。
固有値を対角線上に並べて作った正方形の行列Ａと、それに対応する固有ベクトルｘ並べた行列Ｖは、ＡＶ＝ＶＡ　となり、両辺の右側からＶの逆行列Ｖ－１を掛けると左辺は、ＡＩ＝Ａ　となり、右辺は、ＶＡＶ－１と表される。

・特異値、特異値分解、特異値ベクトルの求め方
行列Ｍが正方形の行列で無い場合に、Ｍu＝σu、ＭＴv＝σuと表せる場合、特異値、特異ベクトルを求めることができる。

第２章：確率・統計
・条件付き確率：ある条件の下で関係する事象が発生する確率。
・独立な事象の同時確率：全く関係性の無い複数の事象が同時に発生する確率。
・ベイズ則：事象Ａが発生する確率の異なる複数のケース（例えば，X,Y,Z）がある場合、事象Ａが発生した場合、Ｘ、Ｙ、Ｚのどのケースで発生したか推定する確率。
・確率変数、確率分布：各事象を単に数値で表したものを確率変数とし、その事象が発生する確率を確率分布とする。
・期待値：確率変数と確率分布を掛けた値の総和で、最も確率の高い確率変数の値。
・分散：各データが期待値がらどのくらい離れているかを表している。期待値からの距離を平均した値なので、値を二乗している。
・共分散：２つのデータの塊の関連性を表すもので、全体の期待値から、各々の期待値の積を引いた値で求める。その値が、０は無相関（関係性が無い）の状態であり、正の値だと両者は似た関係にあり、負の値だと逆の関係にあると表す。

第３章：情報理論
・自己情報量：発生する確率が小さい場合に、大きい値をとり、表すべき事象の数（ビット数）を示すために、底が２のＬｏｇをとっている。
・シャノンエントロピー：自己情報量の期待値（平均値）で表す。
・カルバック　ライブラー　ダイバージェンス：ある事象が発生する期待値。２つの事象の違いを表す情報量の違いを表す。
・交差エントロピー：事象Ｐで関する確率を、事象Ｑ（確率分布の違いが分かったものと仮定して）の平均で表したもの。値が小さければ、両者の関係は近く、大きければ無関係に近い状態であると表せる。
Amazon Linux2にyumでMeCabが入らなかった

# はじめに

https://github.com/neologd/mecab-ipadic-neologd
の手順に従って、 Amazon Linux2にMeCabをインストールしようとしたところ、以下のエラーが発生しました。

```:実行したコマンド
$ sudo rpm -ivh http://packages.groonga.org/centos/groonga-release-1.1.0-1.noarch.rpm
$ sudo yum install mecab mecab-devel mecab-ipadic git make curl xz patch
```

```:エラーメッセージ
http://packages.groonga.org/centos/2/x86_64/repodata/repomd.xml: [Errno 14] HTTP Error 404 - Not Found
```


# 解決策
エラーメッセージ中のURLにAmazon Linuxのバージョン「2」が入っているっぽいのでCentOSの最新バージョンである「7」に変えてみます。

具体的には、`/etc/yum.repos.d/groonga.repo`の以下の部分を

```:/etc/yum.repos.d/groonga.repo
baseurl=http://packages.groonga.org/centos/$releasever/$basearch/
```

以下のように変えました。

```:/etc/yum.repos.d/groonga.repo（更新後）
baseurl=http://packages.groonga.org/centos/7/$basearch/
```

その後以下をもう一度実行するとエラーは出ず

```
$ sudo yum install mecab mecab-devel mecab-ipadic git make curl xz patch
```

MeCabも実行できました。

```
$ mecab
アデリーペンギンかわいい
アデリーペンギン        名詞,一般,*,*,*,*,*
かわいい        形容詞,自立,*,*,形容詞・イ段,基本形,かわいい,カワイイ,カワイイ
EOS
```


# おわりに
**これが正しい方法なのかはわかりません。**
ソースからビルドするのが無難だと思います。
Reactのchildren探訪

ReactのJSXでも子要素を定義できますが、これが結構面白いものでした。

## 自作エレメントにも子要素

ReactのJSXでは、（DOMを組み立てるものである以上当然ですが）`<div>`の中に`<a>`を書いて、そしてさらに文字列を書き込む、ということが可能です。

そして、これはHTML由来のエレメントだけでなく、自作のコンポーネントでも実現可能です。

```jsx
function SomeWrapper({children}) {
  return(
    <div className="some-class">
      { children }
    </div>
  );
}
```

このように、子要素は`children`というPropとして渡ってきます。

## `children`の中身が知りたくて

では、この`children`には何がどのような形式で来るのでしょうか。JSXの変換先である`React.createElement`の[ソースコード](https://github.com/facebook/react/blob/824e9bec7a3f5aa290e5f4e7d7ad52261a7c5d40/packages/react/src/ReactElement.js#L338)に当たってみました。挙動は`children`の数によって違います。

* 0個…`children`には`prop`として渡した`children`が（もしあれば）渡される
* 1個…`children`には唯一の`children`引数が**そのまま**渡される[^1]
* 2個以上…`children`には引数で渡されたものが**配列**に詰め込まれる

[^1]: `Context.Consumer`などで子要素代わりにコールバックを書くことがありますが、1個なので関数がそのまま`children`に入る形となっています。

## 公式な操作方法

現実問題として、今から`children`の実装を変えてしまうということは互換性問題などを考えれば可能性は薄いのですが、公式には`children`のデータ形式は「非公開」ということになっています。そこで、`children`を操作するための`React.Children`というユーティリティ関数群があります（[リファレンス](https://ja.reactjs.org/docs/react-api.html#reactchildren)）。

* `React.Children.map`…`children`の各要素に対して関数を実行して、結果を配列で得る。
* `React.Children.forEach`…`children`の各要素に対して関数を実行する。
* `React.Children.count`…`children`の個数を返す
* `React.Children.toArray`…`children`を本物の配列に変換して返す
* `React.Children.only`…`children`が1つのJSXエレメントであることを保証する

なお、`forEach`、`map`、`toArray`で処理する際に、キーは子要素間で一意となるようなものがReact側で振られます。また、子要素として`<React.Fragment>`を渡した場合、1つものとして扱われます。

## `children`と`React.memo`

今のところ、`React.createElement`をキャッシュするような仕組みはないので、`<br />`のようなシンプルなJSX要素であっても、2回の実行でオブジェクトとして一致することはありません。さらに、上述のように複数の子要素をもたせた場合、`children`の配列を生成しますので、このインスタンスも一致しません。

そして、`PureComponent`や`React.memo`は`children`を特別扱いしませんので、（文字列1つだけ指定するような例外的なケースは別として）`children`を指定するようなコンポーネントでは、メモ化は利かないということになってしまいます。

対策としては、

* 子要素を取るコンポーネントを使う側の場合、「コンポーネント+子要素」全体を1つのコンポーネントとして、それをメモ化する
* 子要素を取るコンポーネントを作る場合、メモ化を諦める

などが考えられます。そして、`children`以外でも、表示する文字列をpropで取る場合に、「HTMLタグで装飾したい」とその場で書いたJSXを渡せば同じ事態となります。こちらについては、`React.useMemo`、クラスのプロパティ、外側で変数に定義するなど、同じJSXインスタンスを使い回す形として対応が可能かと思います。
Python bool() の中で何が起こっているか

組み込み関数の1つ、`bool()`
引数として渡されたオブジェクトの真偽値を返却します。

# 中で何が起こっているか確認する

オブジェクトの真偽値はどうやって決まるのでしょうか？
公式リファレンスによると
https://docs.python.org/ja/3/library/stdtypes.html#truth
> オブジェクトは、デフォルトでは真と判定されます。ただしそのクラスが `__bool__()` メソッドを定義していて、それが False を返す場合、または `__len__()` メソッドを定義していて、それが 0 を返す場合は偽と判定されます。

だそうです。試してみます。

```python
# __bool__() __len__()を定義している場合
>>> class Class1:
...     def __bool__(self):
...         print('__bool__が呼ばれたよ')
...         return False
...     def __len__(self):
...         print('__len__が呼ばれたよ')
...         return 0
...
>>> hoge = Class1()
>>> bool(hoge)
__bool__が呼ばれたよ
False

# __bool__()が定義されていない場合
>>> class Class2:
...     def __len__(self):
...         print('__len__が呼ばれたよ')
...         return 0
...
>>> piyo = Class2()
>>> bool(piyo)
__len__が呼ばれたよ
False

# __bool__()__len__()が定義されていない場合
>>> class Class3():
...     pass
>>> fuga = Class3()
# デフォルトどおり真が返る
>>> bool(fuga)
True
```

# 応用してみる

組み込み型のクラスであれば`__bool__()`か`__len__()`のどちらかは定義されています。
組み込み型を継承して自作クラスをつくる場合はこれらの特殊メソッドをオーバーライドできます。
例えば↓こんな感じ

```python
# 通常のリストの場合、要素が1つ以上あれば真になる
>>> list = list([0])
>>> bool(list)
True
# 要素それぞれの真偽値判定をし、真になるものが1つ以上あれば真を返す
>>> class MyList(list):
...     def __bool__(self):
...         return any(self)
...
>>> my_list = MyList([0])
>>> bool(my_list)
False
```
`bool()`の中で何が起こっているか理解していると、こういったアレンジができちゃいます。
（特殊メソッドをオーバーライドすると影響範囲が大きくなるので、やるときは慎重に！）
cron-job.orgを使ってHerokuの無料プランのスリープを無くした話

## cron-job.orgを使ってHerokuの無料プランのスリープを無くした話
HerokuのDynoは無料プランでは30分間のinactivityでスリープ状態になります。

僕が運営している[スクールレポート](https://school-report.com/)はHerokuの無料プランで稼働しているのですが、スリープ状態になることは避けたいです。
そのために、cron-job.orgを利用して、１５分毎にリクエストを送っています。
リンクはこちらです。 https://cron-job.org/ 

cron-job.orgは完全無料で使えるので、HerokuのDynoをスリープさせたくない場合はおすすめです。

注意点としては、cron-job.orgはレスポンスサイズが少しでも大きいと動作を停止してしまうことです。

この問題には、次のように対策しました。
まず、サーバーで0Bの空ファイルを配信するようにします。
そして、cron-job.orgのリクエスト先をその空ファイルに向けます。
これで設定は完了です。

この記事が参考になれば幸いです。
## 終わりに
私は現在、Web3のサービスの開発をしています。詳しくはこちらの記事をご覧下さい。
        [無料でイーサリアムが当たる、Web3時代の寄付サイトを作った話](https://note.com/kenroda/n/n814347fbdcd7)
選挙の演説の候補者の計算【ruby初心者】

#はじめに

演説が終わるたび「他のそれぞれの立候補者の支持者から 1 人ずつ」および「誰も支持していない有権者から 1 人」支持者が増える。
その場合、最終結果で一番多い支持を集めた立候補者の番号を取得する。

#実際のコード

```
#M は立候補者の人数を、N は有権者の人数を、K は演説が行われる回数
m,n,k = gets.split(" ").map &:to_i

#誰がどの順番で演説したかを表す整数 a_1, ..., a_K
a = readlines.map &:to_i

#立候補者の人数に応じて、支持者の人数を図れる配列を用紙
r=[]
m.times {r.push(0)}

#すべての演説が終わった後、最も支持者が多い立候補者の番号(複数ある場合は、すべて出力)
a.each do |i|
    #誰も支持していない人が、指示をする
    if n >0
        n -= 1
        r[i-1] += 1
    end
    #他の人を支持している人が、指示をする
    r.count.times do |t|
        if r[t] >0
            r[t] -= 1
            r[i-1] += 1
        end
    end
end

#最大数を返す
r.each_index do |t|
    if r[t] == r.max
        puts t+1
    end
end
```
ASP.NET CoreをUbuntu18.04 LTSで動かしてみたよ～

# はじめに
Microsoftが最近オープンソースに力を入れている。
元々VisualStudioが好きな僕が「そうだ！ASP.NET Coreを使ってみよう」と奮い立ってみた。
※いつもはJavascriptとPerl使いです。Tengラブ。

# .NET Core SDKインストール

## インストール参考
https://dotnet.microsoft.com/download/linux-package-manager/ubuntu18-04/sdk-current

## インストール手順
```
$ wget -q https://packages.microsoft.com/config/ubuntu/18.04/packages-microsoft-prod.deb
$ sudo dpkg -i packages-microsoft-prod.deb
$ sudo add-apt-repository universe
$ sudo apt install apt-transport-https
$ sudo apt update
```


# ASP.NET Coreサンプルを用意

VisualStudio2019を起動し、ASP.NET Coreのサンプルプロジェクトを作成して、ビルド。
Debug配下またはRelease配下のファイル達をUbuntuに転送。

```
$ sudo mkdir /var/webapp/
$ sudo mv /home/hoge/asp_net_app /var/webapp/
```

# 実行してみる

```
$ dotnet /var/webapp/asp_net_app/hoge.dll

Unable to start Kestrel.
System.InvalidOperationException: Unable to configure HTTPS endpoint. No server certificate was specified, and the default developer certificate could not be found.
```

エラー。。
調べてみるとhttps接続でなければならないらしく、オレオレ証明書を作って入れる。

# オレオレ証明書の作成

参考 - ASP.NET CoreでHTTPSエラーが発生する現象の対処方法
https://www.aruse.net/entry/2018/10/05/204120

```
$ openssl genrsa 2024 > server.key
```

証明書署名要求(CSR / Certificate Signing Request)を作成します。

```
$ openssl req -new -key server.key > server.csr

Country Name (2 letter code) []:
State or Province Name (full name) []:
Locality Name (eg, city) []:
Organization Name (eg, company) []:
Organizational Unit Name (eg, section) []:
Common Name (eg, fully qualified host name) []:localhost
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: password
```

サーバー証明書を作成します。

ここでは有効期限を10年(3650日)としています。

```
$ openssl x509 -req -days 3650 -signkey server.key < server.csr > server.crt
```

サーバー証明書を crt 形式（と秘密鍵）から pfx 形式に変換します。パスワードは"password"と設定しています。

```
$ openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt
Enter Export Password:
Verifying - Enter Export Password:
```

そして、ASP.NET MVC プロジェクトの Program.cs を以下のように修正します。

```CS
//追加
using System.Net;

//(中略)

    public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
        WebHost.CreateDefaultBuilder(args)
            .UseKestrel(options =>
            {
                options.Listen(IPAddress.Loopback, 5000);
                options.Listen(IPAddress.Loopback, 5001, listenOptions =>
                {
                    listenOptions.UseHttps("server.pfx","password");
                });
            })  
            .UseStartup<Startup>();
```
Spring Securityがアクセスをはねると@ExceptionHandlerで処理できない話（だがSpring Bootは処理する）

# はじめに

最近Springに触れる機会がありました。Javaなんて5より前の時代でしかまともにプログラム書いたことない化石なのでアノテーションとかメソッドチェーンとか[^1]「現代的なJava」をQiitaの先人方の記事を参考に習得させていただきました。

[^1]: JUnit4は見たことあるのでアノテーションをばりばり使ったプログラミングについてはそこそこ知見がありました。

で、作ろうとしたシステムですが以下のような感じです。

- ユーザ認証を行う。これはSpring Security使えばよいようだ。
- ロールも使って特定ページには管理者しかアクセスできないようにする。
- エラーページはSpring Bootが出してるようだけどデフォルトのままじゃもちろん駄目なのでエラーハンドリングを行う。

で、最後のエラーハンドリングの方法を調べたところ`@ExceptionHandler`アノテーションを付ければいいということがわかりました。というところまでが前置き。

なお今から説明するコード（状況再現コード）の全体はgithubに置いときました。
https://github.com/junjis0203/spring-security-boot-error-example

# とりあえず`@ExceptionHandler`使ってみる

`@ExceptionHandler`アノテーション付けて、戻り値はStringでビュー名返すようにしてました。

```java:CommonControllerAdvice.java
	@ExceptionHandler
	@ResponseStatus(code = HttpStatus.INTERNAL_SERVER_ERROR)
	public String handle(Exception e) {
		logger.error(e.toString());
		return "error";
	}
```

管理者権限与えてないユーザでアクセスして、ちゃんと返してるビューが表示されていることを確認。

![handle-error.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/141091/640ecfa0-db19-3b1d-1965-ee4d78c83e56.jpeg)

さてExceptionと大味に捕まえてしまったが実際どの例外が・・・
あれ？(。´･ω･)?ログが出てない。ログ設定おかしいのかな。

# Spring Security「わいやで」

？？？「一体いつから、エラーハンドリングできていると錯覚していた」
さわだ「お前は！？」

Spring Security「そのリクエストは私がフィルタした。つまり、コントローラには届いていない」
さわだ「な、なんだってー！では何故自分で書いたビューが表示されるのだ」

# Spring Boot「わいやで」

Spring Boot「あ、それやってるのわい」
さわだ「え？」
Spring Boot「[ここ](https://docs.spring.io/spring-boot/docs/2.1.6.RELEASE/reference/html/boot-features-developing-web-applications.html#boot-features-error-handling)に書いてあるで。ざっくり訳すと、サーブレットコンテナのグローバルなエラーページとして登録されてます、となる。つまり、Spring Securityはんがはねたエラーでもわいはハンドリングできるんや」
さわだ「error.html使うなんて書いてないぞ」
Spring Boot「[ソースコード](https://github.com/spring-projects/spring-boot/blob/v2.1.6.RELEASE/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/servlet/error/BasicErrorController.java#L91)参照」

# 解決策

というわけで、Spring Securityを使ってアクセス制御したところ、権限エラーを捕まえることができない、しかしSpring Bootは捕まえられるということがわかりました。
私としては「何故権限エラーがハンドリングされないのか」と「何故ハンドリングされてないのに自分で書いたページが表示されるのか」さえ明確になればよかったので`error/403.html`を置いてアクセス権がないことを知らせるようにしました。

# あとがき

ちょっと前に書いたSinatraの話など、個人的に「プログラミング記法」に関する話題は大好きなのでその点Springはとてもおもしろいですね。
また、「でこれ結局どうやって動いてるの？」とコードを読むのも大好きなのですが、Springの森は深過ぎですね。本体にたどり着く前にインターフェースと抽象クラスが何個あることか。でも別件でソース探索を少ししておいたおかげで今回のBasicErrorControllerへは比較的早くたどり着くことができました(笑)
phpunit.xmlの設定が反映されない

## 問題：phpunit.xmlが反映されない
```xml
        <env name="APP_ENV" value="testing" />
```
Laravelの開発で phpunit.xml の環境名の上書きを下記のテストで確認したところ、反映されませんでした。

tests\Unit\DemoTest.php

```php
use Tests\TestCase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Foundation\Testing\RefreshDatabase;

class DemoTest extends TestCase
{
    /**
     * @test
     */
    public function 環境確認()
    {
        $this->assertEquals('testing', $this->app->environment());
    }
}
```

```
   │ Failed asserting that two strings are equal.
   │ --- Expected
   │ +++ Actual
   │ @@ @@
   │ -'testing'
   │ +'local'
   │
   │ /home/vagrant/code/demo-vue-practice/tests/Unit/DemoTest.php
   │

Time: 2.09 seconds, Memory: 16.00 MB
```

## 解決策： force=trueを設定
https://stackoverflow.com/questions/45922358/why-phpunit-is-not-getting-the-correct-app-env-as-specified-in-phpunit-xml

```xml
        <env name="APP_ENV" value="testing"  force="true"/>
```

また`php artisan config:clear`も行う必要がありそうでした。
https://stackoverflow.com/questions/48227569/failure-to-set-app-env-to-testing-for-unit-testing-in-laravel-5-5


これで先のテストが通りました。

```
Unit\DemoTest
 ✔ 環境確認

Time: 2.07 seconds, Memory: 16.00 MB

```

以上です。
FirebaseAuthでOAuth2.0を使ったアプリをGoogle Play Storeにリリースする際はまった件

少し前から、GooglePlayStoreでアプリ内課金を使ったアプリを個人的にリリースすべく作業をしていまして、初めて扱うKotlinやGoogle Purchasesなどでいくつか記事を投稿させてもらいました。

https://qiita.com/taedookim/items/a4280ed9d66288c24b51
https://qiita.com/taedookim/items/698982a89f97e3576544
https://qiita.com/taedookim/items/66cdfcad526b33fd03e2

そんなわけで四苦八苦していたアプリが、一応基本的な動作については問題なく動くところまで来ましたので、リリース手続きをしまして、いざ公開！となったところで躓いたお話です。

先に結論から言いますと、FirebaseAuthというよりはそこで利用しているGoogle Sign-InやFacebook Loginの要件が満たせていなかった、ということだったのですが、開発作業を進めている中ではいろいろと気づかないまま進んでしまった結果見落としていたポイントでしたので、自戒も込めて書かせていただきます。

## やっていたこと

上記の通り、アプリではGoogle Play Storeのアプリ内課金を利用する想定でいたため、ユーザー管理のため、Firebaseを使おうと考えて実装を進めていました。
何分個人アプリなのであまりユーザー管理などに運用の労力は裂きたくないなというのが正直なところでして、OAuthを使い、GoogleアカウントやFacebookアカウントを使ってログインしてもらい、ユーザー識別だけできればいいや、と考えていたのが発端です。

実装の対応としては、FirebaseAuthの公式ドキュメントを参考にしていました。

https://firebase.google.com/docs/auth/android/firebaseui?hl=ja

UIまで用意されているし、簡単に実装できるものなんだなぁ～と思いながら、公式ドキュメントの指示に従い、FirebaseConsoleの設定を行って比較的開発初期の段階で無事、ログインできるようになり、課金などのアプリ部分の実装へ。
すべてが整って、いざリリース手続きということで、クローズドテストを設定したところ、Play Storeからダウンロードしたアプリでは、サインインに失敗する、という事象が起きました。

## 確認したこと

開発環境から直接端末にインストールして実行するとやはり正常にサインイン可能。
ということで、何が違うんだ？？と、PlayStoreからインストールしたバイナリを実行している端末をPCにつないでLogを確認したところ、サインインを実行したところで以下のようなエラーが出ていました。（エラーメッセージ自体は消してしまったのですが、検索時に見つけたサイトに記載されていた内容からの抜粋でこんな感じのメッセージだったはずです）

```
com.google.android.gms.common.api.ApiException: 10:
```

GoogleからAPIエラーが出ているというのはわかりましたが、10というエラーコードの意味がわからず検索してみたところ
https://stackoverflow.com/questions/47437678/why-do-i-get-com-google-android-gms-common-api-apiexception-10
このページに行き着きました。

ページ内に記載のアドバイスに従い、今度はFirebaseUIではなく、GCPのコンソール上で各種環境設定を行い、Google Sign-Inを使ってみるが、やはり同様に開発環境ではOKなのにPlay Store経由になるとNG。
続いて、Firebaseと連動させていたFacebookを使って実装してみましたがそれでも事象は解消されず。

ここまで来てふと、GCPのコンソールをよく見て気づいたのが、ドメインの承認に関する項目。

![authenticate.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/45794/df1c5816-bb54-8585-c0d7-7ea3790d21c6.jpeg)

OAuth同意画面の項目にあるこれらの項目ですが、一番下の「アプリケーション利用規約リンク」の欄には *（省略可）* とあるのに、その上2か所、アプリケーションホームページリンクとアプリケーションプライバシーポリシーリンクの欄には、その文言がありませんでした。

ここにきてようやく「あ！もしかしてこれ、専用ドメインのWebサイトが必要なんじゃ？！」という初歩的なことに気づいたのでした…

## 対処方法

今回のアプリでは、FirebaseとGoogle Play課金機能の実装を試したいというのが主目的で、個人でやっているということもあり、特にサービスサイトなどは作成は予定していませんでした。
よくよく考えてみたら、こんな怪しいサービス提供者に各SNSのアカウントを利用させるって、結構リスクが高いことだよなぁ～ということで、どう考えてもセキュリティ的にNGか。ときっぱり諦めまして、Firebaseで提供されている、Email認証を採用することにしました。

そもそもEmail認証を採用しなかった理由としては、先ほど書いた、アカウントはあくまで識別できればよくてこちらで管理をするためのコストをかけたくないな、という点と、アカウント認証できたほうがユーザーにとって便利だろう、という2点でした。
ただ、いざEmail認証を実装してみると、そもそもEmailの初期値として実行中のAndroid端末に登録されているGoogleアカウントのメールアドレスが入力候補として表示され自動入力できますし、パスワードだけ登録する必要はありましたがそのパスワードもSmart Linkで自動的に記録されて、ユーザーの手間暇はほとんどなアカウント認証と変わらないな～というのが実感でした。

ということで、各種APIを使うならともかく、アプリ内で最低限のユーザー識別さえできればいい、ということであれば、Email認証で十分だし、最初からこれを採用していればよかったな…というお話でした。

同じような境遇になる人はあまりいない気もします（大体は業務で開発した場合は、きちんとサービスサイトは用意されると思いますし…）が、もし、これからアプリ開発をするのに、どういう認証方法を選ぼうか、ということを考えている人がいましたら、併せて「何をやらなきゃいけないか」を認識するのに一助となれば幸いです。
NiFi1.8からNiFi1.9にアップグレードのメモ

一つのAmbariでHDP３．１とHDF3.3（NiFiだけを使っている）のクラスタを管理しています。NiFi1.8のPutHive3Streaming関連のメモリリークのバグがあるらしく、一定時間経つとをJVM OOMエラーを起こしてしまいます。

There are unfortunately 2 memory leaks around this processor: 
one in the NiFi processor that was fixed in 1.9.0: 
https://issues.apache.org/jira/browse/NIFI-5841
and one in the Hive client library, 
https://issues.apache.org/jira/browse/HIVE-20979

そこでAmbariとHDP3.1のコンポーネントのバージョンはそのまま、HDF3.3.0（NiFi1.8）からHDF3.4.1.1（NiFi1.9）へのアップグレードを試してみました。

手順は概ねこちらになります

NiFiなど関連コンポーネント停止
https://docs.hortonworks.com/HDPDocuments/HDF3/HDF-3.4.1.1/ambari-managed-hdf-upgrade/content/hdf-stop-hdf-services.html

HDFのManagement Packをアップグレード
https://docs.hortonworks.com/HDPDocuments/HDF3/HDF-3.4.1.1/ambari-managed-hdf-upgrade/content/upgrade-mpack-hdf-on-hdp.html
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110403/c44e4741-5abd-b705-c634-e7cab5447e0c.png)
手順７の中のHDF-3.4が書いてありますが、実際のところはHDF-3.4が存在していない、設定できないことになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110403/a2e4c06d-cafc-bc2e-1e2c-be917661ea0d.png)

新しいバージョンを作る事も考えたのですが、バージョンの名前が共存できないため、新しい作ると、HDPのバージョンも合わせて変わってくるため、ちょっと危険の匂いがするので、やめておきました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110403/9d2f82d1-b04d-5d8c-8ef0-c14b06cfca15.png)

そこで新しいバージョンのNiFiを手動で各サーバーでインストールしました。
上の手順８のところ、各ノードに以下を追加

```
path=/
enabled=1
gpgcheck=0
[HDF-3.4-repo-1]
name=HDF-3.4-repo-1
baseurl=http://public-repo-1.hortonworks.com/HDF/centos7/3.x/updates/3.4.1.1
```

次に、インストール。今回はNiFiとNiFI-toolkitだけ

```
yum install -y nifi_3_4_1_1_4
yum install -y nifi_3_4_1_1_4-toolkit
```
インストールされていることを確認
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110403/35d9d0be-8412-71b9-b731-3723e16f05e9.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110403/96f9d703-0b17-acb6-18b8-e076f8642b16.png)

/usr/hdf/の下に２つバージョンのHDFが存在しています
シンボリックリンクは古いバージョンのままになっています。
以下を実行して、シンボリックリンクを変更します(直接変更してもいいですが。。）

```
hdf-select set nifi 3.4.1.1-4
hdf-select set nifi-toolkit 3.4.1.1-4
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110403/5fac1695-1531-2612-a43c-d3245898f864.png)

最後にAmbariからnifi.propertiesに以下のプロパティを追加する

```
nifi.nar.library.autoload.directory = {{nifi_internal_dir}}/work/extensions
```


この状態でAmbariからNiFiを起動する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110403/b01a3179-9730-6970-006d-d590ba090470.png)

成功した！！