OmniAICreator/Qiita-1.07M huggingface dataset:
言語処理100本ノック-95(pandas使用):WordSimilarity-353での評価

[言語処理100本ノック 2015](http://www.cl.ecei.tohoku.ac.jp/nlp100/)の95本目「WordSimilarity-353での評価」の記録です。
前のノック結果に対して**スピアマン相関係数**を計算します。自作プログラムでの結果は約23%、Gensim使用時の結果は52%とこれまた大きく水をあけられています。

# 参考リンク

|リンク|備考|
|:--|:--|
|[095.WordSimilarity-353での評価.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/10.%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93%E6%B3%95%20(II)/095.WordSimilarity-353%E3%81%A7%E3%81%AE%E8%A9%95%E4%BE%A1.ipynb)|回答プログラムのGitHubリンク|
|[素人の言語処理100本ノック:95](http://qiita.com/segavvy/items/6181994f5667ee1fbebf)|言語処理100本ノックで常にお世話になっています|

# 環境

|種類|バージョン|内容|
|:--|:--|:--|
|OS|Ubuntu18.04.01 LTS|仮想で動かしています|
|pyenv|1.2.15|複数Python環境を使うことがあるのでpyenv使っています|
|Python|3.6.9|pyenv上でpython3.6.9を使っています<br>3.7や3.8系を使っていないことに深い理由はありません<br>パッケージはvenvを使って管理しています|

上記環境で、以下のPython追加パッケージを使っています。通常のpipでインストールするだけです。

|種類|バージョン|
|:--|:--|
|pandas|0.25.3|

# 課題
## [第10章: ベクトル空間法 (II)](http://www.cl.ecei.tohoku.ac.jp/nlp100/#ch10)
> 第10章では，前章に引き続き単語ベクトルの学習に取り組む．

### 95. WordSimilarity-353での評価
> 94で作ったデータを用い，各モデルが出力する類似度のランキングと，人間の類似度判定のランキングの間のスピアマン相関係数を計算せよ．

#### 課題補足(スピアマン相関係数)
「スピアマン相関係数」は**[「スピアマンの順位相関係数(Spearman's rank correlation coefficient
)」](https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%94%E3%82%A2%E3%83%9E%E3%83%B3%E3%81%AE%E9%A0%86%E4%BD%8D%E7%9B%B8%E9%96%A2%E4%BF%82%E6%95%B0)**のことで、順位を使った相関係数です。よく耳にする[「ピアソンの積率相関係数」](https://ja.wikipedia.org/wiki/%E3%83%94%E3%82%A2%E3%82%BD%E3%83%B3%E3%81%AE%E7%A9%8D%E7%8E%87%E7%9B%B8%E9%96%A2%E4%BF%82%E6%95%B0)は、順位ではなく値を使って相関係数を出します。
どちらも1から-1までの範囲で値をとり、1だと正の相関が強いという意味です。

# 回答
## 回答プログラム [095.WordSimilarity-353での評価.ipynb](https://github.com/YoheiFukuhara/nlp100/blob/master/10.%E3%83%99%E3%82%AF%E3%83%88%E3%83%AB%E7%A9%BA%E9%96%93%E6%B3%95%20(II)/095.WordSimilarity-353%E3%81%A7%E3%81%AE%E8%A9%95%E4%BE%A1.ipynb)

```python
import pandas as pd

def calc_corr(file):
    df = pd.read_table(file, header=None, usecols=[2, 3], names=['original', 'calculated'])
    print(df.corr(method='spearman'))

calc_corr('./094.combine_1.txt')

calc_corr('./094.combine_2.txt')
```

## 回答解説
pandas使っているのでコードは非常に短いです。関数`corr`のメソッドに`spearman`を指定してあげるだけです。

```python
print(df.corr(method='spearman'))
```

自作プログラムでの結果です。`original`と`calculated`の交わる部分が結果の値で、0.227916です。低いですね・・・

```bash
            original  calculated
original    1.000000    0.227916
calculated  0.227916    1.000000
```

Gensim使った場合の結果です。0.516526とだいぶ上がっています。

```bash
            original  calculated
original    1.000000    0.516526
calculated  0.516526    1.000000
```
Rustの関数の変数名の前のmut

以下の関数romの引数を「fn qom(r:&mut str)」のように書くとエラーになる  

```Rust
#[allow(unused_assignments)]
fn main() {
    let mut p = "dummy strings";
    p = "Pom";
    println!("{}", p);
    qom(&mut p)
}

#[allow(unused_assignments)]
fn qom(r:&mut str){
    r = "Pom in qom";
    println!("{} in qom",r);
}
```  

---エラー-----
error[E0308]: mismatched types
  --> src/main.rs:15:9
   |
15 |     r = "Pom in qom";
   |         ^^^^^^^^^^^^ types differ in mutability
   |
   = note: expected type `&mut str`
              found type `&'static str`
---エラー-----
しかし引数を「fn qom(mut r:&str)」のように書くとエラーにならない  

```Rust
#[allow(unused_assignments)]
fn main() {
    let mut p = "dummy strings";
    p = "Pom";
    println!("{}", p);
    qom(&mut p)
}

#[allow(unused_assignments)]
// 関数の引数のmutの位置ここでええんか？
fn qom(mut r:&str){
    r = "Pom in qom";
    println!("{} in qom",r);
}
```
関数の変数名の前のmutという書式がよくわからない
おんなじ疑問をもった人がいた。
 https://users.rust-lang.org/t/solved-placement-of-mut-in-function-parameters/19891

 「mut 変数名: 型」の場合、渡されたオブジェクトに対する可変な参照
（関数内の変数は変更できるが、渡されたオブジェクトは変更できない)

「変数名: &mut 型」の場合、渡された可変なオブジェクトに対する参照
（渡されたオブジェクト自身を変更できる）

###  「mut 変数名: 型」の例   
```Rust
fn main() {
    let pom = 4;
    println!("pom:{} [before test_fn]", pom);
    test_fn(pom);
    println!("pom:{} [after test_fn]", pom);
}

// 関数の引数の変数の前にmut
fn test_fn(mut pom:i32){
    println!("pom:{} [enter in test_fn]", pom);
    pom = 13;
    println!("pom:{} [changed in test_fn]",pom);
}
```
実行結果：
pom:4 [before test_fn]
pom:4 [enter in test_fn]
pom:13 [changed in test_fn]
pom:4 [after test_fn]

### 「変数名: &mut 型」の例
```Rust
fn main() {
    let mut pom = 4;
    println!("pom:{} [before test_fn]", pom);
    test_fn(&mut pom);
    println!("pom:{} [after test_fn]", pom);
}

// 関数の引数の型の前に&mut
fn test_fn(pom:&mut i32){
    println!("pom:{} [enter in test_fn]", pom);
    *pom = 13;
    println!("pom:{} [changed in test_fn]",pom);
}

```  
実行結果：
pom:4 [before test_fn]
pom:4 [enter in test_fn]
pom:13 [changed in test_fn]
pom:13 [after test_fn]
[React]どこからか受け取ったHTMLの文字列を、HTML要素として画面に表示しつつ、特定ワードでハイライトしたい

# 背景

開発中のシステムで、データベースにHTMLが入っているカラムがあり、それをAPIで取ってきて、Reactで表示するという構成の画面があります。
その画面にはHTML内の文字列を検索できる機能があり、「検索ワードをハイライトして表示できないか？」という相談を受けたので、実装しました。

(Google検索だと、ハイライトではなく太字になっていますが、やりたいことはこんな感じです)
![Screen Shot 2020-01-22 at 4.59.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174325/0ef7bd22-b8fa-c96e-f485-1cc15b80a592.png)

ただ文字列をハイライトするのはかんたんですが、HTMLとしてレンダリングしつつというところで少し悩んだので記事にしました。

# できたもの

だいたいこのような感じです。

![Jan-22-2020 05-30-59.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174325/958c1c0a-3132-16f6-1fa0-a6ed02ddb3f7.gif)

HTMLに対して、スペース区切りで文字を入力したら、入力された文字とマッチする箇所をハイライトします。

codesandboxに上げました。

[![Edit react-innerHTML-highlight-words](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/interesting-neumann-dntwc?fontsize=14&hidenavigation=1&theme=dark)

# ポイント

文字をハイライトさせるのには、react-highlight-wordsというパッケージが便利だったので使っています。
処理の流れは、

1. (HTMLのstring)HTMLをstateから受け取る
2. (React elementでstringをラップ)ハイライトしてくれるコンポーネントに突っ込む
3. (HTMLのstring)`react-dom/server`でサーバで一旦レンダリングする
4. (HTMLのstring)正規表現でHTMLタグをアンエスケープする
5. (React Element)dangerouslySetInnerHTMLというHTMLのstringをReactでHTML要素として表示できるプロパティに入れる

という感じです。
もしかしたらもっといいやり方があるかもですね。

HTMLタグのアンエスケープはこれでできます。

```js
    const unescapeHtml = string => {
      const patterns = {
        "&lt;": "<",
        "&gt;": ">",
        "&amp;": "&",
        "&quot;": '"',
        "&#x27;": "'",
        "&#x60;": "`"
      };

      const escapedString = string.replace(
        /&(lt|gt|amp|quot|#x27|#x60);/g,
        match => patterns[match]
      );

      return escapedString;
    };
```

# 注意

HTML内部のリンクとマッチするワードが入力されたら、HTMLがこわれます。
必要ならエスケープすることになります。
また、もととなるデータが、ユーザーが自由に入れることができるものである場合は、XSS対策などセキュリティ対策が必要です。
MySQLで挿入できるレコードの文字数制限を変更する方法

# ALTER文使おう
ALTER文を使ってテーブル構造の情報を変更してあげれば良い。

```
mysql> DESC {table_name};
+------------+---------------------+------+-----+---------+----------------+
| Field      | Type                | Null | Key | Default | Extra          |
+------------+---------------------+------+-----+---------+----------------+
| id         | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255)        | NO   |     | NULL    |                |
| contents   | varchar(255)        | NO   |     | NULL    |                |
| created_at | timestamp           | YES  |     | NULL    |                |
| updated_at | timestamp           | YES  |     | NULL    |                |
+------------+---------------------+------+-----+---------+----------------+
```
`contents`カラムを`varchar(2000)`にしたい。

```
mysql> ALTER TABLE {table_name} MODIFY COLUMN contents varchar(1000);
```

```
mysql> desc {table_name};
+------------+---------------------+------+-----+---------+----------------+
| Field      | Type                | Null | Key | Default | Extra          |
+------------+---------------------+------+-----+---------+----------------+
| id         | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| title      | varchar(255)        | NO   |     | NULL    |                |
| contents   | varchar(1000)       | YES  |     | NULL    |                |
| created_at | timestamp           | YES  |     | NULL    |                |
| updated_at | timestamp           | YES  |     | NULL    |                |
+------------+---------------------+------+-----+---------+----------------+
```

oh yeah~♪
Reactで行数可変なtextareaを作った話

#TL;DR
![タイトルなし.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283789/92cfb705-6649-ded0-6497-4109f4f350b5.gif)

**中身に応じて高さが変わるtextareaが出来た**
コピペ、複数行まとめて削除しても大丈夫

軽く検索しても出てこなかったので
似たようなことをしたくなった人や未来の自分のために書いてみました


#環境
react:15.6.2
redux-form:6.8.0
lodash.isempty:4.4.0

正直reactだけでもOKなはず
廃止されるライフサイクルメソッドなども使っていないので最新版のreactでも動くと思います

他２つは細かいところ書くのが面倒なので使ってます
無くても本質には関係ないので大丈夫です

chromeとIEで動作確認済み（バージョンはわからないですが2020/01付近です）

#参考
[textareaの大きさを自動調整](https://qiita.com/SoundRabbit/items/289dcb28fd4b0d101c97)

#実装
細かいところはフィーリングで読んでください

```jsx:index.js
import React from 'react';
import { Field, reduxForm } from 'redux-form';
import TextArea from './textArea';

function index() {
  return (
    <div>
      <Field name="TextArea" component={TextArea} rows={2} />
    </div>
  )
}

export default reduxForm({ form: 'form' })(index);
```

```jsx:textArea.js
import React, { Component } from 'react';
import isEmpty from 'lodash.isempty';

class TextArea extends Component {
  constructor(props) {
    super(props);
    this.textArea = null;
  }

  shouldComponentUpdate(nextProps) {
    if (this.props.input.value !== nextProps.input.value) {
      if (isEmpty(nextProps.input.value)) {
        this.textArea.setAttribute('rows', this.props.rows);
      } else {
        this.textArea.setAttribute('rows', this.props.rows);
        while (this.textArea.scrollHeight > this.textArea.offsetHeight) {
          const tempRows = Number(this.textArea.getAttribute('rows'));
          this.textArea.setAttribute('rows', tempRows + 1);
        }
      }
    }
    return true;
  }

  render() {
    return (
      <textarea
        ref={c => {
          this.textArea = c;
        }}
        style={{ resize: 'none' }}
        name={this.props.input.name}
        onChange={e => this.props.input.onChange(e.target.value, this.props.input.name)}
        rows={this.props.rows}
      />
    );
  }
}
```

#解説
参考にしたコードと似たようなことをしています
以下の部分が全てです

```jsx
  shouldComponentUpdate(nextProps) {
    // textareaの内容が変更された時のみ操作
    if (this.props.input.value !== nextProps.input.value) {
      if (isEmpty(nextProps.input.value)) {
        // 内容が空なら初期値の行数に戻すだけ
        this.textArea.setAttribute('rows', this.props.rows);
      } else {
        this.textArea.setAttribute('rows', this.props.rows);
        // 内容が有るならスクロールせずに表示できる高さになるまで初期値から1行ずつ増やす
        while (this.textArea.scrollHeight > this.textArea.offsetHeight) {
          const tempRows = Number(this.textArea.getAttribute('rows'));
          this.textArea.setAttribute('rows', tempRows + 1);
        }
      }
    }
    return true;
  }
```

#注意点
高さにmax-heightなどで上限を定めたい時は
直接textareaにmax-heightを書かないでください

高さの計算とぶつかるのか無限ループになってブラウザが固まります
高さを決めたい場合は適当にラップしてそちらに色々設定してください

※今回で言うと、index.jsのdivに{max-height: 100px, overflow-y: scroll}みたいにすれば
100pxより入力欄が高くなったらスクロールになるよう切り替えられます

#まとめ
shouldComponentUpdateでこういうことして良いのかはわかりませんがとりあえず動いてるのでヨシとします
横方向(cols)にも同じ方法で拡縮できるのではないかと思いますがそこまでは試してないです
【Golang - goroutine(ゴルーチン) 】for - select パターン 例

# 概要
Golangにおけるゴルーチンのfor-selectパターンを実装してみました。
基本的には、チャネルを介してゴルーチン内外でデータのやり取り、エラーハンドリング、終了処理についての例を実装しています。

処理の流れは、

1. ゴルーチン外部から、チャネルを介して文字を挿入("1", "bad0")
2. ゴルーチン内部で、チャンネルから得た文字を数字に変換(エラーかどうか場合分けして、結果をresultに挿入)
3. ゴルーチン外部から、doneをcloseすることで、ゴルーチンが終了し、それに伴いresultチャネルもcloseされる。
4. ゴルーチン外部で、resultを取得していたforが終了する。

# 実装

以下にプログラムと結果を示します。

```go
package main

import (
	"fmt"
	"strconv"
	"time"
)

type Result struct {
	Error    error
	Response int
}

func doSomething(done <-chan interface{}, printStr <-chan string) <-chan Result {
	result := make(chan Result)

	go func() {
		defer fmt.Println("タスク終了")
		defer close(result)
		for {
			select {
			case s := <-printStr:

				i, err := strconv.Atoi(s)
				if err != nil {
					result <- Result{Error: err, Response: 0}

				} else {

					result <- Result{Error: err, Response: i}
				}

			case <-done:
				return
			}
		}
	}()
	return result
}

func main() {
	done := make(chan interface{})
	printStr := make(chan string)
	result := doSomething(done, printStr)

	//1秒後にdoSomethingを終了

	go func() {
		pushData := []string{"1", "bad1"}
		for _, v := range pushData {
			printStr <- string(v)
		}
		time.Sleep(1 * time.Second)
		fmt.Println("doSomethingを終了")
		close(done)
	}()

	//doSomething終了に伴いresultがcloseされる。
	for res := range result {
		if res.Error != nil {
			fmt.Println("error:", res.Error)
			continue
		}
		fmt.Println("Result:", res.Response)
	}

	fmt.Println("Finished !!")
}
```

```bash
Result: 1
error: strconv.Atoi: parsing "bad1": invalid syntax
doSomethingを終了
タスク終了
Finished !!
```
#PowerAutomate #LogicApps でデータの操作を実行する（選択アクション編）

本投稿は、Power Automate、Logic Apps の「データ操作」アクションの中にある「選択」についてサンプルを交えて解説していきたいと思います。

# 選択アクションとは
[データの操作の実行 | Microsoft Docs](https://docs.microsoft.com/ja-jp/azure/logic-apps/logic-apps-perform-data-operations)

公式ドキュメントでは「選択」については下記のように説明されています。
> 異なる配列のすべての項目に対して指定されているプロパティから配列を作成します。

アクションの名前とこの説明でピンときた方はきっとプロ開発者のことでしょう。

私なりの言葉で選択アクションについて説明すると・・・
***「配列の項目の数を変えることなく、項目の内容を変えた配列にする」***
です。

もう少し細かく言うと・・・
「配列の項目の数を変えることなく、***あるルールを項目に適用して***、項目の内容を変えた配列にする」
です。前述の ***あるルール*** というのが選択アクションの設定内容を指します。

ここからは、選択アクションの使い方について初級編、中級編、上級編という形でサンプルを紹介したいと思います。


# 選択アクション：初級編
まずは初級編です。配列はシンプルなものを例として挙げます。

`[1,2,3]` の配列の各項目に対して `1` を加算した配列 `[2,3,4]` を取得したい場合を考えます。
選択アクションは次のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/217aed96-868b-ba64-4af9-7ecdec3895bf.png)

数学関数 `add` を使って、各項目に `1` を加算しました。
結果はこの通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/d4e730b8-557e-427c-619d-2f08efbe17b3.png)

# 選択アクション：中級編
次はオブジェクトの配列を例に挙げます。

次のような JSON があった時に、`name` の部分だけを抽出した配列が欲しい場合を考えます。

```json
[
  {
    "name": "name1",
    "value": {
      "id": 1,
      "subKey": "subKey1",
      "subValue": "subValue1"
    }
  },
  {
    "name": "name2",
    "value": {
      "id": 2,
      "subKey": "subKey2",
      "subValue": "subValue2"
    }
  },
  {
    "name": "name3",
    "value": {
      "id": 3,
      "subKey": "subKey3",
      "subValue": "subValue3"
    }
  }
]
```

選択アクションは次のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/f96a580f-5a51-9b9f-eec3-7a8ea5bec405.png)

選択アクションで `name` 属性を動的なコンテンツで扱えるように、対象の配列を JSON の解析アクションに渡しています。
結果はこの通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/2f03d2c2-1e96-1eb2-cf27-fa96e60523a9.png)

# 選択アクション：上級編
初級編で扱った配列 `[1,2,3]` を入力情報として、中級編で扱ったオブジェクト配列を生成する例を紹介します。

頭を悩ませるのは、中級編で扱ったオブジェクト配列の要素には、子オブジェクトである `value` 属性を持つところです。子オブジェクトを持つオブジェクト配列を生成する場合、まずは子オブジェクトから生成することを考えます。

選択アクションは次のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/a3e0edef-679a-108f-3936-3652bd045841.png)

※ 選択アクションの入力欄に ***表形式*** のマップが表示される場合、選択アクションの結果は***オブジェクト***配列になります。
※ 逆に、初級編、中級編のように入力欄が ***単一項目*** の場合、数値か文字列かブール値の配列になります。

この選択アクションで子オブジェクト部分の配列ができあがります。
結果はこの通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/df4e27ac-1253-bf67-c2cc-7b07e14dcdb5.png)

さらに、この後に続いてもう一つ選択アクションを使います。
今生成したオブジェクトを項目として持つ、オブジェクトの配列を生成します。

選択アクションは次のように設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/f8b1404d-cb04-5013-7372-0306d879aae3.png)

マップの `name` 属性には `item()['id']` を、`value` 属性には `item()` を設定します。
結果はこの通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/89309/e1ae2a5d-b65c-c640-711d-767e99f096cc.png)

# まとめ
いかがだったでしょうか。
選択アクションの***「配列の項目の数を変えることなく、項目の内容を変えた配列にする」***という動きを見ていただきました。
読者の方々の選択アクションに対する理解が深まれば幸いです。

選択アクションを利用する機会は沢山あると思います。
「配列のデータをもとに別のデータに変換したい」、「配列のデータの中から、特定の項目だけを抽出したい」と思ったときは選択アクションの出番です。どんどん使って快適なデータ加工の沼にハマりましょう！ｗ
Sparkの永続化処理（後日談）

以前に「[Sparkの永続化処理に参った話](https://qiita.com/ayatty/items/d1f5af461efee72052e1)」という記事を書きましたが、その後わかったことなどを書きます。おすすめの設定なども書いていきます。

# checkpoint()のおさらい
Sparkのデータの永続化手法には何種類かありますが、その中でも`checkpoint()`の特徴としては、 

- 即実行される。対抗馬である`persist()`は呼んでもマークされるだけでActionが実行されないと永続化処理が実行されないのと比べてタイミングが制御しやすい。
- 取り消せない。これも`persist()`との比較になりますが、`persist()`には`unpersist()`があるのに対して、`checkpoint()`にはそれがない。[^persist]
- 遅い。ファイルに書き込むので仕方がない[^hdfs]ですが、途中経過を計算して一時的に保持しときたいなーなんていうライトな用途にはやや重い。`persist()`なら・・・。

取り消せないので永続化したファイルがずっと残ってしまってそれがファイル容量は食うし、遅いし、後片付けもしないといけないし面倒だ！というのが前回のお話でしたが、それがもう少しなんとかなったよ、という話です。

# SparkのConfigurationを穴のあくほど見つめる
Spark公式の[Configuration](https://spark.apache.org/docs/latest/configuration.html)を眺めていたところ、あるじゃないですか良い項目が！

|プロパティ名                                   |デフォルト|意味| 
|:------------------------------------------------|:------------|:--|
|spark.checkpoint.compress|false|RDDチェックポイントを圧縮するかどうか。 一般的には良い考えです。 圧縮にはspark.io.compression.codecが使用されます。|
|spark.cleaner.referenceTracking.cleanCheckpoints|false|参照がスコープ外の場合にチェックポイントファイルをクリーニングするかどうかを制御します。|

共にデフォルトがfalseですが、チェックポイント使うならこれは必須でしょうよ！

# 試してみた
それなりに期待した通りに効きました。

まず、`spark.checkpoint.compress`ですがこれは環境にもよりますが書き出し先がRAMディスクでもない限り[^cpu]、効果あると思います。自分はSSDの劣化が怖くてHDDをチェックポイント出力先にしていたので効果はてきめんでした。

次に`spark.cleaner.referenceTracking.cleanCheckpoints`の方ですが、こちらは期待通りが半分、がっかりが半分でした。
期待通りなのは、当たり前ですがちゃんと消えてくれることで、自分はループに埋め込まれてて一回のセッションで数十回程度`checkpoint()`を呼んでるんですがファイルは多くても最新の2回分とかなのでディスク容量の圧迫はあまり心配しなくて良くなりました。
がっかりは、結局最後（セッションの終わり）に全部消えてくれるわけでもないので、別途お掃除は必要といったところです。
そもそも、どういった仕組みで参照が切れたと判断しているのかが不明なので、セッションを終わらせる前にひと手間かけるにしてもどうしたらいいのかわからない。
ファイルが消えるタイミングも「いらなくなったら即！」というわけでもないようなので、GCと同じ仕組みなのかな？

# 結論
どんな事情があるのかわかりませんが、個人的にはチェックポイントを使うなら

- spark.checkpoint.compress
- spark.cleaner.referenceTracking.cleanCheckpoints

の2つはほぼ必ずtrue！にしといたほうがいいと思います。

[^persist]: ただしpersist()はpersist()で、unpersist()忘れると（実質）メモリリークになるという使いずらさがありますが。malloc()/free()かと・・・。
[^hdfs]: 生ドライブでなくHDFSを使うともう少しましなのかもしれません。
[^cpu]: つまりCPU時間を圧縮処理に使ってでもI/Oを減らした方がトータルで速くなる場合です。
nvmを使ったNode.jsのバージョン管理

これまでWindowsならnodist、Macならnodebrewを使ってきましたが、nvmがユーザー数多いみたい（ Google Trend によると)なのでnvm使うことにしたい。

nvmのGitHub上に手順や使い方があるけれど英語でさらに初心者にはさっぱりな部分もあるので自分用の備忘録もかねてのメモです。

(nvmリポジトリ)[https://github.com/nvm-sh/nvm]

# Git経由でインストール
インストール方法は他にもあるけどnvmそのものの更新に対応するためには、Git経由でGitHub上のレポジトリクローンがよいみたいです。
更新された場合はプルするだけです。

## 1. nvm をインストール
github.com から nvm を clone する

```terminal
$ git clone https://github.com/nvm-sh/nvm.git .nvm
```
clone したら最新バージョンに checkout してください。

## 2. nvm を使えるようにする
nvm.sh を実行して nvm を使えるようにする

```terminal
$ source ~/.nvm/nvm.sh
```
これで以下が動けば成功です。

```terminal
$ nvm --version
```

## 3. ~/.bashrcに追加

起動時に使えるように設定追加

```bash
export NVM_DIR="$HOME/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"  # This loads nvm
[ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"  # This loads nvm bash_completion
```

以下で再読み込み

```terminal
source .bashrc
```

## 3. Node.jsをインストール
利用可能なバージョン確認

```terminal
$ nvm ls-remote
```
バージョン指定してインストール

```terminal
$ nvm install <version>
```

以下が動けば成功

```terminal
$ node -v
$ npm -v
```

## 4. その他よく使うコマンド

インストールしたバージョン一覧

```terminal
$ nvm ls
```

使用するバージョンの指定

```terminal
$ nvm use <version>
```


nvmの機能一覧

```terminal
$ nvm --help
```

▼参考
https://ikkyu.hateblo.jp/entry/2019/05/03/003636
https://phiary.me/nvm-node-js-install/
【swift】画像のデータサイズを取得し、バリデーション を実装する

#方法
```swift

var image:UIImage? = ... //画像を読み込む

//
let imageData:Int = NSData(data: image.jpegData(compressionQuality: 1)!).count

//※画像のデータサイズをKBで表示。
let dataToKB = Double(imageData) / 1000.0
        
//バリデーションを実装。（10MB以下のみ保存可能）
if dataToKB < 10000.0 {
      
      print("画像を保存できます")

      //画像をimageViewに描写させたりする
      self.imageView.image = image
} else {
            
      print("画像データが過大です。10MB以下可能です")
}
```

#詳しく
##`jpegData(compressionQuality: CGFloat)`

```swift
func jpegData(compressionQuality: CGFloat) -> Data?
```
>指定された画像を含むデータオブジェクトをJPEG形式で返します。

>`compressionQuality: CGFloat`とは？
>0.0〜1.0の値として表される、結果のJPEG画像の品質。値0.0は最大圧縮（または最低品質）を表し、値1.0は最小圧縮（または最高品質）を表します。

今回は、最高品質（オリジナルの画質）でデータサイズを確認したいため、`compressionQuality: 1`にします。

##`count`する
```swift
NSData(data: image.jpegData(compressionQuality: 1)!).count
```
>`NSData(data: Data)`で、
>別のデータオブジェクトの内容でデータオブジェクトを初期化します。

画像を`NSData`型に変換することで、`countメソッド`を使うことができます。
countすることで、byteの数をカウントすることができます。

#参考文献
- https://stackoverflow.com/questions/34262791/how-to-get-image-file-size-in-swift
node.jsのsvg変換パッケージconvert-svg-to-jpeg/pngの日本語文字化け対策

# 問題

svg画像をjpegやpngに変換する際には[convert-svg](https://github.com/neocotic/convert-svg)を使っています。NodeコードからやCLIからも使えたりと高機能なことに加えて、内部的にブラウザに描画したSVGをラスター化しているので変換後の仕上がりが素直で気に入っています。

<div class="iframely-embed"><div class="iframely-responsive" style="height: 140px; padding-bottom: 0;"><a href="https://github.com/neocotic/convert-svg" data-iframely-url="//cdn.iframe.ly/ezeoAj7"></a></div></div><script async src="//cdn.iframe.ly/embed.js" charset="utf-8"></script>

<!--(GitHubのリポジトリはモノレポ化されていて、`packages`ディレクトリ内に共通部分、jpeg/pngの専用処理別に分けて開発されています)-->

以前、日本語を含んだSVG画像を変換した際に文字化けに遭遇したので、その原因、対策をメモしておきます。

文字化けした画像はこんな感じ。
<img width="320px" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135313/5d10a8e0-50d3-34f5-c8d4-89d8135d3de9.png" />

# 原因

内部的にSVGをブラウザ上で表示する際に利用するHTMLテンプレート上に文字コードの指定がされていないため。

具体的には、変換の共通処理を記述している`convert-svg-core`に含まれる以下の箇所

```js:Converter.js
...
    let html = `<!DOCTYPE html>
<base href="${options.baseUrl}">
<style>
* { margin: 0; padding: 0; }
html { background-color: ${provider.getBackgroundColor(options)}; }
</style>`;
...
```

> <https://github.com/neocotic/convert-svg/blob/master/packages/convert-svg-core/src/Converter.js#L194>

# 対策

HTMLテンプレートにメタタグでcharsetを明記してあげる。

```js:Converter.js
...
    let html = `<!DOCTYPE html>
<base href="${options.baseUrl}">
<meta charset="utf-8">
<style>
* { margin: 0; padding: 0; }
html { background-color: ${provider.getBackgroundColor(options)}; }
</style>`;
...
```

# おわりに

Forkして手元で修正したけど本家にPRしてもいいのか迷う。
charsetが固定とも限らないし...。
LaravelでCSVダウンロード機能を実装する。

CSVダウンロード機能を実装するにあたり、少しはまった部分があったので備忘録です。

# 流れ
1. 出力データを用意
2. 出力データをカンマ区切りで配列にセット
3. 改行区切りの文字列に変換
4. 一時的にCSVファイルを作成
5. CSVファイルに書き込み
6. ダウンロードレスポンスを返す。

# 実装
はまったポイント
- 金額など、値にカンマが含まれる文字の扱い -> 値をクオートで囲むことで1つの値として評価される。
- 出力結果が改行されnai -> 改行コードをダブルコートで囲むことで改行コードとして評価される。
- Excelで開いたときに文字化けする -> SJISにエンコーディングする。

```php
public function downloadCsv()
{
    // 1. 出力データをを用意
    $csvHeader = ["No,", 師匠名, ふりがな];
    $csvData = [
        [0001, 春風亭助羊, しゅんぷうてい　すけよう],
        [0002, 桂左志郎, かつら　さしろう],
        [0003, 三遊亭遊智, さんゆうてい　ゆうち],
        [0004, 月亭がた枝, つきてい　がたし],
        [0005, 春雨や雷扇, はるさめや　らいおう],
        [0006, 桂喜八宝, かつら　きゃぽう],
        [0007, 翁家八ゑ千代, おきなや　やえちよ],
        [0008, 春雨や雷海, はるさめや　らいかい],
    ];

    // 2. 出力データをカンマ区切りで配列にセット
    $downloadData = [];
    $downloadData[] = implode(',', $csvHeader);

    foreach ($csvData as $record) {
        // 念の為ダブルクオートで囲む
        foreach ($record as $i => $v) {
            $record[$i] = '"' . $v . '"';
        }

        $downloadData[] = implode(',', $record);
    }

    // 3. 改行区切りの文字列に変換
    $downloadData = implode("\r", $downloadData); // 改行コードはダブルクオートで囲む

    // Excel対応
    $downloadData = mb_convert_encoding($downloadData, "SJIS", "UTF-8");

    // 4. 一時的にcsvファイルを作成
    if (! file_exists(storage_path('csv'))) {
        $bool = mkdir(storage_path('csv'));

        if (! $bool) {
            throw new Exception("ディレクトリを作成できませんでした。", 500);
        }
    }
    $name = 'test.csv';
    $pathToFile = storage_path('csv/' . $name);

    // 5. CSVファイルを作成
    if (! file_put_contents($pathToFile, $csvData)) {
        throw new Exception("ファイルの書き込みに失敗しました。", 500);
    }

    // 6. ダウンロードレスポンスを返却
    return response()->download($pathToFile, $name)->deleteFileAfterSend(true);
}
```
# 参考
https://gray-code.com/php/download-for-csv-file/
https://teratail.com/questions/2199
https://bayashita.com/p/entry/show/49
https://qiita.com/ikemonn/items/f2bc4f9f834c989084ff
https://www.megasoft.co.jp/support/mifes/faq/miw8faq/faq017.html
gitで複数のリモートリポジトリを設定する方法

# 手順（CUI）
やり方は簡単です！
コマンドライン上では以下のコマンドによって2つ目のリモートリポジトリを追加することができます。

```bash
$ cd {PROJECT_DIRECTORY}
$ git remote add {REMOTE_NAME} {REMOTE_URL}
```

初めてリモートをaddするときと何ら変わりません。
例えば、githubのリモートリポジトリを新たに追加したければ以下のような感じになります。

```bash
$ git remote add github https://github.com/{USER_NAME}/{PROJECT_NAME}
```

# 手順（GUI）
SourcetreeのようなGUI(Sourcetreeしか知りませんが笑[*1](#注釈))で行う場合は以下のようになります。
例としてSourcetreeで行っています

<img width="258" alt="スクリーンショット 2020-01-22 0.56.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412552/95394084-8c50-ee08-5374-9c1a115630a2.png">

メニューバーからリポジトリ -> リポジトリの設定を選択

<img width="573" alt="スクリーンショット 2020-01-22 0.57.03.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412552/8119c2ae-9480-45b0-f27e-03ed8a7859da.png">

メニュータブのリモートを選択 -> 追加

<img width="618" alt="スクリーンショット 2020-01-22 0.57.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412552/7742ac50-2343-0833-0c0c-4f0a727f5904.png">

リモートの名前(originなど、好きな名前で大丈夫です)とURLを入力 -> OK

こうすることでリモートリポジトリを追加できます。

ということで `今回はリモートリポジトリの複数追加` についてお話しさせていただきました。
ここまでご覧いただきありがとうございます！
自分自身まだまだ未熟なので訂正、指摘等ございましたらコメントにてよろしくお願いします🙇‍♂️
もちろんその他ご意見ご要望ご質問等もお待ちしております！
それではまた次回の記事でお会いしましょう🙌

# 注釈
*1 他に<a href="https://git-scm.com/book/ja/v2/Appendix-A%3A-%E3%81%9D%E3%81%AE%E4%BB%96%E3%81%AE%E7%92%B0%E5%A2%83%E3%81%A7%E3%81%AEGit-%E3%82%B0%E3%83%A9%E3%83%95%E3%82%A3%E3%82%AB%E3%83%AB%E3%82%A4%E3%83%B3%E3%82%BF%E3%83%95%E3%82%A7%E3%83%BC%E3%82%B9">Git GUI</a>や、<a href="https://www.gitkraken.com/">GitKraken</a>などがあるようです。
VSCodeでLombok

#何の記事？
VS CodeでSpring Bootアプリケーション作成時、Lombokが仕事を放棄しているのではと感じたときのこと。

#どんな状態？
DTOやEntityに「`@Data`」をつけても`getter`,`setter`でコンパイルエラーになるし、補完にも出てこない。

#結論
放棄していない。

VS CodeでLombokを使用するにはSpring Bootの依存関係だけでなく、拡張を入れてあげる必要があるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287607/7d59e9f3-fd3d-8a4e-4aa5-56841f5f5e04.png)

これをインストールするとVS Codeの再起動が求められます。
再起動し、ビルドが完了するとコンパイルエラーが消えています。

あともちろん補完にも出るようになります。
GCP Cloud Build のトリガー条件（2020年1月時点）

Cloud Build のトリガー設定で「トリガーのタイプ」「含まれるファイルフィルタ」「無視されるファイルフィルタ」を組み合わせ他時に、どの条件が優先されるのかわからないケースがあり試してみた結果です。

※Cloud Build のトリガーは記事公開時点でベータ扱いのため、今後仕様が変更される可能性があります。

# 結論

* 「トリガーのタイプ」が「タグ」の場合、「含まれるファイルフィルタ」と「無視されるファイルフィルタ」の設定は無視される
* 「トリガーのタイプ」が「ブランチ」の場合
    * 「含まれるファイルフィルタ」だけを設定すると、それにマッチしないファイルをコミットしてもビルドはトリガーされない
    * 「含まれるファイルフィルタ」と「無視されるファイルフィルタ」いずれも設定した場合、両方にマッチするファイルをコミットしてもビルドはトリガーされない（無視されるファイルフィルタが優先される）

# 試した内容

以下の組み合わせを考えて、どうなるのか曖昧なパターンについて実際にコミットして試してみた結果が上述の結論です。また、トリガーのタイプにタグを設定した場合にいずれの指定も無視されるようだったのでこのパターンでもいくつか試してみましたが、やはり無視されるようでした（タグは特定のコミットのみ示すので差分を気にしないのは理にかなっている気がします）。

含まれるファイルフィルタ指定|無視されるファイルフィルタ指定|含まれる～にマッチするファイル|無視される～にマッチするファイル|マッチしないファイル|トリガーされる？|
:---:|:---:|:---:|:---:|:---:|---|
|||||v|トリガーされるはず|
|v||v|||トリガーされるはず|
|v||||v|?|>トリガーされない
||v||v||トリガーされないはず|
||v|||v|トリガーされるはず|
||v||v|v|トリガーされるはず|
|v|v|v|||トリガーされるはず|
|v|v||v||トリガーされないはず|
|v|v|||v|?|
|v|v|include/exclude 両方にマッチ|include/exclude 両方にマッチチ||?|
|v|v|v|v||トリガーされるはず|
|v|v|v||v|トリガーされるはず|
|v|v||v|v|?|
|v|v|v|v|v|トリガーされるはず|
Redisを5分間だけ触ってみた

# Redis

前から気になる存在だったので5分だけ触ってみた。思っていたよりもあっけなかった。

```
                _._                                                  
           _.-``__ ''-._                                             
      _.-``    `.  `_.  ''-._           Redis 5.0.7 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._                                   
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 12730
  `-._    `-._  `-./  _.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |           http://redis.io        
  `-._    `-._`-.__.-'_.-'    _.-'                                   
 |`-._`-._    `-.__.-'    _.-'_.-'|                                  
 |    `-._`-._        _.-'_.-'    |                                  
  `-._    `-._`-.__.-'_.-'    _.-'                                   
      `-._    `-.__.-'    _.-'                                       
          `-._        _.-'                                           
              `-.__.-'                 
```

## Redisの基礎知識

* KVS
* インメモリ
* デフォルトで16個のデータベースを持っていて、それぞれ0～15の*index*が割り当てられている

## Redisサーバ立ち上げ

```
$ redis-server /usr/local/etc/redis.conf
```

## Redisクライアント立ち上げ

```
# -nでデータベースの番号指定
$ redis-cli -n 1
```

あるいは`$redis-cli`でredisコンソールに入り`SELECT 1`でも良い。

## Redisでpub/sub
```terminal
# あるターミナルのタブにてsubscribe
$ redis-cli
127.0.0.1:6379> subscribe my_channel
1) "subscribe"
2) "my_channel"
3) (integer) 1
1) "message"       # 受け取った
2) "my_channel"    # 受け取った
3) "hello"    　　　# 受け取った

