OmniAICreator/Qiita-1.07M huggingface dataset:
AWS S3 のオブジェクトURLを Azure Storage でやるための手順

ただ単にファイルをダウンロードできるURLを作りたいだけだったのだが、知らないと苦労する典型的なパターンだと思いました。

# 手順
## 0. 概要
1. ストレージアカウントを作成する
2. コンテナーを作成する
3. ファイルをアップロードする
4. 共有用のURLを作成する

## 1. ストーレジアカウントを作成する
1. 左ペインのストレージアカウントを選択する    
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/5b46e990-3635-996b-089e-12983a5792c0.png" width=320 />
2. `新規` を選択    
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/ca8b34cb-a08c-b603-9db6-792b378226d2.png" width=320 />
3. `ストレージアカウント名` に適当な名前を入力する。(※1)  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/9b2a447f-2aad-90e1-5276-89aa88e9c069.png" width=320 />
4. `作成` を押す
5. デプロイ中になるので、`デプロイが完了しました` と表示されるまで待つ。
![2021-05-07_22h18_01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/babd10f6-791d-7604-e4f6-4676be8b5442.png)

※1 よくわからなければいったんその他の項目はスルーでも大丈夫。

* `地域` は近いところのほうが好ましいかも。
* `冗長性` も必要ならあげればいいし、不要なら下げればよい。
* 詳細設定、ネットワーク、データ保護、タグ、確認および作成はスルー。

## 2. コンテナーを作成する
1. リソースに移動を選択する。    
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/bb7120ac-3457-9d5b-2676-96164643dc98.png" width=160 />
2. 左側のペインのデータストレージのところにあるコンテナーを選択し、`+コンテナー` を選択する名前を入力して、作成ボタンを選択する   
![2021-05-07_22h30_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/b48a031e-5171-b91b-18c0-879b38b94c85.png)

## 3. ファイルをアップロードする
1. 2 で作ったコンテナーを選択し、アップロードを押して、ポチポチローカルファイルを選択していく。  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/3452b0ed-0669-0ac5-0937-1190c8a4a1a2.png" width=160 />
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/5df632b2-a7eb-bd8f-a0f8-3fad2a6aff72.png" width=160 />

## 4. 共有用のURLを作成する
1. 3 でアップロードしたファイルを選択し、SAS の生成を選択し、SASトークンおよびURLを生成を選択する(※2)  
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/c2f7853b-2f75-6ff1-7bae-2ebd74fed2cc.png" width=540 />
2. BLOB SAS URL が表示されるので、この URL を使ってアクセスすればファイルをダウンロードできる
![2021-05-07_22h37_58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/506075/eb814e68-e2f4-2c3a-1db1-40676972385c.png)


※2 共有に対する開始日時と有効期限の設定があるので、必要なら修正する。デフォルトだと次の日ぐらいまでなので短いです。
形態素解析ツールKyTeaのインストールと使い方

# はじめに
とりあえずKyTeaを試してみようという人が公式サイトを読むのは、少しハードルが高いと感じました。
そこで、KyTeaをインストールして最低限の形態素解析を行えるようになるための情報を記載しました。
KyTeaを使いこなしたい人は、公式サイトもチェックしてください。


# インストール
## Windows版
以下のリンク先よりWindows版の最新バージョンのzipファイルをダウンロードして解凍する。

http://www.phontron.com/kytea/index-ja.html

作成されるディレクトリ"kytea-win-0.4.2"にpathを通しておく。

## Linux, Mac OSX, CygWin版
途中で~がないと怒られる場合はインストールしてやり直す．

```場所:端末
$ sudo apt update & sudo apt upgrade
$ cd <path>
$ git clone https://github.com/neubig/kytea.git
$ cd kytea
$ autoreconf --install
$ ./configure
$ make
$ sudo make install
```

動作確認とトラブル例．

```:端末
// 動作確認
$ kytea --help

// インストールが成功していればヘルプが表示される

// 以下のエラーが表示される場合があり，その場合は以下を実行する．
> kyTea: error while loading shared libraries: libkytea.so.0: cannot open shared object file: No such file or directory
$ sudo ldconfig
$ kytea --help
```

# KyTeaの使い方
## KyTeaの学習
以下の形式のコーパスを用意する。

```
単語/タグ1/タグ2/.../タグn 単語/タグ1/タグ2/.../タグn ... 
例. コーパス/名詞/こーぱす の/助詞/の 文/名詞/ぶん で/助動詞/で す/語尾/す 。/補助記号/。
```
用意したコーパスを利用し、以下で学習する。

```場所:端末
# フルアノテーションデータを使う場合
$ train-kytea -full corpus_full.txt -model model.dat
```
さらなる情報およびリソースへはリンク先を参照

http://www.phontron.com/kytea/train-ja.html#feature

http://www.phontron.com/kytea/model-ja.html

http://www.phontron.com/kytea/active-ja.html

## KyTeaを使って形態素解析
```:端末
# 端末に出力するだけの場合
$ kytea < test_raw.txt
# 学習したモデルを使い、出力結果を保存する場合
$ kytea -model model.dat < test_raw.txt > result_full.txt
# デフォルト(-in raw -out full)以外のファイル形式で形態素解析
$ kytea -in full -model model.dat < test_full.txt
```
## KyTeaのファイル形式
使用できるファイル形式は表の通りで、詳細はリンク先を参照

|オプション名  |形式  |
|---|---|
|-full  |フルアノテーション  |
|-part  |部分的アノテーション(未知タグあり)  |
|-tok   |単語分割のみ  |
|-raw   |アノテーションなし  |
|-conf  |信頼度付きアノテーション  |

http://www.phontron.com/kytea/io-ja.html

## プログラムからKyTeaを呼び出す方法

http://www.phontron.com/kytea/api-ja.html

### Pythonの場合(pipを使う)
setup.pyを読む限り，python3.7-3.10に対応．

```:端末
$ python --version
> Python 3.10.1
$ pip install kytea

// 動作確認
$ python
>>> import Mykytea
```

### コード例
```:Python
import Mykytea

# 引数は以下のように渡す
opt = "-model /usr/loca/share/kytea/model.bin"
mk = Mykytea.Mykytea(opt)
s = "今日はいい天気です．1999"

# 単語分割を取得
for word in mk.getWS(s):
   print(word)

#解析結果(単語/品詞/読み)を文字列で取得
print(mk.getTagsToString(s))

#1位のタグ(単語/品詞/スコア/読み/スコア)を取得
t = mk.getTags(s)
showTags(t)

#(2位以降含む)すべてのタグを取得
tt = mk.getAllTags(s)
showTags(tt)
```

# 参考
http://www.phontron.com/kytea/index-ja.html

https://qiita.com/SUZUKI_Masaya/items/f5c4118bff616d94c230

https://qiita.com/SUZUKI_Masaya/items/dd8b28122eb53b0ba90a
MySQL8+phpMyAdmin

#なにこれ
ローカルのDBなんて適当でええねんという人向け。
認証を古いバージョンに対応させたもの、設定不要でupしたらもう使えるやつ。
production環境の場合はきちんとmy.cnfに書くなり個別設定するなりしましょう。

# 参考

https://qiita.com/A-Kira/items/f401aea261693c395966
https://qiita.com/hirokiseiya/items/04ad429713be7042c9d1

# docker-compose.yml
```yml
version: '3'

services:
  # MySQL
  db:
    image: mysql:latest
    container_name: mysql_host
    environment:
      MYSQL_ROOT_PASSWORD: root
      MYSQL_DATABASE: db
      MYSQL_USER: docker
      MYSQL_PASSWORD: docker
      TZ: 'Asia/Tokyo'
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci --default-authentication-plugin=mysql_native_password
    volumes:
    - ./db/data:/var/lib/mysql
    - ./db/my.cnf:/etc/mysql/conf.d/my.cnf
    - ./db/sql:/docker-entrypoint-initdb.d
    ports:
    - 3306:3306
  # phpMyAdmin
  phpmyadmin:
    container_name: phpmyadmin
    image: phpmyadmin/phpmyadmin
    environment:
    - PMA_ARBITRARY=1
    - PMA_HOSTS=mysql_host
    - PMA_USER=root
    - PMA_PASSWORD=root
    ports:
    - 8080:80
```
ロボットの運動学表現の整理

最近調べたところロボットの運動学表現には3種ほどあって、違いがよくわからなくなってきたので整理したく本記事を書いています。

# DH法(Denavit-Hartenberg line coordinates: 1955～)
最も古典的な表現方法です。

1. 各JointのZ軸(下図の青矢印)を、回転軸の向きとする
2. 各JointのX軸(下図の赤矢印)を、現在の関節とZ軸と次の関節のZ軸との共通法線の向きとする。共通法線が一意に決まらない(すなわちZ軸が平行)場合は、X軸とZ軸の交点は自由に決めて良い。
3. Y軸を、X軸とZ軸と右手系を成すように設定する。

この手順でDHパラメータ$a, \alpha, d, \theta$を決定します。
同次変換行列は次のようになります。
$$
^{n-1}T_{n} = \rm{Trans}(z_{n-1}, d_{n}) \rm{Rot}(z_{n-1},\theta_{n})\rm{Trans}(x_{n}, a_{n})\rm{Rot}(x_{n},\alpha_{n})
$$
変換の読み方は左からです。
1. $z_{n-1}$軸の向きに$d_{n}$だけ平行移動
2. $z_{n-1}$軸周りに$\theta_{n}$だけ回転
3. $x_{n}$軸の向きに$a_{n}$だけ平行移動
4. $x_{n}$軸周りに$\alpha_{n}$だけ回転
 

特徴は、共通法線でX軸向きを決めていることと、関節の座標原点$O_{i}$を関節$i$のZ軸上に置くのではなく、関節$i+1$のZ軸上においていることだと思います。


![1024px-Classic_DH_Parameters_Convention.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92606/c362a38d-85f4-2079-5694-810569d594ff.png)

# 修正DH法(Modified Denavit-Hartenberg line coordinates)
たぶん現在この表現方法が主流だと思います。従来のDH法と異なる点は、座標原点$O_{i}$を関節$i$のZ軸上に置いていることです。
これがどうしたと思われそうですが、計算順序が変わります。

$$
^{n-1}T_{n} =  \rm{Rot}(x_{n-1},\alpha_{n-1}) \rm{Trans}(x_{n-1}, a_{n-1}) \rm{Rot}(z_{n},\theta_{n}) \rm{Trans}(z_{n}, d_{n})
$$

1. $x_{n-1}$軸周りに$\alpha_{n-1}$だけ回転
2. $x_{n-1}$軸向きに$a_{n-1}$だけ平行移動
3. $z_{n}$軸周りに$\theta_{n}$だけ回転
4. $z_{n}$軸周りに$d_{n}$だけ平行移動

![DHParameter.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/92606/a9dc0b96-31f0-4089-a3a5-54768623faac.png)

> __補足__
> 修正DHは他にも様々なものがあるようです。ここで挙げたのはWikipediaの記法。

# Hayati-Roberts line coordinates(1985～)
ハヤティの方法(?)と呼ばれているとかなんとか。これが書きたかった。
ハヤティの方法では$L_{hr}(e_{x},e_{y},l_{x},l_{y})$と線表現される。
DH法では平行な軸があるとき煩雑になってしまう欠点があったが、これを改善、そもそも共通法線を使わない表現方法にしました。という感じらしい。

特にスクリュー理論表現が含まれるような状況で有効だとか。確かにDH法だとスクリュー形状は表現できなさそうだけど、スクリュー形状のロボットってなんだろう。想像が出来ない。今後調べてみる。

以下はWikipediaをGoogle翻訳にそのまま突っ込んだものです。

* $e_{x}$と$e_{y}$は$X$軸と$Y$軸の単位方向ベクトル。$e_{z}=(1- e^{2}\_{x} - e^{2}\_{y})^{\frac{1}{2}}$と表せることから、$Z$成分は必要なくなる
* $l_{x}$ と $l_{y}$ は、ワールド リファレンス フレームの原点を通り、ラインに垂直な平面とラインの交点の座標です。 この法平面上の基準座標系は、世界基準座標系と同じ原点を持ち、その $X$ および $Y$ 座標系軸は、世界座標系の $X$ および $Y$ ラインに沿った平行投影による Y 軸。

# 感想
普通のロボットアームを使用する場合には修正DH法で問題は無さそうだけど、いろんな論文等で言われているように平行軸の場合の処理が大変ですよとのこと。
平行軸だと、$z_{i-1}$軸から$z_{i}$への向きへ共通法線$x_{i-1}$を定義することは一意に出来るけど、共通法線の交点を一意に出来ないところがネックという記述をよく見る。

まあ結局、メーカーが出してるロボットを使うなら修正DH法でやるしかないよねって気がする。
JavaのPriorityBlockingQueueを試してみる

#プライオリティ順に要素を取得できるQueue
PriorityBlockingQueueなるものを知ったので、使い方を確認するためにサンプルプログラムを書いてみました。

通常のQueueは、先に入った要素から先に取得できる、いわゆるFIFO(First In First Out)になっています。

PriorityBlockingQueueも基本はFIFOですが、プライオリティがより高く設定されているものは、先に取り出すことができるようになっています。

以下がサンプルプログラムです。

```java:PriorityBlockingQueueSample.java
import java.util.concurrent.PriorityBlockingQueue;

public class PriorityBlockingQueueSample {
    public static void main(String[] args) {
        PriorityBlockingQueue<Entry> queue = new PriorityBlockingQueue<>();
        queue.add(new Entry("one", 2));
        queue.add(new Entry("two", 1));
        queue.add(new Entry("three", 3));
        queue.add(new Entry("four", 5));
        queue.add(new Entry("five", 4));

        while (queue.size() > 0) {
            System.out.println(queue.poll().getValue());
        }
    }
}
```

```java:Entry.java
public class Entry implements Comparable<Entry> {
    String value;
    int priority;

    public Entry(String value, int priority) {
        this.value = value;
        this.priority = priority;
    }

    String getValue() {
        return value;
    }
    int getPriority() {
        return priority;
    }

    @Override
    public int compareTo(Entry other) {
        return Integer.compare(this.priority, other.getPriority());
    }
}
```

このプログラムの実行結果は、以下のようになります。
>two
one
three
five
four

通常のQueueであればFIFOなので、"one, two, three, four, five"の順に要素を取得できるはずですが、プライオリティを設定してるため、順序が異なっています。

EntryクラスはQueueに入れる用に定義したクラスです。ポイントとしては、Comparableインターフェースを実装し、compareTo関数をオーバーロードすることです。

PriorityBlockingQueue内では、格納されているインスタンスのcompareToメソッドを呼んで、プライオリティの判定を行っています。

今回の例ではpriorityフィールドの値のみを使っていますが、compareToメソッドを書き直せば、priorityが同値ならvalueの値もプライオリティ判定に加える、といったことも可能です。

ジョブの管理をQueueで行っていて、ジョブにプライリティをもたせたいと言った場合に、使えそうなクラスですね。
Mac OS X (Big Sur)にdockerをインストールする

# はじめに
多くの方が書かれていますが、記事が古いため書いてる通りにやっても上手くいかない事があります。

なので、振り返られるように記事にしておきます。

---

# Dockerのインストール

以下のコマンドでインストールします。

```
$ brew install docker --cask
```
---

インストール中のメッセージ。
長らくHomebrewをアップデートしてないのでErrorが出ていますがインストールは出来ました。

```
Error: 
  homebrew-core is a shallow clone.
To `brew update`, first run:
  git -C /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core fetch --unshallow
This command may take a few minutes to run due to the large size of the repository.
This restriction has been made on GitHub's request because updating shallow
clones is an extremely expensive operation due to the tree layout and traffic of
Homebrew/homebrew-core and Homebrew/homebrew-cask. We don't do this for you
automatically to avoid repeatedly performing an expensive unshallow operation in
CI systems (which should instead be fixed to not use shallow clones). Sorry for
the inconvenience!
==> Downloading https://desktop.docker.com/mac/stable/amd64/61853/Docker.dmg
Already downloaded: /Users/Masaaki_Murakami/Library/Caches/Homebrew/downloads/f47fc0605c8d59cc9f5232206dec8ea7d11e3d502dea4dad960e0551ccb10c97--Docker.dmg
==> Installing Cask docker

==> Moving App 'Docker.app' to '/Applications/Docker.app'
🍺  docker was successfully installed!

```

---

記事によっては以下のように書いていますが、この方法はBig Surでは使えないそうです。

```
$ brew cask install docker
```
https://qiita.com/luton-mr/items/83386f43c395ecec7736

---

インストールが無事終了したらバージョン確認。
(以下は2021.06.01時点でのバージョン番号)

```
$ docker --version
Docker version 20.10.5, build 55c4c88
```
sort.SearchStrings の注意点と対策コード

## 記事の概要

文字列を二分探索する関数 sort.SearchStrings は、その返り値では、
探索対象の文字列が存在するか、存在しないかが判断できない。
その説明と対策コードを考え、書いた。

## 参考文献
https://golang.org/pkg/sort/#SearchStrings
https://golang.org/src/sort/search.go?s=3680:3724#L91

## sort.SearchStrings の仕様

sort.SearchStrings は 公式ドキュメントによると、
昇順にソートされた文字列スライスと文字列xを受け取り、スライスの中にxがあるか二分探索する。
文字列スライスの中にxが存在する場合, そのインデックスを返し、
文字列スライスの中にxが存在しない場合、そのスライスに、昇順を維持して、xを挿入するためのインデックスを返す。