```


```terminal
# 別のタブにてpublish
$ redis-cli
127.0.0.1:6379> publish my_channel 'hello'
```
Rider で探る、このメソッドどのボタンから呼ばれているの？

Unity の IDE に Rider 使うと楽になったな～と思っているショートカットの紹介シリーズです。

# 前提
* Windows です
* ショートカットキーの設定が Reshaper バインドです 

# このメソッド、どこのボタンから呼ばれているの？

人の書いたプログラムを読んでいて、このメソッド、どこのボタンから呼ばれているの？って思ったことありませんか？

この3ステップやるのにどのぐらいかかると思いますか？
1. ファイル開いて
2. 目的のメソッドに飛んで、
3. そのメソッドが使われているボタンまで飛ぶ

これ、Rider なら15秒でできます。
1. Ctrl+N してポップアップにファイル名
2. F12 してポップアップにメソッド名
3. Alt+F7 で設定されているボタンに飛ぶ（複数個所から使用されている場合は候補が出る感じになります。）
![3step.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/e6037e9f-c8da-0d0f-98b4-91be8790fadd.gif)

うっすら覚えている少し前のプロジェクトや、知らない人のプログラム読むの早くなります。

# 捕捉
Mac で IntelliJ IDEA バインドだと以下のような感じになりますが、結局ステップ数は同じです。
1. shift + shift してポップアップにファイル名
2. command + F12 してポップアップにメソッド名
3. option + Alt + F7 で設定されているボタンに飛ぶ
システムからメール送信するときのメール配信サービスを列挙

システムからメール送信をするため、メール配信サービスを調査したので列挙します。

当初は、Amazon SESの利用を検討していましたが、
バウンスメールの処理を独自実装しないといけないため、
他のサービスを検討することとなりました。

[AWSのSESでバウンスメール(bouncemail)対策。3つの方法とメリット・デメリット](https://vitalify.jp/blog/2018/03/aws-ses-bouncemail.html)
[AWS SESでバウンスメールをハンドリングしてみた](https://qiita.com/Yoshi_T/items/b12c74b6af09df05dff3)

ちなみにLaravelドキュメントで触れられているサービスは、
バージョンによって地味に変わっています。

5.7
> MailgunとSparkPostなどAPIベースドライバはシンプルでSMTPサーバよりも高速です。

5.8
> MailgunとSparkPost、Postmarkなど、APIベースドライバはシンプルでSMTPサーバよりも高速です。

6.x
> MailgunとPostmarkなど、APIベースドライバはシンプルでSMTPサーバよりも高速です。

# Mailgun
[いますぐ使う Mailgun](https://qiita.com/sasasin/items/4797c681393b663f2960)

以下の理由で却下

> - RFC準拠していないメドに容赦ない
> - 単純にAmazon SESの4倍くらい高価

# Postmark
このサービスは、トランザクションメールにのみ利用できるというポリシーのようで、今回のメール配信内容としてはマーケティングメールに当たるため、却下

[トランザクションメールとマーケティングメールの違いとは？](https://sendgrid.kke.co.jp/blog/?p=2989)

# SendGrid
今回はSendGridで要望を満たせたため、こちらを採用しました。

- マーケティングメールでも利用可能
- バウンス処理をしてくれる
- 無料枠が大きい(12,000通/月)

https://sendgrid.kke.co.jp/plan/
コンポーネントについて少し考える

# コンポーネントの原則

SOLID…レンガを組み合わせて壁や部屋を作る方法
コンポーネントの原則…部屋を組み合わせて建物を作る方法

## コンポーネント

- デプロイの単位
- 単体でもデプロイでき、システムの一部でもデプロイでき、複数のコンポーネントをリンクして実行可能ファイルを作れたり、.exe のように動的に読み込むプラグインとしてもデプロイできる。
- 優秀なコンポーネントは常に個別にデプロイできる
- ディスクの高速化や安価に手に入るようになったり、小型化されることでデータの I/O が爆速で向上したおかげで、プログラム量が増えることを気にしたり、コンパイルに数時間・数日かかることはなくなった

## コンポーネントの凝集性

### 再利用・リリース等価の原則(REP)

リリースには適切な通知とドキュメントが必要

また、tag とかリリース番号とかで追跡できることも重要

**コンポーネント**

- クラスやモジュールを適当に寄せ集めたものではない
- 一貫するテーマや目的がありそれを共有するためのモジュールを集める必要がある

一つのコンポーネントを形成するクラスやモジュールは**まとめてリリース可能**であること

### 閉鎖性共通の原則(CCP)

SRP のコンポーネント版

#### SRP(復習)

- クラスを変更する理由が複数あるべきではない

例えば本を管理するアクターとして、司書、利用者が考えられるが、一つのクラスを変更したら二つのアクターに影響が出てしまう
以下の例は SRP に違反する

```rb
class Book
  def getTitle
    "A Great Book";
  end
end
```

#### CCP(閉鎖性共通の原則)

- コンポーネントを変更する理由が複数あるべきではない
- 同じタイミングでデプロイされることが多いクラスは一つにまとめてもいい

CCP の「閉鎖性」は OCP の「クローズド」と同じ意味

- 新規機能や機能拡張をしても既存の実装に影響がないこと(OCP)
- 変更の種類が似ているクラスを一つのコンポーネントにまとめる(CCP)

何か良い例がないものか…

SRP との関係

```text
SRP…複数アクターに影響が出るのであれば別のクラスにメソッドを分ける
CCP…変更の理由が異なるクラスは別のコンポーネントに分ける
```

要は同じタイミングで変更したり、同じ理由で変更するものについてはひとまとめにしてしまうということ

### 全再利用の原則(CRP)

一緒に用いられることが多いクラスやモジュールは同じコンポーネントにまとめよ

A というコンポーネントが B というコンポーネントを用いるうときに、実際には B というコンポーネントのごく一部の機能を使いたいがために使用するのは避けるべきである

なぜなら、ごく一部の機能を使っているかそこそこ多くの機能を使っているかどうかに関わらず依存は発生し、使われる側(B)のコンポーネントが変更されるたびに使う側(A)のコンポーネントにも変更が必要になるから

Node(npm)や Ruby(gem)を想像すると良さそう

[gem のバージョンアップで依存関係が壊れるのを調べやすくした](https://ota42y.com/blog/2018/04/04/virtual_gem/)

ISP との関係

```text
ISP…使っていないメソッドを持つクラスに依存しない
CRP…使っていないクラスを持つコンポーネントに依存しない
```

使っていないクラスを持つコンポーネントに依存しない  
→ つまり、使っていない機能を持ったコンポーネント使わないようにしよう  
→ ひとまとめにするクラスはどれか？よりも、どのクラスをひとまとめにすべきではないかを伝える原則

### まとめ

REP・CCP と CRP は相反する概念である

なぜなら、REP・CCP が出来るだけ一つのコンポーネントにまとめられる場合はまとめてしまおうという思想であることに対して、CRP はひとまとめにすべきでないクラスを伝える原則だからである

そのため、開発時の利便性と再利用性をトレードオフを考慮する必要がある

![iamge](https://user-images.githubusercontent.com/24403693/72807923-c4f1cd80-3c9b-11ea-99cd-9886adacf729.png)

## 参考

[Clean Architecture 達人に学ぶソフトウェアの構造と設計](https://www.amazon.co.jp/Clean-Architecture-%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%AE%E6%A7%8B%E9%80%A0%E3%81%A8%E8%A8%AD%E8%A8%88-Robert-C-Martin/dp/4048930656/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1FX6G45547IYU&keywords=clean+architecture&qid=1579622033&sprefix=clean+archi%2Caps%2C235&sr=8-1)
ゼロから作るDeep LearningでMNIST認識ニューラルネットワークを作ろうとして少し手こずった話

#はじめに
ゼロから作るDeep Learning<sup>[1](#参考文献)</sup>を読んで、MNISTの手書き文字を認識するニューラルネットワークを作りました(長いのでコードは省略)。
本の通り、誤差逆伝播法で損失関数の勾配を算出し、Wやbを更新していくものです。
GitHub上にソースコードがありますが、極力コピペせずに本を読みながら自分でコードを書くようにしました。とはいえ、構成はGitHubのものとほぼ同じです。ソフトマックスやクロスエントロピー関数、シグモイド関数などをを関数として作成、レイヤーやネットワークをクラスとして作成しています。
(パラメータの更新にはAdamを使うなどちょっと変えていますが)

結果↓　(こちら<sup>[2](#参考文献)</sup>の記事のコードを使って出力しています)
<img width="683" alt="スクリーンショット 2020-02-02 10.15.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391077/e8741183-7229-3145-1777-6fce7a61eb7b.png">
勾配確認↓
<img width="610" alt="スクリーンショット 2020-02-02 10.21.07.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391077/fa8935d0-ed89-5182-973e-08691c672a5d.png">
認識精度10%なので当てずっぽうレベル。勾配もあってない。予測できない。

#原因追求でやったこと
・手動で順伝播、逆伝播(行列計算)をして、ニューラルネットワークの結果と照合する
　⇨手動の結果とニューラルネットワークの結果は一致。ニューラルネットワーク関連(レイヤの実装など)に問題はなさそう。
・ニューラルネットワーク内部で使用している関数(ソフトマックス、交差エントロピー、シグモイド、relu)を確認する
　⇨それぞれ簡単なarrayを入れて計算しても変なところは見当たらず。
　　そこで本のGitHubからこれらの関数をコピペして学習させてみた。ソフトマックスを入れ替えてみたところ↓
<img width="667" alt="スクリーンショット 2020-02-02 10.43.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/391077/48ba225e-5c8a-9aba-52eb-7db98db868e2.png">

こいつだ・・・・・・

#どこがいけなかったか
↓ソフトマックス容疑者

```python:softmax.py
def softmax(x):
    c = np.max(x) 
    return np.exp(x - c) / np.sum(np.exp(x - c))