```
func SearchStrings(a []string, x string) int
SearchStrings searches for x in a sorted slice of strings and returns the index 
as specified by Search. The return value is the index to insert x if x is not 
present (it could be len(a)). The slice must be sorted in ascending order.
```

## 何を問題としているか

返り値から探索対象の文字列が存在するか、存在しないかが判断できない。
例えば、以下のコードでコメントは出力結果を表しているが、以下の結果が一致してしまっている

- a を探索した場合: スライスに a がなく、a の挿入位置 0 が返る 
- b を探索した場合: スライスに b があり、その位置の 0 が返る

```go
var slice = []string{"b"}

fmt.Println(sort.SearchStrings(slice, "a")) // 0
fmt.Println(sort.SearchStrings(slice, "b")) // 0
fmt.Println(sort.SearchStrings(slice, "c")) // 1
```

## どうするのか

返ったインデックスを元に、スライスにアクセスし、その文字列と探索文字列が等しいか調べる。
ただし、公式ドキュメントの言及(```it could be len(a)```)や、上の例の c の探索のように、
範囲外のインデックスが返る場合があるので、その場合を避けて考える。以下がそのコードである.

```go
	var target = "b"
	var slice = []string{"b", "d"}
	var idx = sort.SearchStrings(slice, target)

	// 存在するかを調べる
	if idx != len(slice) && slice[idx] == target {
		fmt.Println("Exists")
	}

	// 存在しないことを調べる
	if idx == len(slice) || slice[idx] != target {
		fmt.Println("None")
	}
```
ngrokの切り替え時に注意すること

オリジナルのlinebotを作成する際に、ローカル環境で`ngrok`を利用して、動作確認を行っていたのですが、デプロイ後、本番環境から開発環境に戻して`ngrok`を使って動作確認をする際に、Webhook URLをngrok用のURLに書き換え、通信状況の確認を行うのですが、毎回、`403Forbiddenエラー`が表示されてしまい、ん？なんでだ？と悩んでしまうことがあったので、解決方法をメモしておきます。

開発環境
macOS BigSur
ruby-2.6.5
Rails 6.0.3.6

`ngrok(エングロック)`というのは、ローカルサーバーを外部公開して、どこまらでもアクセスできるようにするツールのことです。