```
↓正しいソフトマックス(本のGitHubからコピペ)

```python:softmax.py
def softmax(x):
    if x.ndim == 2:
        x = x.T
        x = x - np.max(x, axis=0)
        y = np.exp(x) / np.sum(np.exp(x), axis=0)
        return y.T 

    x = x - np.max(x) # オーバーフロー対策
    return np.exp(x) / np.sum(np.exp(x))
```
バッチ(サンプル数が2以上の時)ではソフトマックス関数の分母が各サンプルの指数関数の和ではなく、全サンプルの指数関数の和になっていました。これが原因でした。
(ソフトマックス関数の動作検証をした時は1次元のarrayを入れていたので気づかなかったのが悪い)

#参考文献
[1]斎藤康毅著　ゼロから作るDeep Learning
本のGitHub：https://github.com/oreilly-japan/deep-learning-from-scratch
[2]ゼロから作るDeep Learningで素人がつまずいたことメモ:4章
https://qiita.com/segavvy/items/bdad9fcda2f0da918e7c
転職日記７日目

前回から少し間が空きました。

というもの、ポートフォリオに熱中していて、

とりあえぜず、ログインや編集、ログアウト、記事投稿その他諸々の機能を付け終えて

あとはcssで形を整えるところまで来れました。

しかし、まだ終わりではなくこれからAWS環境で動かせるようにしてみたり、Dockerを使ってみたりやること

は山のようにあるのですが今月中にせめて開発環境をDockerにして、gitにあげたいです。

東京に住む家も決まり、ここからが本当の戦いではありますが、頑張ります。
ChromeでPush通知が動作しない

# はじめに
v58だとできるのですが、v70を超えるとうまくいかないと思って調べていたら、ようやくこれだというものを見つけた

◆chromeの保護されていない通知にて通知を許可する方法
　https://teratail.com/questions/158309
　　※きっとこれと同じ現象が発生している

で、回避策として以下のサイトを見つける。
◆“unsafely-treat-insecure-origin-as-secure” の設定をGUIで行う方法について
　https://qiita.com/dmiya/items/77eadd8abdfd7282d917

簡単に動作確認してみたら、うまくいった。
これで問題が1つ解決した。。。はず。

後は参考サイトをいくつかぺたりと
◆Push.jsを使ってサイトに10分でブラウザプッシュ通知を導入する
　https://qiita.com/_mochi_fuwa/items/8b69e1a0585fa9c6bcac

◆Chrome 69からHTTPSの表記が変化！Chrome 70以降も要チェック！
　https://zenlogic.jp/aossl/browser/chrome69-https/

◆「unsafely-treat-insecure-origin-as-secure」フラグがChromeで機能しない
　https://tutorialmore.com/questions-1732472.htm
【CSS】position: fixed; と z-index

## position: fixed;
:sunny: 指定した位置に要素を固定
:sunny: 位置は top, bottom, left, right を使う

![ezgif.com-video-to-gif.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/36d8430b-161b-95d2-da47-b474b946fe2a.gif)

上の動画をご覧いただくと、背景だけが動き
ずーっとログインボタンが同じ位置にあるのがわかるかと思います。
これは position: fixed; でログインボタンを固定しているためです。

```ログインボタンCSS.
position: fixed;
  top: 50px;
  left: 500px;