### 403Forbiddenエラー
messagingAPIの[公式リファレンス](https://developers.line.biz/ja/reference/messaging-api/#status-codes)では、ステータスコード403エラーについて

*リソースにアクセスする権限がありません。ご契約中のプランやアカウントに付与されている権限を確認してください。*

と記載されており、リクエストを送っても、権限がないので、アクセスできないということだと分かります。
つまりは、Webhook URLに設定した

```
https://xxxxxxx.ngrok.io/callback
```
の`xxxxxxx.ngrok.io`の部分からの通信を許可するような設定をアプリケーション側に設定しないといけません。


### 解決方法

rails6以降を使用する場合、`config/application.rb`内に先程説明した`xxxxxxx.ngrok.io`の部分をコピーし、そこからの通信を許可する設定を行うとエラーが解決できます。

```:config/application.rb
(省略)
config.hosts << "xxxxxxxxx.ngrok.io"
(省略)
```

ngrokは立ち上げるたびに、このURLが変更され、毎回、このエラーにハマってしまったので、忘れないように記事にさせていただきました。
VSCode Remote container にプラグインの追加（シンタックスハイライト等）

## VSCodeのリモートコンテナでのシンタックスハイライト表示できるようにする
リモートコンテナに対して起動したVSCodeではデフォルトだとプラグインは有効になっていない
javascriptやcssなどのハイライト表示は有効
 
### 前提
- 既にVSCodeをインストールしている
- VSCodeのプラグインを入れている（もしくはまだ入れていない）
- VSCodeのリモートコンテナを使い始める

### VSCodeの起動
- リモートコンテナで接続しているところで、`code .` にて VSCodeは起動できる
![vscode-0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1482752/1c9b8655-1580-2eca-9f8f-6947baa41f4e.png)

- 設定
![vscode-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1482752/c808def2-e19a-45e5-d718-f78af4159f0f.png)

Install in Dev Container:... を押すとリモートコンテナ側に対してプラグインが有効になります
シンタックスハイライト表示された

![vscode-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1482752/79d11fbc-9d13-114f-0f86-2fea45ec7bdc.png)


### 他のプラグイン
- Git用のプラグイン等も同様の方法で追加できます
    - mhutchie.git-graph
    - eamodio.gitlens
第 6 章 Linter とフォーマッタでコード美人に メモ

###linter
コードを静的解析してコンパイルではじかれない潜在的なバグを警告するもの

###コードフォーマッタ
インデントや改行などのスタイルを一律に自動整形してくれるもの

ESLint については Create React App で生成したプロジェクトには ESLint パッケージが最初からインストールされてる 
インストール済みのものをそのまま使っておいたほうが無難 

・インストールされているバージョンの確認の方法

```typescript
$ yarn list eslint
warning Filtering by arguments is deprecated. Please use the pattern option instead.
└─ eslint@7.20.0
```
追加でインストールしていくのは、ESLint による公式の TypeScript 対応プロジェクト『TypeScript ESLint』が提供してるパッケージ群

ESLint 本体を除くエコシステムのパッケージは主に 3 種類に分類される
・パーサ(Parser)
...... ソースコードを特定の言語仕様に沿って解析してくれるライブラリ。ESLint には JavaScript のパーサが組み込まれているが、標準では TypeScript には対応していないので、TypeScript のパ ーサを導入する

・プラグイン(Plugin)
...... ESLint の組み込みルール以外に独自のルールを追加するもの。それらを適用した推奨の共 有設定とパッケージングして提供されることが多い

・共有設定(Shareable Config)
...... 複数のルールの適用をまとめて設定するもの。ESLint に同梱される eslint:recommended や
Airbnb社が提供しているeslint-config-airbnb53 が有名

####ESLint の設定ファイル
設定ファイルは eslint --init コ マンドでひな形を対話的に作ることもできる

生成される設定ファイル .eslintrc.js の内容は次のよう になるはず

```javascript
module.exports = { 
 env: {
  browser: true,
  es2021: true, 
 },
 extends: [ 
  'plugin:react/recommended', 
  'airbnb',
 ],
 parser: '@typescript-eslint/parser', 
  parserOptions: {
  ecmaFeatures: { 
   jsx: true,
  },
  ecmaVersion: 12, 
  sourceType: 'module',
  }, 
 plugins: [
  'react',
  '@typescript-eslint', 
 ],
 rules: {
 }, 
};
```
ESLint の設定ファイルは JSON でも YAML でもいいんだけど、JavaScript にしておくのが無難

・env
...... プログラムの実行環境を ESLint に教える。個別の環境ごとに globals の値がプリセットさ れている

・extends
...... 共有設定を適用する。共有設定は ESLint に標準で含まれているものか別途インストールし たもの、またはインストール済みプラグインのパッケージに含まれているものを指定する。なお ここに記述した共有設定間でルール設定が重複している場合、リストの後ろに記述されたほうが 優先される

・parser
...... ESLint が使用するパーサを指定する

・parserOptions
...... パーサの各種実行オプションを設定する

・plugins
...... 任意の(インストール済みの)プラグインを組み込む

・rules
...... 適用する個々のルールと、エラーレベルや例外などその設定値を記述する

###特別なコードフォーマッタ Prettier

####Prettier の環境を作る
・prettier
...... Prettier 本体

・eslint-config-prettier
...... Prettier と競合する可能性のある ESLint の各種ルールを無効にする共有設定

###stylelint
stylelintはまさにESLintのCSS版

・stylelint
...... stylelint 本体

・stylelint-config-standard 84
...... stylelint 公式による標準の共有設定

・stylelint-order 85
...... stylelint の並び順に関するルールセットのプラグイン

・stylelint-config-recess-order 86
......RECESS87 にもとづくCSSの並べ替えのための共有設定
Tips: CodeBuildでGitHubのPRへコメントを行う

## これは何

記事投稿イベント「3000文字Tips」の参加記事です。

https://qiita.com/official-events/d523df99d6479293ffa7

## CodeBuildについて
CodeBuildとは、AWSで使えるCI/CDサービスです。
詳しくは↓の記事などが参考になると思います。

https://qiita.com/yuta-38/items/7ff485019e23cf3b9f6e

## CodeBuildの準備
まずはCodeBuildとGitHubを以下の記事を参考に連携してください。

https://qiita.com/sasasin/items/6e5f7001cba350851d49

https://kitigai.hatenablog.com/entry/2019/04/13/220607

CIの発火イベントは`PULL_REQUEST_UPDATED`を設定してください。

## コメントを行うためのスクリプトを用意する
GitHubのPRへコメントを行うためのスクリプトを用意します。
今回はRubyで書いていますが、GitHubのAPIが叩ければなんでも大丈夫です。

```ci.rb
require 'net/http'
require 'uri'
require 'json'

trigger_data = ENV['CODEBUILD_WEBHOOK_TRIGGER'].split('/')

uri = URI.parse("https://api.github.com/repos/#{'ユーザー名'}/#{'リポジトリ名'}/issues/#{trigger_data[1]}/comments")
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true

params = {
  body: <<~EOS   
    #{'コメントしたい内容'}
  EOS
}

headers = {
  "Accept" => "application/vnd.github.v3+json",
  "Authorization" => "token #{'GITHUBアクセストークン'}"
}


response = http.post(uri.path, params.to_json, headers)

```


## buildspec.ymlの準備
buildspec.ymlに以下のように記述します。

```buildspec.yml
phases:
  build:
    commands:
      - |
        parsed_triger=(${CODEBUILD_WEBHOOK_TRIGGER//\// })
        if [ "${parsed_triger[0]}" = "pr" ]; then
          ruby scripts/ci.rb
        fi
```
py.exe をインストール


 
2.7.15(32bit
2.7.15(64bit
 python launcher はインストールされない（py.exe）

3.6.8(64bit
 python launcherはインストールできる

１度インストールした　pythonLauncherはpythonのアンイストールには引きづられない
アンインストールはwindowsのアプリから個別にアンインストールが必要


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1484234/8df5c5c6-1657-e822-1e45-57b9e3b73c28.png)
MySQL WorkbenchでRead Onlyと表示されデータが編集できない時の対応

#テーブルのデータが編集できない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/6dc4301d-723d-7dda-fd29-b2b34d202805.png)

ReadOnlyと表示されています。

#対応法

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/659469/69ad5bf4-7401-77f2-07a7-ae8e1aee0c7f.png)

オートインクリメントのプライマリキーのカラムを追加して解決しました。

https://stackoverflow.com/questions/10815029/mysql-workbench-edit-table-data-is-read-only
簿記仕訳 例題

仕訳問題：
１．東京商店は、商品￥２００を仕入れ、代金は後日支払いとした。なお、引取運賃￥３０は、後日支払うことにした。

答え：

（仕入）　２３０　　（買掛金）　２００
　　　　　　　　　　（未払金）　３０

仕入の時自社負担の運賃は借方の仕入に含まれます。貸方は商品の額は買掛金、運賃は未払金です。後日それぞれ支払うので、全て買掛金にまとめないです。

２．東京商店は、建物の修繕費（収益的支出）￥１０００と改造費（資本的支出）￥６０００を現金で支払った。

答え：

（修繕費）　　１０００　　　　　（現金）７０００
（建物）　　　６０００　　

何で修繕費は借方の建物ではないですか。
修繕費は建物を利用するとともに必要な支出です。これは費用です。損益計算書の費用欄で反映されます。
改造費はもっと便利に利用できるための投資です。貸借対照表の資産欄に反映されます。
費用ですが投資に扱うやり方は粉飾決算でよく利用される方法です。

３．当期首に消耗品￥４００を購入し**消耗品費**勘定で処理しているが、当期中に￥３５０を使用している。消耗品に関する決算整理仕訳を行いなさい。

４．当期首に消耗品￥４００を購入し**消耗品**勘定で処理しているが、当期中に￥３５０を使用している。消耗品に関する決算整理仕訳を行いなさい。

答え：
３．　（消耗品）　　５０　　　　（消耗品費）　　５０
４．　（消耗品費）　３５０　　　（消耗品）　　　３５０

購入時に費用として勘定したら、期末の決算整理で未使用分は費用から消耗品に振替します。
購入時に消耗品に勘定したら、期末の決算整理で利用分を費用として振替します。

5. 店主が店の商品２0,000円を私用で使った。

答え：
（資本金　）　　　20,000　　　　　　　（仕入）　　　　　　20,000

商品を使ったことによってその分仕入の費用がなくなりました。

７. 店舗兼自宅としている建物の固定資産税１０,０００円を現金で支払った。なお、店舗部分は７０％（７,０００円）、自宅部分は３０％（３，０００円）である。

答え：
（租税公課）　　　　　　７,０００　　　（現金）　１０,０００
（資本金また引出金）　　３,０００　　　　
　　　
費用となる税金　→ 租税公課
費用とならない税金、費用となる税金でも事業以外の部分　→ 資本の引き出しとして処理
WPF + MVVM で ListViewItem の MouseDoubleClick から ViewModel の ICommand を呼ぶ方法

NuGet で [AttachedCommandBehavior](https://www.nuget.org/packages/AttachedCommandBehavior/2.0.0?_src=template) を追加

```c#:ViewModel
Public ReactiveCommand<T> Hoge { get; set; }
```

```xml:View
xmlns:cb="clr-namespace:AttachedCommandBehavior;assembly=AttachedCommandBehavior"

<ListView>
    <ListBox.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="cb:CommandBehavior.Event" Value="MouseDoubleClick" />
            <Setter Property="cb:CommandBehavior.Command" Value="{Binding Path=DataContext.Hoge, RelativeSource={RelativeSource AncestorType=Window}}" />
            <Setter Property="cb:CommandBehavior.CommandParameter" Value="{Binding}" />
        </Style>
    </ListBox.ItemContainerStyle>
</ListView>
```
はじめての可観測性ハンズオン + ハンズオン後、担当システムにLambda Insights適用

[AWSの基礎を学ぼう 特別編　最新サービスをみんなで触ってみる はじめての可観測性](https://awsbasics.connpass.com/event/209070/)に参加しハンズオンをしました。

そして後日、自分の担当しているシステムに未適用だったLambda Insightsを適用してみました。

# ハンズオン



## 手順と設定のリポジトリ

https://github.com/harunobukameda/Observability

WORDとPDFで手順書が用意されますが、PDFのほうだとコマンドをコピペするとき改行部分でスペースが入ったりしてちょっと詰まったのでWORDのほうがおすすめです。


## このハンズオンで学べるサービス
 - CloudWatch ServiceLens
 - X-Ray
 - CloudWatch Contributor Insights
 - CloudWatch Synthetics
 - CloudWatch Container Insights
 - CloudWatch Lambda Insights
 - CloudWatch Anomaly Detection

## 注意点
 - 料金がそこそこかかる構成なので、環境構築〜いろいろ触る〜環境削除まで１日でやりきったほうがいいと思います(計３時間ぐらいはみておいたほうがいい)
    - リソースの削除手順は手順書の最後に用意されています。
    - 一通り手順書にざっと目を通してからやったほうがいいかも
 - 手順実行する上でVPCは２つ新規に作成されるので余裕が２つ以上必要
    - Cloud9用のVPC
    - 観測対象のサービスをホストするVPC

## memo

 - [CloudWatch ServiceLens](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/ServiceLens.html) と X-Ray は実体は同じもの。見せ方/メニューが違うだけ。
    - 同じものでは？と思ってたのですっきりしました。

# 担当システムにLambda insights適用

普段から「X-Ray」は活用していたのですが、サーバレスアーキテクチャを多用するわりにまだ「Lambda Insights」を入れてなかったので、担当するサービスの１つに入れてみました。

[Lambda Insights の使用を開始する](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Lambda-Insights-Getting-Started.html)に記載のいずれかの方法で有効にする必要があります。

## やったこと

AWS SAMを使っているので[AWS SAM CLI を使用して既存の Lambda 関数で Lambda Insights を有効にする](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/Lambda-Insights-Getting-Started-SAM-CLI.html)の手順を実施します。

書いてある通り、以下をするだけ

- ステップ 1: レイヤーをインストールする
- ステップ 2: マネージドポリシーを追加する
(non VPC Lambdaなので ステップ3は不要)

Lambda Insights用のレイヤーをAWSが用意してくれているので、めっちゃ楽でした。

## 確認

![スクリーンショット 2021-06-01 21.25.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/f014ae79-e887-3ac9-5c30-2c9cbc3c151e.png)

ちゃんと出た〜。
21時以降に記録されているメトリクスがおそらくLambda Insights入れないと出ないもの
Costや Memory Usage がログをLog insightsかけて頑張ったりしなくても可視化されてるので便利！！



## 最初うまくいかなかったところ

まずはじめに、開発環境にLambda Insightsを適用して、ワークロードにリクエストを２つほど処理させましたがLambda Insightsにデータが表示されずメトリクスも生成されていませんでした。
![スクリーンショット 2021-06-01 22.39.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/43631/83800e87-e153-d568-b06f-48039805ad5d.png)

Lambdaコンソールを見るとEnhanced monitoring自体は正常にEnabledになっていたので
リクエストが常にあるていど流れているステージング環境に適用すると、ちゃんとLambda Insightsに表示されメトリクスも生成されました。

あまりに分析対象のデータがないと表示しようがないのかも。
ゲストユーザのセキュリティ設定について

**ゲストユーザ**
　　Salesforceでは、アクセスに認証を必要としない「公開サイト」を作成することができます。例えばナレッジやFAQの公開サイトなどです。
　これらの公開サイトに認証せずにアクセスするユーザを総称して「ゲストユーザ」と呼びます。作成した公開サイトごと にゲストユーザが割り当てられます。

**公開サイトの種類**
　　ゲストユーザがアクセス可能な公開サイトを提供する製品および機能
●Experience Cloud (旧 Community Cloud)
カスタマーやパートナー、従業員のような、ビジネスプロセスに重要な人と情報を共有し、コラボレーションするた めにサイトを構築する事ができます。
公開コミュニティは、認証されていないユーザ（ゲストユーザ）がサイトを閲覧できるようにします。

●Salesforce サイト
Saleforce 上の組織と直接統合された、公開 Web サイトやアプリケーションを作成する機能です。

●Site.com
Site.com は Web コンテンツ管理システム (CMS) です。この製品では、データ主導の動的な Web ページを迅 速に構築し、実行時にコンテンツを編集したり、Web サイトを管理したりできるようになります。

**①カスタムApexによる公開APIメソッド**
Apex クラスメソッドを REST または SOAP Web サービス処理として公開できます。メソッドを Web 経由でコールで きるようにすることで、外部アプリケーションと Salesforce を統合して、あらゆる種類の便利な操作を実行できます。
Apex クラス内で、必要以上のレコードが取り出せないプログラムとなっているか確認することが重要となります。
カスタムApexによる公開APIメソッド![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669836/3fce9f21-de82-2c93-09b0-15bd3a9dbf2c.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669836/740fa6bf-2b8e-251c-a2fb-eab683c9bb38.png)
上記のWeb サービスをゲストユーザが呼び出し可能な場合、
メソッドを使用して必要以上のレコードが取り出せないプログラムとなって いるか確認します。
Apex Web サービスメソッドはシステム権限で実行され、ユーザのオブジェクト権限や項目権限は考慮されません。ただし、Apex Web サービスメソッドが with sharing キーワードで宣言されている場合は、共有ルールが適用されます。
初めてのLaravel ~Blog App~ 04 (備忘録)


**[渋谷で働くエンジニア福さん](https://www.youtube.com/channel/UCqzJi2o7bAPtRD3tTFvi7zA)のYoutube動画,[実践で学ぶプログラミング入門](https://youtu.be/yaitzPzBzuI) の学習記録です。**
<h1>機能実装編</h1>
<h2>１、ブログ一覧機能の実装</h2>
<流れ>
1, ModelでDBからブログデータを取り出す
2, Controllerでモデルクラスを呼び出し、Viewに渡す

```php
public function showList()
    {
        $blogs = Blog::all(); 
　　　　　//BlogModelからallメソッドで全てのブログデータを取得し、変数にいれる
        return view(
            'blog.list',
　　　　　　　 //ディレクトリ中のビューファイル名（view/blog/list.blade.php）
            ['blogs' => $blogs]
　　　　　　　　//keyとvalueでデータを配列にいれ、viewに渡す
        );
    }
```
3, Viewで一覧表示させる

```php
     @foreach($blogs as $blog)
      <tr>
        <td>{{ $blog->id }}</td>
        <td>{{ $blog->updated_at }}</td>
        <td>{{ $blog->title }}</td>
        <td>{{ $blog->content }}</td>

      </tr>
      @endforeach
```

<h2>2、ブログ詳細の実装</h2>
<流れ>
1, 詳細表示したいブログのIDのリンクを作成
`<td><a href="/blog/{{ $blog->id }}"> {{ $blog->title }}</a></td>`
2, Route(web.php)でIDを受け取り、Controllerへ
`Route::get('/blog/{id}', 'BlogController@showDetail') ->name('show');`
3, Modelで該当データを取得
4, Controllerでモデルクラスを呼び出し、Viewに渡す

```php
public function showDetail($id)
    {
        $blog = Blog::find($id);
        //findメソッドで該当するIDのブログデータを取得し、変数に入れる
        if(is_null($blog)){
            \Session::flash('err_msg', 'データがありません。');
            return redirect(route('blogs'));
        }
        return view(
            'blog.detail',
            ['blog' => $blog]
        );
    }
```
 **＜nullとemptyの違い＞**

* null:
変数が NULL かどうか調べる。変数がNULLなら”TRUE”それ以外は”FALSE”を返す
* empty:
変数が空(空文字 0 NULL FALSE 空の配列)だったら”TRUE”それ以外は”FALSE”を返す


5, Viewで表示

```php
@extends('layouts')
@section('title', 'ブログ詳細')
@section('content')
<div class="row">
  <div class="col-md-8 col-md-offset-2">
    <h2>{{ $blog->title }}</h2>
    <span>作成日: {{ $blog->created_at}}</span>
    <span>更新日: {{ $blog->updated_at}}</span>
    <p>{{ $blog->content}}</p>
    
  </div>
</div>
@endsection
```
僕のプロダクトマネジメント(2) - ビジョンドリブンでプロダクトを作っていく

## これは何
この記事は、僕のプロダクトマネジメントに関する知見や考え方などをまとめたものです。
僕の経験や勉強してきたことをもとに、僕の解釈でプロダクトマネジメントについての記事をシリーズとして投稿していこうと思っています。
記事の内容で、それは違うよ、みたいなものがあればぜひコメントや編集リクエストをいただければ嬉しいです。

この記事は

https://qiita.com/getty104/items/4668e2a20b39ffd859c4

の続編となります。

今回はプロダクト作りにおけるビジョンの重要性について解説を行います。

この記事は記事投稿イベントの「エンジニアによるマネジメント」の参加記事でもあります。

https://qiita.com/official-events/c826cda7a9514df143cb

## ビジョンとは何か
企業によっては、「ビジョン」「ミッション」「バリュー」の三つを設定していると思います。この三つに加えて「ストラテジー」を設定ている企業もあるかもしれません。しかしこれらの定義はふんわりしていることが多いです。
まずはじめに、「ビジョン」「ミッション」「バリュー」「ストラテジー」とはなんなのかを改め説明させてください。

結論から言うと、以下の二つの軸によって分けられる4象限の各象限の名称です。

- 社会（外部）と組織（内部）
- 目的（アウトカム）と行動（アウトプット）

図にするとこのような形になります。

![4象限](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/158501/79fdc9b8-c514-c4bf-8eba-0636fc07c3a8.png)

この図を元にして「ビジョン」「ミッション」「バリュー」「ストラテジー」を説明すると以下の通りです。

- ビジョン（組織、目的）
    - 組織が存在する目的
- ミッション（社会、目的）
    - 社会に対してもたらすもの
- バリュー（組織、行動）
    - ビジョンを実現するために、組織として行う行動
- ストラテジー（社会、行動）
    - ミッションを実現するために、社会に対して行うこと

このように、ビジョンとは「組織が存在する目的」となります。
組織によってはビジョン起点でミッションを定義するパターン、ミッションを起点にビジョンを定義するパターンがあります。
ただ、企業として何かを行なっている以上、ビジョンというのはどのような形であれ存在しているはずです。
今回の記事では具体的なビジョンの設定方法などについては省略します。

## プロダクトを作っていく上でなぜビジョンが必要なのか
前項までで、ビジョンがなんなのかについて説明を行いました。
ここからは、なぜプロダクトを作るときにビジョンが重要なのかについて説明を行っていきたいと思います。

### プロダクトは何にでもなれてしまう
現代のプロダクト、特にソフトウェアは本当に様々なものが作れるようになっています。
どんな機能でも、どんなUIでも、自由自在に実現することができます。
しかし、この自由度の高さが、逆にプロダクトの可能性をつぶしてしまう可能性があります。
目的のないプロダクトには目的のない機能が増えていきます。
「目的のない機能が増えるとなんでダメなの？機能が増えてるんだから良いじゃん！」
みたいに思う方もいるかもしれません。これは確かに機能が存在するだけならば正しそうです。
しかし、プロダクトは作って終わりではなく、存在し続ける限り改善とメンテナンスを行い続ける必要があります。
つまり、価値を注ぐべき箇所に注げる力が分散していくことにつながり、プロダクトは価値を曇らせて行ってしまうのです。

### ビジョンは「やること」と「やらないこと」を定義する
前項の通り、プロダクトは何にでもなれてしまうという魅力と危険性を備えています。
改めてビジョンの役割を整理すると、ビジョンとは「やること」に加えて「やらないことも」判断できるようになるのです。
僕は「やらないこと」を判断できるようになる、というのがとても重要だと思っています。
プロダクトは開発をし続ける限り、いやでも機能は変化し続けます。それはまるで一度走り始めた機関車のようなものです。
この変化の中で「やらないこと」を避けることがすなわちプロダクトの価値の最大化につながるのです。

## まとめ
どの企業でもプロダクトを作っている限り、プロダクトは変化し続けるものです。
変化を上手く乗りこなしていくことで、プロダクトは常に最大の価値を提供し続けるものになる、そしてビジョンはその変化を乗りこなすための舵であるというお話でした。

次回はプロダクトの価値にフォーカスし続けるための考え方について解説したいと思います。

## バックナンバー

https://qiita.com/getty104/items/4668e2a20b39ffd859c4
初めてのLaravel ~Blog App~ 03 (備忘録)


**[渋谷で働くエンジニア福さん](https://www.youtube.com/channel/UCqzJi2o7bAPtRD3tTFvi7zA)のYoutube動画,[実践で学ぶプログラミング入門](https://youtu.be/yaitzPzBzuI) の学習記録です。**
<h2>Seeder編</h2>
***シーダーとは？***
”テストデータを簡単にDBに設定できる”  
***factoryとは？***
”Eloquentモデル (SQLをできるだけ書くことなく、簡潔にデータベースにアクセスできるような仕組み)  を使って、テストデータを作る際に、自動でデフォルト値を設定する便利な機能”  
<使い方>

* コマンドからfactoryファイルを作成
`php artisan make:factory BlogFactory`
* Faker PHPライブラリを使用
 言語の設定の編集　`'faker_locale' => 'ja_JP',`
* コマンドでseederファイルを生成
` php artisan make:seeder BlogsTableSeeder`
* BlogFactoy.phpファイルで欲しいテストデータを設定

```php

/** @var \Illuminate\Database\Eloquent\Factory $factory */

use App\Models\Blog;
use Faker\Generator as Faker;

$factory->define(Blog::class, function (Faker $faker) {
    return [
        'title' => $faker->word, //ランダムな英単語
        'content' => $faker->realText, //ランダムな小説の文章
    ]
});

```

* Database.Seeder.phpに作成したファイルを登録

```php
public function run()
    {
        $this->call(BlogsTableSeeder::class);
    }
```
* 以下のコマンドを実行
`composer dump-autoload`
`php artisan config:clear` 
`php artisan db:seed` //MAMPを起動させておく
初めてのLaravel ~Blog App~ 02（備忘録）


**[渋谷で働くエンジニア福さん](https://www.youtube.com/channel/UCqzJi2o7bAPtRD3tTFvi7zA)のYoutube動画,[実践で学ぶプログラミング入門](https://youtu.be/yaitzPzBzuI) の学習記録です。**
<h2>2,Migration編</h2>
***マイグレーションとは？***  

"データベースのテーブル作成や編集などを管理するためのファイル”
基本的に操作は　ファイルの作成と実行の２つ。
[参照ドキュメント](https://readouble.com/laravel/5.5/ja/migrations.html)

* コマンドからマイグレーションファイルを作成  
`php artisan make:migration create_blogs_table`  
(ここでは　blogsという名前)
* 作成したファイルに移動し、中身を設定する
* 実行コマンド　`php artisan migrate`　　
　   

<h2>3,Model編</h2>
***モデルとは？***  

MVCというWebアプリケーションを実装する効率的な方法の一つで、
”データを処理したり、データをDBへ保存したりする役割”
[参照ドキュメント](https://readouble.com/laravel/6.x/ja/eloquent.html)

*  コマンドからモデルを作成`php artisan make:model Models/Blog`
(ここではModelsフォルダにBlogファイル *blogsテーブルの単数名)

 * `php artisan make:model Models/Blog -m `でマイグレーションファイルとモデルの作成を同時に行うことも可能
 * ` php artisan make:model -help`で様々なオプションが用意されているのが確認できる

<h2>4,Route編</h2>
***ルーティングとは？***

”ブラウザから任意のURLにアクセスがあった場合、どのコントローラー処理を動かすか定義する”


<h2>5, Controller編</h2>
***コントローラーとは？***

”Viewからリクエストを受け取り、Modelへ処理の命令を出す、またModelから処理の結果を受け取り、レスポンスとしてViewへ返す役割”

<h2>5, View編</h2>
***ビューとは？***

”Viewとは、ユーザーが実際に見る画面”

***Bladeとは？***

”Laravelのテンプレートエンジン = HTMLに直接PHPが書けたり、テンプレートのけ継承やデータの受け渡しができるなど便利に記述できる”
                  
* 共通テンプレート作成
 
```html:views/layouts.blade.php
<!DOCTYPE HTML>
<html lang="ja">

<head>
  <meta charset="UTF-8">
  <title>@yield('title')</title> 
  <link rel="stylesheet" href="/css/app.css">
  <script src="/js/app.js" defer></script>
</head>

<body>
  <header>
    @include('header') 
  </header>
  <br>
  <div class="container">
    @yield('content') //中身が変化するコンテンツ
  </div>
  <footer class="footer bg-dark  fixed-bottom">
    @include('footer')

  </footer>
</body>

</html>
```
* 共通ヘッダー作成

 ```html:views/header.blade.php
<nav class="navbar navbar-expand-lg navbar-dark bg-dark">
  <a class="navbar-brand" href="#">ブログ</a>
  <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNavAltMarkup" aria-controls="navbarNavAltMarkup" aria-expanded="false" aria-label="Toggle navigation">
    <span class="navbar-toggler-icon"></span>
  </button>
  <div class="collapse navbar-collapse" id="navbarNavAltMarkup">
    <div class="navbar-nav">
      <a class="nav-item nav-link active" href="#">ブログ一覧 <span class="sr-only"></span></a>
      <a class="nav-item nav-link" href="#">ブログ投稿</a>
    </div>
  </div>
</nav>
```
* 共通フッター作成

 ```html:views/footer.blade.php
<div class="container text-center">
  <span class="text-light">©︎福のプログラミング講座</span>
</div>
```
* 共通テンプレートを継承した containerの中身を作成  
(ブログ一覧やブログ詳細、投稿 etc..)

```html:views/blog/list.blade.php
@extends('layouts') //親テンプレートを継承
@section('title', 'ブログ一覧') //親テンプレートの@yieldの中身
@section('content')
<div class="row">
  <div class="col-md-8 col-md-offset-2">
    <h2>ブログ記事一覧</h2>
    <table class="table table-striped">
      <tr>
        <th>記事番号</th>
        <th>日付</th>
        <th>タイトル</th>
        <th></th>
      </tr>
      <tr>
        <td>1</td>
        <td>2020/06/30</td>
        <td>テスト</td>
        <td></td>
      </tr>
    </table>
  </div>
</div>
@endsection
```
Java9のList.ofメソッドとArrays.asListメソッドの違い

Listにする際に
挙動がよくわからなかったのでメモ

```java
System.out.println(Arrays.asList(1, 2, 3));
System.out.println(List.of(1, 2, 3));

List<String> strings = List.of("first", "second");
System.out.println(strings.toString());

//[1, 2, 3]
//[1, 2, 3]
//[first, second]


//よくわからなかったのでもう一度
String foo = "a,b,c,d";

List.of(foo)
//→[ "a,b,c,d" ]

Arrays.asList(foo.split(",");
//→[ "a", "b", "c", "d" ]　　　これがしたかった！！
```
残りの人生のためのプログラミング 第-0回

# 今日が人生最後の日だとしたら

***"If today were the last day of my life, would I want to do what I am about to do today?"-Steve Jobs***

スティーブ・ジョブズが大学の卒業祝賀スピーチで述べた言葉です．素敵ですよね．今年で彼の死からちょうど10年ですし，これを胸に生きてみるのもいいかもしれません...


# 残り21915日

まあ，そんなこと急に言われたって無理．今日が人生最後って，そんな気しないし．
一応，人生の残り日数でも計算してみましょう．
日本人の平均寿命(男性)は81歳です．自分が今21歳なので人生残り60年，日になおすと...


~~~lastday.py
import datetime

today = datetime.date.today()
rip = datetime.date(year=2081, month=6, day=1)
print(abs(rip - today).days)
~~~

~~~
21915 days, 0:00:00
~~~


**21915日**
長いのか短いのかよくわかりませんね．


# メメント・モリって奴

自発的に意識できないなら強制的にさせればいい．
ってことで，せっかくだしジョブズの忘れ形見を有効活用しましょうか．

iPhone(Andoroidでも可)とLINE,LINE Notifyを利用します．


~~~mementomori.py
import requests
import datetime

class Routine:
	def __init__(self, name, once_every_N_days):
		self.name = name
		self.once_every_N_days = once_every_N_days
		self.content = "{}のは残りの人生{}日で後{}回．\n".format(name, days_to_die, days_to_die//once_every_N_days)
		routines.append(self)


if __name__ == '__main__':
	today = datetime.date.today()
	rip = datetime.date(year=2081, month=6, day=1)
	days_to_die = abs(rip - today).days

	routines = []
	call_mother = Routine("母と電話する", 30)
	meet_grampa = Routine("祖父に会う", 180)
	eat = Routine("飯を食う", 1/3)

	send = "\n"
	for s in routines:
		send += s.content
	
	send += "MEMENTO MORI"
	send_dict = {'message': send}

	TOKEN = 'hoge'
	url = 'https://notify-api.line.me/api/notify'
	TOKEN_dict = {'Authorization': 'Bearer ' + TOKEN}

	requests.post(url, headers=TOKEN_dict, data=send_dict)
~~~


![mementomori_notify.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578927/f7936faf-3a9b-1f38-ba4d-dcbb3185b4f8.png)

これをタスクスケジューラー等で登録すればひとまず完成．


# 次回　第21914回は...

上記のプログラムをもうちょっと有意義なものに変えていきます．タスクの登録・通知を実装しようかな．ゆくゆくはタスク管理ができるようになると嬉しいですね．

ちなみに今日はLINE Notifyの設定とか使い方で一日潰れましたが，特に後悔はしてません．あと21915日もあるし．
SNSシェアボタンにUTMパラメーターを付与する方法

# 概要

行動分析のためのGA4のUTMパラメーターをTwitterシェアのURLに追加したところ、
ツイート内に期待していたURLが出てこなかったため一工夫した話

**期待していたURL**

```
https://mysite.com/?utm_source=hogehoge&utm_medium=fugafuga&utm_campaign=piyopiyo
```

**ツイート内に含まれていたURL**

```
https://mysite.com/?utm_source=hogehoge
```

`&`で区切られてutm_medium以降は不要なパラメーターとして捨てられてしまっています。
上記を見て、雑な実装として自分でエスケープ（`& => %26`）してしまえばいいやと思って書き直したのが下記です。一応、動作するはずです。

```
?utm_source=hogehoge%26utm_medium=fugafuga%26utm_campaign=piyopiyo
```

なんだか不格好ですのでちゃんと実装していきます。

# 実装内容
```javascript
// hogehoge fugafuga piyopiyoの箇所は必要に応じて関数等で動的に実装
const utmSource = 'utm_source=' + 'hogehoge'
const utmMedium = 'utm_medium=' + 'fugafuga'
const utmCampaign = 'utm_campaign=' + 'piyopiyo'
const utmParams = encodeURIComponent('?' + utmSource +'&' + utmMedium + '&' + utmCampaign)
const url = window.location.href                 // シェアボタンはシェアするページに配置する想定
const text = 'ツイート本文 hogefugapiyo'            // 適当なツイート本文

const tweetUrl = 'https://twitter.com/intent/tweet?url=' + url + utmParams + '&text=' + text

window.open(tweetUrl);
```

今回はTwitterのみの記載となりますが、他のSNSシェアボタンでも同様の処理が必要となるかと思います。

# その他

エンコードの関数として`encodeURI()`があるが、こちらは`&`をエスケープしないため、`encodeURIComponent()`を利用する必要がある。
詳細は下記をご参照ください。

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
React + Next.js + Vercel デプロイはやっぱこれらしい

ReactのデプロイはやはりVercelが手軽で、あわせて、Vercelが開発をしているNext.jsを使うのが多いと思います。
React + Next.js + Vercelというのが唯一ではないですが、有力な構成候補だと思います。

Facebookは当然として、Netflix、Dropboxを始め数え上げたらきりがないぐらい。

##スクラッチ開発の呼吸、壱の型「サーバレス」、ビジネスロジックに全集中
　
サーバレスを利用することで、インフラ構築・運用のコストを下げ、その分、ビジネスロジックを実現するアプリ開発に資源を集中し、より多くの機能をより早くリリースしていくことがこれから一般化すると思います
初めてのLaravel ~Blog App~ 01(備忘録)


**[渋谷で働くエンジニア福さん](https://www.youtube.com/channel/UCqzJi2o7bAPtRD3tTFvi7zA)のYoutube動画,[実践で学ぶプログラミング入門](https://youtu.be/yaitzPzBzuI) の学習記録です。**

<h2>初期設定編</h2>
* composerでLaravelをインストール(MAMP使用)
* phpMyAdminから　新規テーブルを作成 = blog_app
* VScodeで作成したプロジェクトを開き、.envの中の設定をいくつか変更  
  (MAMPトップページより確認)  
    *   APP_Name (任意の名前）
    *   DB_PORT / DB_PASSWORD / DB_SOCKET 
　　　
*  MySQLのバージョンによって文字化けを防ぐための設定をapp/Providers/AppServicePreviders で行う
    *  `use Illuminate\Support\Facades\Schema;`  
    *  ``` public function boot()
        {
        //
        Schema::defaultStringLength(191);
        }```
* App/config/app.phpで 以下を設定
    * `'timezone' => 'Asia/Tokyo',`
    * ` 'locale' => 'ja',   `
EKSでNLBを使ってIPアドレスを制限しつつ外部公開する

## 構成
- EKS v1.19
- aws loadbaranser controller v2.2.0
- externaldns v0.7.6

## ポイント
- `spec.loadBalancerSourceRanges`で指定したIPアドレスのみを許可する
    - aws loadbaranser controllerのannotationで同じような挙動をすると思われる`service.beta.kubernetes.io/load-balancer-source-ranges:`があるけれど、公式ページで`spec.loadBalancerSourceRanges`を使ってくれとあった
    - NODEに自動アタッチされているSecurityGroupに自動的にルールがエントリされる
- NLBの場合、ALB ingressとは異なり、Service内でLoadbaranserとそこからルーティングされるNodePortServiceの２つの意味を一緒に定義することになる
    - 通信の流れは、NLB(80)→NodePortService(30082)→CotainerPort（30082）→コンテナ内のNginx(80)という感じだと思う
    - NodePortを指定せず、TargetPortだけでやっていたからか、その場合`spec.loadBalancerSourceRanges`が作用しなかった
- ELBを使うにあたりaws loadbaranser controllerが必要だったかはどうだったけかな。。。いらないかも


## マニフェストファイル

```nginx-replicaset.yaml
---
apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: nginx-replicaset-nlb
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx-nlb
  template:
    metadata:
      labels:
        app: nginx-nlb
    spec:
      containers:
        - name: nginx-container
          image: nginx:1.12
          ports:
            - containerPort: 30082
---
apiVersion: v1
kind: Service
metadata:
  name: aws-nlb
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: external
    service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance
    service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
    service.beta.kubernetes.io/aws-load-balancer-name: vamdemic-nlb
    external-dns.alpha.kubernetes.io/hostname: nginx.vamdemicsystem.com
spec:
  type: LoadBalancer
  ports:
    - name: "http-port"
      protocol: "TCP"
      port: 80
      targetPort: 80
      nodePort: 30082
  selector:
    app: nginx-nlb
  loadBalancerSourceRanges:
  - "12.34.56.78/32"
```
最新コミットから差分のあるファイルをscpでサーバーにコピーする

たとえば、仮想マシン上にウェブアプリの実行環境を構築し、ファイル編集は手元で行って動作確認するケースなどを想定。


## コマンド

以下の例では、サーバーのアドレスが`192.168.56.101`で、ユーザー名が`alice`だとします。また、サーバーのホームディレクトリ直下に`abcproject`ディレクトリがあり、これ以下の階層は、手元のGitリポジトリと同一であるものとします。

```bash
git diff --name-only | xargs -I '{}' scp '{}' alice@192.168.56.101:abcproject/{}
```


## 解説

```bash
git diff --name-only
```

で最新コミットから差分のあるファイル名を、Gitリポジトリのルートからの相対パスで取得します。

```bash
xargs command
```

で標準入力をcommandの引数に渡します。
`-I`オプションは置換文字列の指定です。コマンド文字列中の置換文字列を標準入力で置き換えます。したがって、標準入力にたとえば`index.html` `src/app.js`が渡された場合、

```bash
xargs -I '{}' scp '{}' alice@192.168.56.101:abcproject/{}
```

は

```bash
scp 'index.html' alice@192.168.56.101:abcproject/file1
scp 'src/app.js' alice@192.168.56.101:abcproject/src/app.js
```

と同じ動きになります。なお、`xargs`はオプション無しで使用した場合、`command file1 file2 file3`のように標準入力を一度にコマンドの引数に渡しますが、`-I`オプションを指定した場合は、標準入力は一行ずつ渡されます。

```bash
scp file target
```

で`file`を`target`にコピーします。もし、ポートを22から変更している場合は、`-P`オプションで指定します。たとえば、ポートが1234の場合は、以下のようにします。

```bash
scp -P 1234 file target
```

なお、このコマンドでは、新しく追加したディレクトリ内のファイルをコピーしようと思うと、「No such file or directory」のエラーになります。また、新規作成したファイルもコピーされません。その場合は、

```bash
scp -r src target
```

で`src`を再帰的に`target`下にコピーします。
【AWS】S3のストレージタイプ

#プログラミング勉強日記
2021年6月1日

#AWSのストレージサービス

| タイプ | 特徴 | 耐久性 | 可用性 |
|:--:|:--:|:--:|:--:|
| STANDARD | 通常S3にデータを保存するときに選ぶ。複数箇所にデータをコピーするため耐久性が非常に高い。いつでもデータにアクセスでき、標準的な値段のもの。(基本的には一番高い値段) | 99.999999999%(イレブンナイン) | 99.99% |
| STANDARD-IA | 標準の低頻度用アクセスストレージ。スタンダードに比べて安い。データの読み出し容量に応じて課金。 |  99.999999999%(イレブンナイン) | 99.9% |
| One Zone-IA | アクセス頻度は低いが、必要に応じてすぐに取り出すデータ向け。複数AZに分かれていないので、可用性は落ちる。バックアップのコピーや一時的なファイル保存向け。 | 99.999999999%(イレブンナイン) | 99.5% |
| RRS(Reduced Redundancy Storage) | 現在、使えるがAWS側は非推奨のストレージ。耐久性が最も低い。一時的なデータを保存する際に使われるものだった。値段は安いとされていたが、現在は更新されておらずSTANDARDの方が安くなっているので今は使われていない。 |  99.99% | 99.99% |
| Amazon Glacier | Glacierとして単独のサービスでありつつ、S3のストレージタイプとしても使われる。最も安いアーカイブ用のストレージ。データ抽出にコストと時間(3~5h)がかかる。ライフサイクルマネジメントで指定する。ボールロック機能でデータを保持する。中長期使わないデータを保管用として使うことに向いている。 |  99.999999999%(イレブンナイン) | N/A |

　IAはどちらも低頻度アクセス向け。その中でも重要なデータではないほうはOne Zone-IAを使う。値段は`STANDARD` > `STANDARD-IA` > `One Zone-IA`の順。

#S3 Intelligent-Tiering
　低頻度アクセスのオブジェクトを自動的に低頻度アクセス層に移動することでコストを削減することのできるストレージタイプ。アクセスパターンがわからない場合や中長期保存する用のデータストレージとして使うことが多い。基本的には30日間アクセスがないファイルは自動的に低頻度アクセス層に移動される。低頻度アクセス層のファイルにアクセスした場合は、自動的に高頻度アクセス層に移動する。
　高頻度アクセス層と低頻度アクセス層の2つに分かれてデータを保存する。低頻度アクセス層がデータ取得時間が長くなる分、料金が安い。
【はんちゃん備忘録】ボタンを押してる間オブジェクトを特定の位置に移動させる

#1. 初めに
この記事はUnity初心者の私が覚えたことを忘れないためのメモのようなものです。

#2. やる事
![Movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578980/83a7e155-b605-b537-567f-5f2f170fd3c4.gif)
 上のgif のように、ボタンを押している間は特定の位置まで移動させ、離すと初期位置に戻るようにする。この動画では2つのボタンで上下移動、離すと中央に戻るようになっています。

 それを応用して作ったゲームがこちらです。
![PlayMovie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578980/345ee7ec-6ab1-0c98-14bb-2f497d5a5c3a.gif)


これを応用したゲーム

https://play.google.com/store/apps/details?id=com.KHanchan.TwinShips



#3. スクリプト
```C#:Player.cs
using UnityEngine;

public class Player : MonoBehaviour
{
    public float speed = 1; //移動スピード
    private float step;
    private Vector3 direction1 = new Vector3(0, 0, 0);   //ボタンを押してない時の位置（初期位置）
    private Vector3 direction2 = new Vector3(0, 2f, 0);   //上ボタンを押した時に移動する位置
    private Vector3 direction3 = new Vector3(0, -2f, 0);  //下ボタンを押した時に移動する位置

    void Start()
    {
        this.gameObject.transform.position = direction1;    //ゲーム開始時に初期位置に移動
    }

    void Update()
    {
        //上ボタンを押した時
        if (Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.DownArrow))
        {
            step = speed * Time.deltaTime;
            this.gameObject.transform.position = Vector3.MoveTowards(transform.position, direction2, step);
        }

        //下ボタンを押した時
        else if (Input.GetKey(KeyCode.DownArrow) && !Input.GetKey(KeyCode.UpArrow))
        {
            step = speed * Time.deltaTime;
            this.gameObject.transform.position = Vector3.MoveTowards(transform.position, direction3, step);
        }

        //ボタンを押してない時
        else    
        {
            step = speed * Time.deltaTime;
            this.gameObject.transform.position = Vector3.MoveTowards(transform.position, direction1, step);
        }
    }    
}
```


上記スクリプトでは、キーボードの右矢印キーを押すと`direction2`の位置。左矢印キーを押すと`direction3`の位置。何も押していない状態だと__初期位置__(`direction1`)へ移動します。

移動速度はスクリプト上で`speed`の値を変えるか、アタッチしたオブジェクトのインスペクターから変更してください。

このスクリプトを操作したいオブジェクトにアタッチすれば下のgif画像と同じ動作になります。( `speed = 10`の場合 )
![Movie.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1578980/83a7e155-b605-b537-567f-5f2f170fd3c4.gif)

```C#:Player.cs
        //上ボタンを押した時
        if (Input.GetKey(KeyCode.UpArrow) && !Input.GetKey(KeyCode.DownArrow))
        {
            ...
        }

        //下ボタンを押した時
        else if (Input.GetKey(KeyCode.DownArrow) && !Input.GetKey(KeyCode.UpArrow))
        {
            ...
        }

```
このif文の条件に`!Input.GetKey(KeyCode.DownArrow)`および`!Input.GetKey(KeyCode.UpArrow`を入れているのは、ボタンが同時押しされた場合の対策です。

#4. まとめ

以上Unity初心者のメモ

https://play.google.com/store/apps/details?id=com.KHanchan.TwinShips
UE4にWiFi経由でAndroidアプリをDeployする方法


# UE4 Androidデプロイがめんどい

UE4便利なんですが、ARアプリなどを作成するとPC上では試せず、結構USB接続してDeployがめんどいわけです。

「めんどいなー」
「全人類同じこと思ってるだろうなー」
「賢い人、どうにかしてよー」

しかも、USB接続のたびに充電されて100％フル充電で、モリモリバッテリーを削っていく。

「こりゃいかんでしょ」

# 実は賢い人が既に解決していた

知らなかっただけで、Android11からはWiFiでアプリがDeployできるようになってました。

「まじで！？」

# ペア設定コードによるデバイスのペア設定

https://developer.android.com/studio/command-line/adb?hl=ja

によると、

1) ワイヤレス デバッグ 有効化
2) ペア設定コードによるデバイスのペア設定
3) デバイスへ接続

らしい。しかし、どうやらかこにUSBでデバッグを有効にしていると、自動的にWiFiもデバッグが有効になるようで、1)と3)だけでいいです。面倒な 2)はパスできます。

## 1) ワイヤレス デバッグ 有効化
開発者向けオプション→ファイやレスデバッグを有効

確かにありますね。
こいつを有効にします。

<img width=200 alt="Screenshot_20210601-113026.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/79763fcd-3c8f-5d61-d52b-0af402728164.png>


## 2) ペア設定コードによるデバイスのペア設定

次に「ワイヤレスデバッグ」をタッチします。
これ… 死ぬほどわかりにくくないですか！？？？

<img width=200 alt="Screenshot_20210601-113026.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/a8fe5b77-9627-1cfa-bc2a-99469fa0f30b.png>

そうするとオプションがひらくので「ペア設定コードによるデバッグデバイスのペア設定」をタッチします。
※ここにIPアドレスとポートが表示されますが、これはペア設定では使えません！！！

<img width=200 alt="Screenshot_20210601-113026.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/1f918283-3aa8-9129-6392-263f97221fb5.png>


はい、ここで、ようやく「adb pair」に用いるペアリングコードと、IPアドレス、ポートが表示されます。

<img width=200 alt="Screenshot_20210601-113026.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/33e75390-680a-fd29-1d09-98400a9ce4f5.png>


この例では、コマンドプロンプトなどから以下を実行しましょう。

```:うまくいった例
> adb pair 192.168.1.3:38058
Enter pairing code: 760348
Successfully paired to 192.168.1.3:43308 [guid=adb-XXXXXX]
```

IP/Port打ち間違いやペアリングコード誤りだと以下のようにエラー出ます。
よくよく確認しましょう。

```:失敗した例
> adb pair 192.168.1.3:38058
Enter pairing code: 760347
Failed: Wrong password or connection was dropped.
```

## 3) デバイスへ接続
ここまで来て、「IPアドレスとポート」に記載されている情報が使えるようになります。

<img width=200 alt="Screenshot_20210601-113026.png" src=https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/1f918283-3aa8-9129-6392-263f97221fb5.png>

```:デバイスへの接続と確認
> adb connect 192.168.1.3:43308
connected to 192.168.1.3:43308
> adb devices
List of devices attached
192.168.1.3:43308       device
```

# UE4からデプロイ

UE4のデバイスマネージャで確認してみましょう。

![SnapCrab_NoName_2021-6-1_21-43-51_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/121950/eac4e787-bc8c-f812-b64d-c32aacdcf10e.png)

普通に認識して、USB接続時と同様にDeployできるようになります！

これははかどる！！！