```

[【CSS】position: absolute; と position: relative;](https://qiita.com/mikimikiman/items/ebe0e32313cd272b5484#position-absolute) のときにも説明しましたが、サイトの左上を始点と考えて

上から 50px
左から 500px

のところにログインボタンを配置して
position: fixed; で ログインボタンよ、そこから動くんじゃない！:raised_hand: と命令しているわけです。

## z-index
:sunny: 要素の重なりの順番を指定する。
:sunny: ０を基準として数字が大きいほど上に重なる。
:sunny: 必ず position プロパティと一緒につかう。

さきほどの動画ですが、のんびりとしてとてもきれいな風景なので気球に乗って景色を観覧するのもいいなと思い、気球に乗ることにしました:smile:

![気球.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/886e3d98-2585-4eea-f5b5-2fe91502207e.png)

配置したのが下の動画になります:smile:
![ezgif.com-video-to-gifのコピー.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/57c28298-aeea-b5dd-27a5-096c45724253.gif)

ありゃりゃりゃりゃ・・・！:open_mouth:
気球が前にきてログインボタンが隠れてしまったじゃないか・・・！:rolling_eyes:
これは気球女子がじゃまだ。。
なんとかせねば:expressionless:

・・・というときに使うのが z-index です:smile:

```ログインボタンcss.
  position: fixed;
  top: 50px;
  left: 500px;
  z-index: 1;
```

z-index は 0 を基準として数字が大きくなるほど上に重なる性質をもっているので、上にきてほしいログインボタンに 1 を設定しました。
z-index を使用するときは**必ず position プロパティを使用する**のがルールです。

では動画を確認してみましょう:smile:
![ezgif.com-video-to-gifのコピー2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532773/823bdbe8-f37e-ae9b-5179-0413bc40f8da.gif)

気球女子が重なることなく、ログインボタンが上になりました:laughing:
Giteaでhttps接続

[Gitea v1\.10（コンテナ）をHTTPS接続で使う \- Qiita](https://qiita.com/niiku-y/items/27c0f5fd2807d8cfc137)
の通りでした。（圧倒的感謝）


```yml:docker-compose.yml
version: '3'
services:
  gitea-server:
    image: gitea/gitea:1.10.3
    volumes:
      - ./gitea-data:/data
      - ./ssl-data:/ssl
    ports:
      - 3000:3000
      - 10022:10022
    environment:
      - SSH_DOMAIN=${MY_DOMAIN}
      - SSH_PORT=10022
      - USER_UID=1000
      - USER_GID=1000
      - ROOT_URL=http://${MY_DOMAIN}:3000
    restart: always
```

サーバーのIP or ドメインを.envに入れる。

```
$ echo MY_DOMAIN=www.example.com > .env
```

letsencryptで作成されたファイルをコピーしておく。

```
# mkdir ssl-data
# cp /etc/letsencrypt/live/www.example.com/fullchain.pem ssl-data/
# cp /etc/letsencrypt/live/www.example.com/privkey.pem ssl-data/
```

一度起動して落とす

```
# docker-compose up
# docker-compose down
```

`ROOT_URL`をhttpsから始まるよう変更して`PROTOCOL`、`CERT_FILE`、`KEY_FILE`の行を追加する。         

```
$ vi gitea-data/gitea/conf/app.ini
# ROOT_URL         = http://www.example.com:3000
ROOT_URL         = https://www.example.com:3000
PROTOCOL         = https
CERT_FILE        = /ssl/fullchain.pem
KEY_FILE         = /ssl/privkey.pem
```

起動して`https://www.example.com`から`登録`ボタンから設定を行う。
[Gitea環境をdocker\-composeで作ってみる \- Qiita](https://qiita.com/k8uwall/items/63c6424a976012122d18)参照

```
# docker-compose up
# docker-compose down
```

[Gitea v1\.10（コンテナ）をHTTPS接続で使う \- Qiita](https://qiita.com/niiku-y/items/27c0f5fd2807d8cfc137)

>なお、わざわざapp.iniをここで編集せずとも環境変数で最初から反映できるんじゃないの？
ということは当然いわれそうであるが、やってみて反映できなかったのでこのようにvolumeにあるiniを
編集するような手順としている。

niiku-y氏も書かれているがdocker-compose.ymlの環境変数から入れてくれそうなものだが、giteaの現在の動きでは手動編集が必要なようだ。


[使用法：HTTPSセットアップ\-ドキュメント](https://docs.gitea.io/en-us/https-setup/)
【React】Next.jsをfirebaseにデプロイする方法

# package.jsonを修正
"start"に「-p $PORT"」を追記かつ、"export"を追加

```
  "scripts": {
    "dev": "next",
    "build": "next build",
    "start": "next start -p $PORT",
    "export": "next export"
  },
```

# build & export

以下コマンドを叩いて、ビルドする

```
npm run build
```

そのあと、エクスポートする

```
npm run export
```

build&exportに成功するとoutフォルダに、静的ファイルが吐き出される

# firebaseのデプロイ準備

まずは、以下コマンドを叩く

```
firebase init
```

各質問に答えていき、以下の質問の際に「out」を入力する

```
? What do you want to use as your public directory? out
```
firebase.jsonに正しい内容が記載されていることを確認して、デプロイ実行

```
firebase deploy
```

以上！
【続編】SwiftUI 導入で LLVM のドキュメント読む羽目になった話

# はじめに
こちらの記事は [前編](https://qiita.com/AkkeyLab/items/a698545f2423b9b1dec9) の続編となります。事前にこちらの記事もご覧ください。
今回もどこかで発表したわけでもないでも関わらずスライドを多用して説明していきますので、最後まで見ていただけると嬉しいです！

# 前編の振り返り
![xcode-previews-and-llvm-neo.004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128344/d4fccfd7-e168-608d-2879-49f8be93a335.png)
前回はこのような考察でまとめていました。
詳細は「[SwiftUI 導入で LLVM のドキュメント読む羽目になった話](https://qiita.com/AkkeyLab/items/a698545f2423b9b1dec9)」を御覧ください。

# 前編の訂正
![xcode-previews-and-llvm-neo.006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128344/01510d4a-03d1-7dd2-008d-45b73375a8ab.png)
まずは訂正をさせてください。エラー文の解釈を間違えておりました。
実はここ、かなり重要なことを教えてくれています。カバレッジを取得するためのランタイムライブラリが呼び出せなかったと言ってくれていました。

# Linker flags に `-fprofile-instr-generate` を追加すると動く理由
早速ではありますが、前回からハッキリしなかった理由について解説していきます。
説明の都合上、理想の挙動から説明していくことにします。

![xcode-previews-and-llvm-neo.010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128344/bd14f215-51e4-5873-af56-054eff047a4f.png)
Swift コンパイラである swiftc に対して `-fprofile-instr-generate` を指定してアプリのソースコードをビルドすることによって、カバレッジ情報を取得するための処理がアプリのコードに挿入されます。この「カバレッジ情報を取得する処理」というのは、コードカバレッジランタイムライブラリ内の関数呼び出しがメインです。

![xcode-previews-and-llvm-neo.011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128344/bcefe0ad-e0b9-c52a-ac94-60f162eb1a89.png)
先程の図では点線の矢印で表現していましたが、これには理由があります。 swiftc によるコンパイル時には **呼び出し処理** が追加されるだけで実際の処理が含まれないからです。
なので、 Linker に対して「コードカバレッジランタイムライブラリのリンク」を命じなければならないのです。したがって、 Linker に対して渡される `-fprofile-instr-generate` はコードカバレッジランタイムライブラリとリンクさせるためのものだったのです。

![xcode-previews-and-llvm-neo.015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128344/8bfd3611-c480-f61e-e8d5-f61ab878becd.png)
先程、 Linker に対して `-fprofile-instr-generate` を指定すると説明しましたが、本来これは Xcode が自動で行っているはずです。その証拠に、 XcodePreviews 以外ではカバレッジを有効にした状態でも正常にビルドができます。
結論ですが、 Xcode のバグ（と思われる）で XcodePreviews のためのビルドのときのみ、コードカバレッジの設定を反映する処理（コードカバレッジが有効であれば Linker に対して `-fprofile-instr-generate` を渡す処理）が欠如しているのだと思います※。
なので、 Linker flags に対して明示的に `-fprofile-instr-generate` を指定してあげなければならなかったのです。

※ Static Framework が含まれる場合に発生したように、ここに記載していないものも含む一定の条件で発生するものだと思われます。

# 学び
![xcode-previews-and-llvm-neo.019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/128344/73c40312-1a3d-3dd1-0767-478cd7099bdd.png)
今回、この結論にいたるまでに多くの方からアドバイスなどをいただきました。
本当にありがとうございます！！

# さいごに
学びとして書いてますが、そもそもカバレッジは日常的に有効にしておくべきではありません。
そんなミスをしていたからこそ遭遇してしまった問題だったわけですが、すごく勉強になりました！この記事も「この問題の解決策！」ではないですが、知識として多くのエンジニアに届けばと思います。

最後まで読んでいただき、ありがとうございます！
DXOpalがマルチタッチに対応しました

このエントリはOpal Advent Calendar 2019の53日目(?)の記事です。

スマホでのマルチタッチに対応したDXOpal 1.4.4をリリースしました。

以下にデモがあります。スマホやタブレットなどのタッチ対応デバイスで開いてみてください。

- https://yhara.github.io/dxopal/examples/multi_touch/index.html

タッチ関係のAPIのまとめを載せておきます。

## タッチAPI(シングル)

- Input.touch_down? : タッチされているかを返す
- Input.touch_push? : タッチされたかを返す
- Input.touch_release? : タッチが離されたかを返す

指一本で操作できるようなゲームを作るときはこっちが便利です。

## タッチAPI(マルチ)

- Input.touches
    - `DXOpal::Touch`の配列を返す
    - Touchオブジェクトは.id, .x, .y, .dataをもつ。また、.released?で離されたかを返す
    - .dataはハッシュで、自分の好きなデータを入れてよい
- Input.new_touches
    - `DXOpal::Touch`の配列を返す(直前のフレームで発生したタッチのみ)

マルチタッチに対応したいときはこっちを使います。以下は例です。

- https://github.com/yhara/dxopal/blob/f1e4db38d8b1226f8cc24159de1900408828af73/examples/multi_touch/main.rb#L12-L22
自動デプロイ（Capistrano）でエラー mkdir: ディレクトリ `/var/www' を作成できません: 許可がありません

Capistranoで自動デプロイをしていると、エラーが発生しました


[![Image from Gyazo](https://i.gyazo.com/f7642507c5e1ffe6c8bc8133fdc66d9e.png)](https://gyazo.com/f7642507c5e1ffe6c8bc8133fdc66d9e)

テキストだと下記ですね

```
mkdir stdout: Nothing written
mkdir stderr: mkdir: ディレクトリ `/var/www' を作成できません: 許可がありません
mkdir: ディレクトリ `/var/www' を作成できません: 許可がありません
```

このエラー"var/www/アプリ名"のディレクトリにしている場合は、パーミッションの問題等だと思いますが、、、

###「　"var/www/アプリ名"使ってないんですけど！！！
　なんでエラーが出るんだよ！！！
  　"www"が気に食わないから、別のフォルダ名にしてるんですけど！！！
　他の記述も確認したけど、全部"var/www/アプリ名"書いてねええよ！！！　」

という人向けに対処方法を解説します。


## 原因

CapistranoのHPにも記載されていますが、
デフォルトだと"var/www/アプリ名"を読み込見ます。
でも"var/www/アプリ名"のディレクトリにアプリを保存していないので、
「アプリないから、自動デプロイできないで」という状態です。

だから手動デプロイだとうまく行きますが、Capistranoを使った自動デプロイではエラーが発生したわけです。


## 解決策

結論：　Capistranoのデフォルト設定が"var/www/アプリ名"を読み込むので、オプション設定で変更する。

```ruby:deploy.rb
# 下記を挿入してください
set :deploy_to, '/var/○○○（ディレクトリ名）/○○○（アプリ名）'
```

これを挿入することで、EC2にあるアプリの保存場所を正しく認識され、Capistranoで読み込みが可能となります。

あとは自動デプロイを実行しましょう

```
# アプリケーションのディレクトリで実行する
$ bundle exec cap production deploy
```

今度はうまくいくはずです。

[参考]（https://capistranorb.com/documentation/getting-started/configuration/)
Markdown テーブル内で文字として「|」を使用する

# 目的

- Markdownのテーブルにて文字としてセル内に`|`を記載する方法をまとめる。

# 結論

- 表示して欲しい`|`の前に`\`を記載する。

# 考え方

- Markdown内ではテーブルを作成する際にセルの区切りに`|`を使用している。
- そのため`|`をセル内に記載したくても表示されない。
- `|`の様な特殊文字を記載したい際は、特殊文字を通常文字列として扱ってもらう必要がある。
- そのために用いるのがエスケープ文字`\`である。
- エスケープ文字`\`の後ろは特殊文字だったとしても通常の文字として扱われる。
- 一文字のエスケープ文字でエスケープできるのは特殊文字一文字のみである。

# 書き方の例

- 下記にテーブル内に`|`を表示させる方法を記載する。

    ```markdown
    |データ名1|データ名2|
    |---|---|
    | \| |   |
    ```

    ↓プレビュー

    |データ名1|データ名2|
    |---|---|
    | \| |  | |
arduino で ccache (ESP32, M5StickC等 編)

# 概要

arduinoでbuildしているとなんで？というぐらい遅い、、、というわけで、ccacheを有効にします。

https://nagayasu-shinya.com/arduino-ccacche/
などを参考にしましたが、ESP32で有効になりませんでしたので、有効の仕方です。

# 準備

```
$ brew update
$ brew install ccache

$ ls /usr/local/bin/ccache
$ mkdir /var/tmp/arduino

$ ccache -M 10G
$ ccache -s
cache directory                     /Users/xxxx/.ccache
primary config                      /Users/xxxx/.ccache/ccache.conf
secondary config      (readonly)    /usr/local/Cellar/ccache/3.7.7/etc/ccache.conf
cache hit (direct)                     0
cache hit (preprocessed)               0
cache miss                             0
cache hit rate                      0.00 %
cleanups performed                     0
files in cache                         0
cache size                           0.0 kB
max cache size                      10.0 GB
```


# 設定編

1. arduino を 立ち上げる
2. file - preference で preference.txtをクリックして、ファイルを開く
3. arduino を 閉じる
4. ２のファイルに```build.path=/var/tmp/arduino```を追加する
5. ```/Users/xxxx/Library/Arduino15/packages/esp32/hardware/esp32/1.0.4/platform.txt```などを開く

```
## Compile c files
recipe.c.o.pattern=/usr/local/bin/ccache "{compiler.path}{compiler.c.cmd}" {compiler.cpreprocessor.flags} {compiler.c.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" {compiler.c.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"

## Compile c++ files
recipe.cpp.o.pattern=/usr/local/bin/ccache "{compiler.path}{compiler.cpp.cmd}" {compiler.cpreprocessor.flags} {compiler.cpp.flags} -DF_CPU={build.f_cpu} -DARDUINO={runtime.ide.version} -DARDUINO_{build.board} -DARDUINO_ARCH_{build.arch} -DARDUINO_BOARD="{build.board}" -DARDUINO_VARIANT="{build.variant}" {compiler.cpp.extra_flags} {build.extra_flags} {includes} "{source_file}" -o "{object_file}"
```

のように、recipe.co.o.patternとrecipe.cpp.o.patternにccacheを追加する
$PATHに見つからないとか言われますので、とりあえず、絶対パスにしたら動きました。

```
$ /usr/local/bin/ccache -s
cache directory                     /Users/xxxx/.ccache
primary config                      /Users/xxx/.ccache/ccache.conf
secondary config      (readonly)    /usr/local/Cellar/ccache/3.7.7/etc/ccache.conf
stats updated                       Wed Jan 22 00:15:13 2020
cache hit (direct)                    11
cache hit (preprocessed)               0
cache miss                           140
cache hit rate                      7.28 %
called for preprocessing             250
cleanups performed                     0
files in cache                       420
cache size                         118.6 MB
max cache size                      10.0 GB
```

みたいに一応hitしているみたいです。

まだ遅いけど、改善はされました。

というか、preference.txtには、build.cache=onみたいにも書かれているのになぜフルビルドするんでしょうね・・・・
binaryenのビルド

## きっかけ

[WebAssemblyとは？〜実際にC言語をブラウザで動かす〜【2019年6月版】](https://qiita.com/umamichi/items/c62d18b7ed81fdba63c2)

この記事を読んで、やっていこうとしたらbinaryenのビルド時にエラー

```
$ cmake . && make
-- No build type selected, default to Release
fatal: No names found, cannot describe anything.
CMake Error at CMakeLists.txt:25 (message):
  Error running git describe to determine version
```

```
$ git clone --depth=1 https://github.com/WebAssembly/binaryen.git -b version_90 //現在最新のリリース
$ cd binaryen
$ cmake . && make
$ sudo make install
```

ちゃんとブランチを指定しなさいってことなんすね、すんません。忘れそうなのでメモ

## 引用
[WebAssemblyとは？〜実際にC言語をブラウザで動かす〜【2019年6月版】](https://qiita.com/umamichi/items/c62d18b7ed81fdba63c2)