OmniAICreator/Qiita-1.07M huggingface dataset:
【Rails/ルーティング】Prefix, URIを好みの値に設定する方法とresourcesについて深ぼる

# 概要
Railsでルーティングを設定する際は「とりあえずresources脳」な僕ですが、今日はふと「自分でURLとか設定したいよな…」と思いました。
今回はそんな思いを叶えるべく、調べた内容をまとめます。
（resourcesの名前の起源も下の方で深ぼってみました！）

<br>

# 環境

* macOS Catalina 10.15.6

* ruby 2.6.5

* Rails 6.0.3.4

* MySQL : 5.6.47

* Bootstrap : 4.3.1

<br>

# 結論

<a href="https://railsguides.jp/routing.html">「Railsガイド : Railsのルーティング」</a>によると、
例えば「マイページ(users#show)」へのリクエストを次のように表現したいとき。

* prefix : users_profile

* URI : '/users/:id/profile'

``routes.rb``に以下のように記載します。

```app/config/routes.rb
Rails.application.routes.draw do
  get 'users/:id/profile', to: 'users#show', as: 'users_profile'
end
```

これを``rails routes``で確認すると、

| prefix | Verb | URI Pattern | Controller#Action |
|:-:|:-:|:-:|:-:|
| user_profile | GET | '/users/:id/profile | 'users#show' |

無事に設定できました！

<br>

# 確認

では、動作を確認しましょう。

## ターミナルでの操作

### 1. users_controllerを作成

```:teminal
% rails g controller users
```

<br>

### 2. ビューファイルの作成と記述

``app/views/users/show.html.erb``を作成し、次のように記述します。

```erb:app/views/users/show.html.erb
<h1>Users#show</h1>
```
<br>

### 3. URIを直打ちして確認

``localhost:3000/users/1/profile``と入力し、確認します！

![demo](https://gyazo.com/52257a0c268b11c6f733f7caaec906e9/raw)

成功です！

<br>

# そもそもresourcesって何？

望み通りのルーティングを作成できましたが、一つ疑問が残ります。

「いつも使ってるresourcesって何者？」

というわけで、またまた<a href=https://railsguides.jp/routing.html">Railsガイド</a>から引用します。

> リソースベースのルーティング (以下リソースルーティング) を使うことで、リソースベースで構成されたコントローラに対応する共通のルーティングを手軽に宣言できます。リソースフルなルーティングを宣言することで、コントローラのindex、show、new、edit、create、update、destroyアクションを個別に宣言しなくても1行で宣言が完了します。

この記述より、``resources :users``などは「7つのアクションを持つリソースフルなルーティング」ということができそうです。

しかし、次は「リソースとは何ぞ？」と思いました。もう少し読み進めましょう。

> ブラウザはRailsに対してリクエストを送信する際に、特定のHTTPメソッド (GET、POST、PATCH、PUT、DELETEなど) を使って、URLに対するリクエストを作成します。上に述べたHTTPメソッドは、いずれもリソースに対して特定の操作の実行を指示するリクエストです。リソースルーティングでは、関連するさまざまなリクエストを1つのコントローラ内のアクションに割り当てます。

これでもイマイチ微妙です。
ということで「Web リソース とは」とGoogleで検索してみました。

メタディスクリプションをサラッと読んで内容をまとめると「**Webリソース=Webサイトを構成するもの**」とのこと。

自分なりに噛み砕いてみると、Webを構成するものとは、

* ページ
* 保存された情報
* 投稿を保存するテーブル

<br>

であるならば、例えば...

* 一覧情報、かつそれをまとめたページを返すindexアクション
* 新たにテーブルにデータを保存するcreateアクション
* 既に存在するデータを削除するdestroyアクション

**これらのような「Web上のリソースを扱うアクション」をリクエストするルーティングを、リソースルーティングと呼ぶ**のにも納得がいきます。
なるほど、だからresourcesだったんですね...

<br>

# まとめ

* Verb 'URI', to: 'Controller#Action', as: 'Prefix'

* 上の記述で所望のルーティングを作成できる

* resourcesは「Webリソースを扱うアクションにリクエストするルーティング」という意味で用いられる(と予想している)
rpm と yum 違い

## 勉強前のイメージ

使い分けは怪しいけど、結局同じことをしているはず....

## rpmとyumの違い

結論から言うと
`rpm` はパッケージ単体のことを指す
`yum` はrpmを管理するマネージャーのことを指す

rpmはここに依存関係が記述されているファイルを持っているが、依存関係を管理してはくれない。
そこで、rpmのパッケージを管理してくれるのがyum。
個々のrpmを確認して、依存関係を解決しながら管理してくれるのがyumの役割

## rpmとyumの大きな特徴

### 依存関係の自動解決有無

rpmは自動で依存関係を解決できないので、yumを使用して自動解決を行う

### インストール時のパッケージファイルの有無

rpmはパッケージファイルを用意してインストールを行うが
yumはパッケージ名だけでよい

### 未インストールのパッケージ参照有無

rpmはパッケージ名が分かっていても情報を得ることは出来ないが
yumはパッケージ名から情報を得ることが出来る

## rpm

- パッケージを追加したり削除したりすることが出来る
- .rpmの拡張子がついたファイルを参照する
- rpmコマンドを使用する
- 依存関係を自動で解決出来ない

## yum

- rpmを管理し、依存関係を自動で解決してくれる
- yumコマンドを使用する
- リポジトリに存在している未インストールのパッケージを見ることが可能

## それぞれのコマンド

### rpm

- インストール

```
rpm -Uvh 【rpmパッケージ名】
```

- 削除

```
rpm -e 【rpmパッケージ名】
```

- パッケージの検索

```
rpm -qa 【rpmパッケージ名】
```


### yum

- インストール

```
yum install 【パッケージ名】
```

- 削除

```
yum remove 【パッケージ名】
```

- パッケージの検索

```
yum search 【パッケージ名】
```

## 勉強後のイメージ

なんとなく一緒な気はしてたけどちゃんと分かってよかった。
yumでインストール出来なくても、rpmファイルをyumでインストールしたらOKってことは分かったし、
自分でも前からやってた....

## 参考

- [【初心者にもわかる】rpmとyumの違いと使い分け一通り](https://eng-entrance.com/linux-package-rpm-yum-def)
- [rpm と yum を今更理解したい](https://qiita.com/Yuta_spade/items/2d829e33d7a9c1b36923)
- [【yum入門】yumとは何か？Linuxにおけるyumとrpmの違い](https://uxmilk.jp/9715)
- [Linux yum を基礎から理解する](https://www.kimullaa.com/entry/2020/01/19/101928)
ansible学習(環境構築編)

# 今更ながらAnsibleを勉強し始めた話（Mac環境編）

知っている人にとっては「今更Ansibleか？」と思われるかもしれませんが、  
人生において未だAnsibleを使っているような良い職場に出会えていない、残念エンジニアの私が勉強した内容をまとめていきます。

## 参考書籍

勉強にあたっては以下の書籍を参考にしています：

- [Ansible徹底入門 クラウド時代の新しい構成管理の実現](https://www.amazon.co.jp/dp/4798149942)

ただし、こちらは**3年前の書籍**なので情報が古い可能性もあり、  
個人的には以下の書籍の方が新しくておすすめです：

- [Ansible実践ガイド 第2版](https://www.amazon.co.jp/dp/B07B2T24V4)

前者の本だと、現在のバージョンでは使えない記述や誤りと思われる内容もありました。  
当時は正しかったのかもしれませんが、環境の変化に注意しましょう。

---

## Ansibleのインストール（Mac編）

私の環境は **macOS** です。  
WindowsやLinuxの方は他のサイトを参考にしてください。

### Step 1：Homebrewのインストール

まずは定番のHomebrewをインストールします。Macユーザーなら必ず入れておくべきツールです。

```bash
curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install | /usr/bin/ruby
```
# Homebrew + Python + Ansible + Vagrant環境構築メモ（macOS）

Homebrewが入れ終わったら、次はPythonを入れていこう。

```bash
brew install python
```

Pythonには `pip` という便利なパッケージ管理ツールが同梱されているので、これを使ってAnsibleをインストールします。

```bash
pip install ansible
```

# Vagrant + VirtualBox 環境構築メモ（Homebrew使用）

次にVagrantとVirtualBoxを導入するために、まずはHomebrew Caskのインストールを行います。  
Caskのインストールが終わったら、そのままVirtualBoxとVagrantをインストールします。

```bash
brew tap caskroom/cask
brew cask install virtualbox vagrant
```

# Ansible環境構築メモ（Vagrant + CentOS編）

ここまでうまくいったら、**一旦インストールは問題なし**。  
この後から実際にAnsible環境を作っていきます。

まず、ローカルに適当に `ansible_test` というフォルダを作成し、その中にCentOSのイメージをダウンロードします。

```bash
mkdir ansible_test
cd ansible_test
vagrant init bento/centos-7.2
```

# Vagrant仮想マシンのセットアップとSSH接続確認メモ

`vagrant init` を実行すると `Vagrantfile` が作成されるので、そのファイルを以下のように修正していきます。

## Vagrantfileの修正内容

```ruby
# ゲストOSの自動アップデートを無効化
config.vbguest.auto_update = false
```

# ネットワーク設定の有効化とIPアドレスの変更
config.vm.network "private_network", ip: "192.168.33.13"

# Vagrantで仮想マシンを作成してSSH接続するまでの手順メモ
## 仮想マシンの作成

修正が終わったら以下のコマンドを実行して、仮想マシンを作成します。  
※この処理は結構時間がかかります。

```
vagrant up
```

# Vagrant環境でSSH鍵ログインの設定と確認

SSH鍵でログインできるように、以下の設定を行います。

```bash
vagrant ssh-config --host 192.168.33.13 >> ~/.ssh/config
```

# SSH接続確認と環境構築の完了

実際にSSHでログインできることを確認します。

```bash
ssh 192.168.33.13
```


## 環境構築、ひとまず完了

ここまで終わったら、ひとまず環境構築は完了です。

あとは実際に **Playbook** を使って、**Ansible** を活用していくフェーズになりますが、  
これはまた**次回**にしたいと思います。

---

ちなみに、作成したマシンが気に入らなかった場合は、  
以下のコマンドで**あっさり削除**することも可能です。

```bash
vagrant destroy
```

ご静聴ありがとうございました。
【zsh】僕のalias【随時更新】

メモ帳代わりにエイリアスを載せておきます。誰かの参考になれば。

```zsh:~/.zshrc
# git
alias glt="git log --graph --pretty=format:'%x09%C(auto) %h %Cgreen %ar %Creset%x09by \"%C(cyan ul)%an%Creset\" %x09%C(auto)%s %d'"

# docker
alias dd='docker-compose down'
alias di='docker images'
alias dcp='docker container ps'
alias dcla='docker container ls -a'
alias d-c='docker-compose'
alias drs='cd /Users/kenya/auto_schedule && docker-compose run --rm -p 3001:3001 back'
alias drb='docker-compose run --rm back'
alias drr='docker-compose run --rm back bin/rspec'
alias drbrcs='docker-compose run --rm back rails console --sandbox'

# ruby
alias be='bundle exec'

# yarn
alias yd='cd /Users/kenya/auto_schedule/front && yarn dev'
alias yrlf='yarn run lint --fix'

# auto_schedule
alias cdf='cd /Users/kenya/auto_schedule/front'
alias cda='cd /Users/kenya/auto_schedule'

alias ls='gls --color=auto'
alias rm='rm -i'
alias ..='cd ..'
alias mv='mv -i'
alias cp='cp -i'
```

プロジェクトなどで何度も同じディレクトリに入って同じコードを打つなら

```zsh:~/.zshrc
alias drs='cd /Users/kenya/auto_schedule && docker-compose run --rm -p 3001:3001 back'
alias yd='cd /Users/kenya/auto_schedule/front && yarn dev'
```
のようにディレクトリ移動とコマンドをくっつけると便利です。絶対パスなので、どこからでも使えます。
天気予報をpythonでスクレイピング 

# 天気予報のスクレイピング

## はじめに

自作しているIoTシステムで天気予報が必要になりました。

BeautifulSoupを使ってtenki.jpから草津市の時間と降水確率を取得しました。

## 環境

pythonでは`beautifulsoup4`が必要になります。

```
conda install beautifulsoup4 requests -y
```

## スクレイピング

Chromeで検証をして、関わる部分のクラスやタグを調査。
毎時の降水確率が欲しかったので調べてみると、

class = forecast-point-1h
class = prob-precip
span の中にデータがあった。

そのため、取り出し方は以下のコードになる。

```python:scraping

# -*- coding: utf-8 -*-

import requests
from bs4 import BeautifulSoup


#tenki.jpの目的の地域のページのURL(滋賀県草津市)
url = 'https://tenki.jp/forecast/3/16/4410/13208/'

#HTTPリクエスト
r = requests.get(url)

bsObj = BeautifulSoup(r.content, "html.parser")

kusatu_1h = bsObj.find(class_="forecast-point-1h")

## 時間
h = []
hour = kusatu_1h.find(class_="hour")
h_tem = hour.find_all('span')
h = [int(h_tem[x].string) for x in range(len(h_tem))]
print(h)

## 降水確率
kousui = kusatu_1h.find(class_="prob-precip")
k_tem = kousui.find_all('span')
k = [k_tem[x].string for x in range(len(k_tem))]
print(k)
```

```sh:実行結果
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]

['(%)', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '---', '90', '90', '70', '70', '70', '80', '70']
```


## 参考

[webスクレイピングで今日の天気と気温を取得 - Qiita](https://qiita.com/RIRO/items/1b67b0418b08a52de0d6)
【OpenFOAM/シェル】チュートリアルのAllrunを解読

#はじめに
OpenFOAMのチュートリアルケースの中にはAllrunというシェルスクリプトが入っています．内容はシミュレーションのプリ処理（メッシュ作成，並列化処理etc）で，これを使えばいちいち手打ちでコマンド実行することなくシミュレーションを開始できます．処理内容はケースによって様々です．ここではmotorBikeのAllrunについて解読した内容をメモします．自分で読むとシェルスクリプトの勉強になりますね．

#環境
Windows 10 Home バージョン 1903
OpenFOAMv7
WSL1

#Allrun
パス
/opt/openfoam7/tutorials/incompressible/pisoFoam/LES/motorBike

ソースコード

```sh:Allrun
#!/bin/sh
cd ${0%/*} || exit 1    # Run from this directory
# ${0%/*}はAllrun実行場所から見たAllrunの相対パス．どこから実行してもAllrunにcdする

# Source tutorial run functions
. $WM_PROJECT_DIR/bin/tools/RunFunctions
# RunFunctionsもシェルスクリプト．
# “.”コマンドで読み込むことでAllrunからRunFunction内のスクリプトが使用可能になる

# copy motorbike surface from resources directory
cp $FOAM_TUTORIALS/resources/geometry/motorBike.obj.gz constant/triSurface/

runApplication blockMesh
# blockMeshを普通に実行するのとほぼ同じ．runApplicationによって引数解析を行っている

cp system/decomposeParDict.hierarchical system/decomposeParDict

runApplication decomposePar -copyZero
# -copyZeroで0ディレクトリを各プロセッサのディレクトリにコピペ

cp system/decomposeParDict.ptscotch system/decomposeParDict
runParallel snappyHexMesh -overwrite
# -overwriteでblockMeshで作成したメッシュを上書き

find . -type f -iname "*level*" -exec rm {} \;
# "level"や"Level"を名前に含むファイルを削除している．不要だから（たぶん）

runParallel renumberMesh -overwrite
# renumberMeshはセル番号を振り直してる．計算高速化のため（たぶん）

runParallel potentialFoam -initialiseUBCs
# -initialiseUBCsで速度の境界条件を初期化

runParallel $(getApplication)
# controlDictのapplicationに書かれているソルバを実行

#------------------------------------------------------------------------------
```
AWS S3に保存しているファイル名を取得する（1000件以上）

# やりたいこと
AWS S3のとあるバケットのとあるフォルダ以下に保存しているファイル名を全て知りたい。
このとき、とあるバケットのとあるフォルダ以下にはファイルが1000件以上ある。

**注意点**
list_objectは1000件までしか取得しないので、ファイル情報を取得する処理を工夫する必要がある。

## 方法
https://boto3.amazonaws.com/v1/documentation/api/latest/guide/paginators.html
に記されている通り。


# コード
※awsのコンフィグは設定しておく。
※python3で実行する。

```python:sample.py
import boto3

MY_REGION = 'リージョン名';
MY_BUCKET = 'バケット名';

# バケット以下のディレクトリ
TARGET_PATH = 'tmp/YYYY/MM/DD/';

client = boto3.client('s3', region_name=MY_REGION)
paginator = client.get_paginator('list_objects')

# フィルタリング設定
operation_parameters = {
    'Bucket': MY_BUCKET,
    'Prefix': TARGET_PATH
}

page_iterator = paginator.paginate(**operation_parameters)

# S3のオブジェクトキーを出力
for page in page_iterator:
    for content in page['Contents']:
        print(content['Key'])

```

上記コードの出力例

```
tmp/YYYY/MM/DD/0001.txt
tmp/YYYY/MM/DD/0002.txt
tmp/YYYY/MM/DD/0003.txt
....
tmp/YYYY/MM/DD/1000.txt
tmp/YYYY/MM/DD/1001.txt
tmp/YYYY/MM/DD/1002.txt
```

# memo
・個人的に1000件以上あるファイルの情報を取得するのが難しかった記憶があったが、最近は簡単にできるんだと少し感動したので記事にしました。
・また、特定のフォルダ以下というようなフィルタリングも指定できるのを知らなかったので、メモメモ。
OpenCVの初めてのプログラム

##OpenCVの使い方
1. 前回紹介した記事では、DebugとReleaseを決めてしまっているので次のコードを追加させるとうまくいくと思います。opencv_world430d.libの数字はダウンロードしたバージョンに変更してください。

```
#if _DEBUG
#pragma comment(lib,"opencv_world430d.lib")
#else
#pragma comment(lib,"opencv_world430.lib")
#endif;
```

2.とりあえずは次の2つをインクルードさせましょう。

```
#include<opencv2/opencv.hpp>
#include <iostream>
```

##超シンプル画像を表示させるだけのプログラム

パスは人によって違うので、随時更新しましょう。この段階で動かなければ設定が違うかも、、
ここのコードの説明は次回します。


```
#include <opencv2/opencv.hpp>
#include<iostream>

#if _DEBUG
#pragma comment(lib,"opencv_world430d.lib")
#else
#pragma comment(lib,"opencv_world430.lib")
#endif

using namespace cv;	

int main() {


	Mat img = imread("C:\\opencv\\sources\\samples\\data\\lena.jpg");

	imshow("View", img);

	waitKey();

	return 0;


}
所属するOrganizationのリポジトリにプッシュできない問題を解決

コミュニティ貢献活動をしていて直面し、解決した問題を共有します。

# この記事について
- 公式ページのソースを記載しています。最新の情報は公式ページを参照してください。
- ソースコードや実行コマンドは、個人情報を保護するために、意味が変わらない程度に編集しています。
- 不明点等ございましたら、お気軽にお問い合わせください。

# 直面した問題
タイトルにもあるように、GitHubの自組織Organizationリポジトリに対してプッシュできない問題に直面しました。

## 事象
メンバーロールで所属しているOrganization内の、他人がforkしたリポジトリに対してpushができません。
pushしようとすると、以下のエラーメッセージが出力されます。

```
C:\Users\MyPC\test-organization\test-repository>git push -u origin test
remote: Permission to test-organization/test-repository.git denied to kobaji.
fatal: unable to access 'https://github.com/test-organization/test-repository.git/': The requested URL returned error: 403
```

【補足】

Organizationには以下のロールがあります(参考：[「GitHubドキュメント>Organization のリポジトリ権限レベル」])。

- 支払いマネージャー
- オーナー
- メンバー

## 原因(当方の場合)
結論を言うと、Organizationの設定にて、リポジトリに対してRead権限を付与していないためでした。

これは[「GitHub公式ドキュメント>Organization の基本レベルの権限の設定」]にも記載されています。

> デフォルトでは、Organization のメンバーは Organization のリポジトリに対する読み取り権限を付与されます。

> Organization のリポジトリに対する管理者権限があるユーザが、リポジトリに対してそれより高いレベルの権限を付与すると、基本レベルの権限は、付与された高い権限によってオーバーライドされます。

ドキュメントのとおり、オーナー権限で「Your profile」>「Organizations」>「Settings」>「Member privilegs」>「Base permissions」を確認したところ"Read"になっていました。

## 対処法
「Base permissions」を"Write"にしました。

## 結果
pushできました！

## おまけ
<!--### 解決時の思考回路、マインド

### その他考えられる原因-->

### その他解決法
上記の方法では、対象のOrganizationに所属する全メンバーに対し、また対象のOrganization内の全リポジトリに対し、一括で権限を変更します。それだと困る場合に、代替案をいくつか挙げます。

方法|特徴
---|---
[チームを作成し、アクセスを管理する]|複数リポジトリがある場合に、チームごとにアクセス権を付与することができます。
[個人ごとにアクセスを管理する] |対象のOrganization内の全リポジトリに対し、個人のロールを変更することができます。


<!-- Links -->

[「GitHubドキュメント>Organization のリポジトリ権限レベル」]: https://docs.github.com/ja/free-pro-team@latest/github/setting-up-and-managing-organizations-and-teams/permission-levels-for-an-organization
[「GitHub公式ドキュメント>Organization の基本レベルの権限の設定」]: https://docs.github.com/ja/free-pro-team@latest/github/setting-up-and-managing-organizations-and-teams/setting-base-permissions-for-an-organization
[チームを作成し、アクセスを管理する]: https://docs.github.com/ja/free-pro-team@latest/github/setting-up-and-managing-organizations-and-teams/managing-team-access-to-an-organization-repository
[個人ごとにアクセスを管理する]: https://docs.github.com/ja/free-pro-team@latest/github/setting-up-and-managing-organizations-and-teams/managing-an-individuals-access-to-an-organization-repository
Amplify でサインアップしてきたユーザーを特定のグループに自動で追加するようにする

# はじめに

とあるアプリケーションで、管理者ユーザーと一般ユーザーとで提供する機能を分けたいと思った時に、どう実現するのが良いか調べたら、Cognito ユーザープールのグループ機能を使って権限管理すると良いらしいということだったので、Amplify でその辺を自動構成する方法を調べました。

以下のような運用を考えていました。

1. 一般ユーザーはアプリケーションからサインアップできるようにしたい
2. 管理者ユーザーは数人なので Cognito ユーザープールに直接追加すれば良い

サインアップを利用するのは一般ユーザーなので、サインアップしてきたユーザーは一般ユーザー用のグループに自動で追加するようにします。

記事執筆時点の Amplify CLI のバージョンは下記のとおりです。

```sh
$ amplify --version
4.29.6
```

# amplify auth add

`amplify auth add` コマンドを実行して、以下のように選択していきます。

グループへの自動追加の構成以外はデフォルト値をそのまま選んでいます。

```sh
$ amplify auth add
```

```
Do you want to use the default authentication and security configuration?
Default configuration
```

```
How do you want users to be able to sign in?
Username
```

```
Do you want to configure advanced settings?
Yes, I want to make some additional changes.
```

```
What attributes are required for signing up?
Email
```

**重要なのは以下の選択肢**。

有効にしたい機能を聞いてくるのですが、ここに `Add User to Group` という項目があって、これが今回実現したい内容を自動構成するための項目です。

この機能を有効化すると、ユーザーの確認後（Post Confirmation）のトリガーで、指定のグループに自動的に追加してくれる Lambda トリガーを作ってくれます。

```
Do you want to enable any of the following capabilities?
Add User to Group
```

で、どのグループに追加するかを聞いてくるので、一般ユーザー用のグループ（例: `Users`）を指定します。

```
Enter the name of the group to which users will be added.
Users
```

```
Do you want to edit your add-to-group function now?
No
```

グループが存在しない場合はトリガーが自動で作成してくれるらしいので、グループをあらかじめ作る必要はありませんでした。

最初の `amplify auth add` で `Manual configuration` を選んで大量の質問をさばきつつグループを作成したり、 `amplify auth update` を実行して後からも作成できます。

Lambda トリガーを後から追加する方法はよくわかりませんでした。

# まとめ

以上の内容は以下の Amplify CLI の公式ドキュメントに記載されています。

- [Advanced workflows - Lambda Triggers - Amplify Docs](https://docs.amplify.aws/cli/usage/lambda-triggers)

ただ、なかなか見つけられなかったのと、ググるとこの機能が追加される前だったからか、頑張って CloudFormation テンプレートを直接書き換えて、自作した Lambda トリガーを割り当てている例ばかり（調べ方が悪いのかもしれません）がヒットしたので、記事にしてみた次第です。

以上。
ARM CPU のQEMUによるエミュレーションの高速化

# Linux のアプリケーションをエミュレートしたいとき

ホストOSもLinuxの場合、[QEMU ユーザーモードエミュレーション](https://www.qemu.org/docs/master/user/index.html) を使うとかなり早くエミュレーションできます。ハードウェアのエミュレーションはしないのでARM用Linuxとかは動かせません。Ubuntu/Debianなら `apt-get install binfmt-support qemu-user-static` で自動的にARM用Linuxアプリを実行できるようになります。

# ARM用のOSをエミュレートしたいとき
## ホストCPUがARMではないとき
忍耐力を高めて遅さに耐えて下さい

## ホストCPUが32bit ARMでゲストCPUが64bit ARMのとき
忍耐力を高めて遅さに耐えて下さい

## ホストCPUが32bit ARMでゲストCPUも32bit ARMのとき
`qemu-system-arm -machine virt -cpu host -enable-kvm`でKVMによる圧倒的な高速化ができます。ただしホストCPUは Cortex A15 などの仮想化機能を含む必要があります。

## ホストCPUが64bit ARMでゲストCPUも64bit ARMのとき
`qemu-system-aarch64 -machine virt -cpu host -enable-kvm`でKVMによる圧倒的な高速化ができます。

## ホストCPUが64bit ARMでゲストCPUは32bit ARMのとき
`qemu-system-aarch64 -machine virt -cpu host,aarch64=off -enable-kvm`でKVMによる圧倒的な高速化ができます。**qemu-system-armを64bit ARM CPUで使うとKVMによる高速が現状ではできません**。
【Go】CloudFrontの署名付きURLでプライベートコンテンツを配信

Golangで署名付きURLを発行します。

```golang

import 	sign "github.com/aws/aws-sdk-go/service/cloudfront/sign"

func main() {

type CFConfig struct {
	KeyID   string
	Domain  string
	KeyPath string
}

// cloud front config
cfConf := &model.CFConfig{
	KeyID:   "xxxxxxxxxxxxCQ"
	Domain:  "http://xxx.cloudfront.net",
	KeyPath: "key/xxxxxxxxxxxxCQ",
}

	privKey, err := sign.LoadPEMPrivKeyFile(r.cfConf.KeyPath)
	if err != nil {
		log.Println("failed to load pem file:", err)
		return "", err
	}

	keyID := r.cfConf.KeyID
	signer := sign.NewURLSigner(keyID, privKey)

	path := "s3アクセスを許可したいコンテンツのパス"

	signedURL, err := signer.Sign(r.cfConf.Domain+path, time.Now().Add(1*time.Hour))
	if err != nil {
		log.Fatalf("Failed to sign url, err: %s\n", err.Error())
	}
	return signedURL, err
}
個人的SQL Serverまとめ

#前書き
SQL Serverを扱える人が周りにいないので何かあった時のためにまとめ。
書く前からOut of dateな感じがバリバリする…
当方のテーブルの列名は太古の昔の名残で全部大文字なので予約語は基本的に小文字でござい

#環境
Microsoft SQL Server 2014(2020/11現在)

* ちょっと古い
* FOR JSONが使えたらどんなに良かったか

#select

```sql:select.sql
--基本の文
select [列名1], [列名2] from [テーブル名1]

--その他
--テーブル結合系
inner join [テーブル名2] on [テーブル名1].[列名1] = [テーブル名2].[列名2]　--内部結合
left join [テーブル名2] on [テーブル名1].[列名1] = [テーブル名2].[列名2]   --左外部結合
right join [テーブル名2] on [テーブル名1].[列名1] = [テーブル名2].[列名2]  --右外部結合
cross join [テーブル名2]                                                --クロス結合
full join [テーブル名2]                                                 --完全外部結合

--抽出条件(グループ化前)
where [列名1] = [値]
  and [列名1] like '[値]%' --ワイルドカード
  or  not [列名1] in ('[値]','[値]') --複数の値から抽出

--グループ化
group by [列名1]

--抽出条件(グループ化後)
having [列名1] = [値]

--並べ替え
order by [列名1] asc　 --昇順
       , [列名2] desc; --降順
```

ちょっと特殊な使い方
selectでテーブル1から抽出したデータでテーブル2がcreateされる


```sql:select_into.sql
select * into [テーブル2]
from [テーブル1];
```

#insert
```sql:insert.sql
--挿入する値と列が一致している場合
insert into [テーブル名] 
values ('[値]','[値]');

--挿入する値と列が一致していない場合
insert into [テーブル名] 
([列1],[列2]) 
values ('[値]','[値]');

--select結果を挿入する場合
insert into [テーブル名1]
([列1],[列2]) 
select * 
from [テーブル名2] ;
```

#update
```sql:update.sql
--指定した列のすべてのレコードを更新
update [テーブル名1]
set [列名] = [値]

--条件を指定して更新
update [テーブル名1]
set [列名] = [値]
where [列名] = [値];

--select結果を使って更新
update [テーブル名1]
set [テーブル名1].[列名1] = [テーブル名2][列名2]
  , ...
from [テーブル名1]
inner join [テーブル名2] on [列名1] = [列名2];
```
#delete(&truncate)
```sql:delete.sql
--条件に当てはまるレコードを削除(where句を書かなければ全件削除)
delete from [テーブル名1]
where [列名1] = [値];

--その他の全件削除(基本こっち)
truncate table [テーブル名1];
```

#create
```sql:create.sql
--テーブル作成
create table [テーブル名](
  [列名1] [型] [項目長]
, [列名2] [型] [項目長] not null --null不可
, [列名3] [型] [項目長] default [値] --初期値の設定
, primary key([列名1], [列名2])
);

--view作成
create view [ビュー名] as
select * from [テーブル名]; --クエリ

--ストアド作成
create procedure [ストアド名]
as
begin
begin try --この中のエラーでエラーが出るとcatchが呼ばれる

   return(0)
end as try
begin catch

end as catch
  --エラー後の処理
end as

```
ストアドについては長くなるので改めてまとめたい

#関数その他
```sql:others.sql
     --日付取得
     , getdate()
	 --表示形式変換
	 , convert(nvarchar, getdate(), 111) --111の部分を変えると形式が変わる
	 --型変換
	 , cast([列名] as varchar)
	 --ゼロパディング等
     , format([列名],'0000')
	 --条件分岐
     , case
	      when then
          else
       end as as
	 --文字列内検索 
     , charindex( 検索文字列, 検索対象文字列[, 位置 ] )
	 --文字切り取り
     , substring([列名],1,1)
	 --列名取得
     , col_name(object_id('[テーブル名]') , 列数 )
	 --レコードナンバー作成
     , row_number() over (partition by [列名] order by [列名]desc)
     --切り捨て
	 , floor([列名])
     --切り上げ	
	 , ceiling([列名])
     --四捨五入
	 , round([列名],桁数)
```

とりあえず以上
全然書ききれないので今後追加したい
OWASP ZAP わかりにくいところメモ

# 2つのスキャン
passive scan(静的)とactive scan(動的)がある
passiveはspiderによる通常アクセスの結果だけで分析
activeは積極的に攻撃

## アクティブスキャン
contextに関係あるURLのみ含める(SaaSとかは入れないように！）
ポリシーは広めに テクノロジー欄で不要なものは削る

## プラグイン
### fuzzer
fuzzingができる。numberが使いやすいかも

## script
静的&動的スキャン時に実行してくれるスクリプト
まずmarketplaceからインストールする.

スクリプト欄を右クリックでonにすると、各スキャンに組み込まれる

# CI/CDへの組み込み
GitHub Actionsの場合、2種類あり
- https://github.com/zaproxy/action-baseline
- https://github.com/marketplace/actions/owasp-zap-full-scan

baselineは軽めで、ほとんど機能なし (passive scan) ログイン不可
full scanは重め。passive + active。なぜかajax spiderは行いません。
-j オプションでajax spiderが追加できるので推奨です


# できること
試験とともに、issueを作成可能です。
不要なアラートは無効化できます
# 制約
Actionsのサーバからscanするサービスにアクセスできる必要があります
APIとフロント双方です。
# Q&A
## AWSへの申請は必要ですか？
不要になりました。

## これをやれば完璧ですか？
ある程度は防げますが、物足りないところです。
別途pen testのノウハウが必要です。

### 防げない例

- アプリレベル認証認可実装のミス
- AWSの設定不備 これはSecurity Hubなどで対応
- 3rd party脆弱性 これはrenovateなどで防ぎましょう
専門担当者のペネトレーションテストや、外部ベンダーの脆弱性検査が必要です。
DASTは誤検知が多く、残念ながら開発者だけで完結させるのは難しい状態です
vim pluginsをインストールしてみましょう

# vim-pluginとは
vimもしくはneovimというテキストエディタを使用していく上でそのままでは手が届かないような機能を追加したり、カラースキームを追加したりなどといった事をするもののことを言います。
多くのものはGitHub上で公開されていて手軽に探すことができます。

#pluginをインストールするには
純粋なvimでも簡単にpluginを追加することができます。
windowsの場合は、`~/vimfiles/pack/適当なパス/start/`
macos等の場合は、`~/.vim/pack/適当なパス/start/`の中に入れれば自動で確認されます。
また、neovimを使用する際にはwindowsでは`~/AppData/Local/nvim-data/site/pack/適当なパス/start` 
他の場合では`~/.local/share/nvim/site/pack/適当なパス/start/`になります。
`適当なパス`というのは自分で好き名前で問題ありません。私が確認をしたところでは`適当なパス`でも問題は生じませんでした。しかし、このようなところで引っかかると厄介なので半角文字で`plugins`などにするといいでしょう  
また、自分で一個ずつダウンロードするのではなく一気に管理をしたいという場合ではプラグインマネージャーが使われる場合もあります。
代表例としていくつか上げると[vim-plug](https://github.com/junegunn/vim-plug), [minpac](https://github.com/k-takata/minpac), [dein.vim](https://github.com/Shougo/dein.vim)があります

例えば、vim-plugを使う場合は[ここ](https://github.com/junegunn/vim-plug#installation)に沿ってインストールを行います。
その後、vimrcに以下のように書き込むことによってプラグインを自動で追加してくれるようになります

```vim:~/.vimrc
call plug#begin('~/vimfiles/plugged')
"GitHubのリポジトリを使用する場合
Plug 'Users/Repository'
call plug#end()
```
これによって`~/vimfiles/plugged`の中で自動で`git clone`をしてvim起動時に読み込んでくれるようになります。
もちろん`'~/vimfiles/plugged'`の部分を変更するとそこのフォルダで追加することができるようになります

#vim-pluginslist
プラグインマネージャーだけでも4種類以上のものがあり、似たような動きの違うプラグインのことも考える山のようなプラグインがあり見つけるのが大変になっていきます。そこで、[vim-pluginlist](https://github.com/mirachan010/vim-pluginlist)を利用するとプラグイン一覧とそれぞれのREADMEが見れるため、手軽にどんなプラグインがあるのかと物色できるようになります。

また、きっとどこかのだれかがもっと簡単にこういう事ができるものを作ってくれることを祈っています。
どうやってゼロトラストネットワークを構築する？

#1.さて...システムをどうやって作ろう...
<a href="https://qiita.com/YU_GENE/items/5b0f3f401d236aa93c5d">前回</a>、ゼロトラストネットワークとはなんぞやについて簡単に語った。
端末、人などから通信の全てを認証するゼロトラストネットワークなんて、簡単に実装できるわけがない。
##認証と認可
前回は結構曖昧に話していたが、認証と認可の違いをここではっきりしておく。
一連の通信の中で、認証はセッションごと、認可はリクエストごと行われる。
例えばどこかのサーバに繋ぐときに行われるのが「認証」、サーバに何かしらのアクションを要求するときに行われるのが「認可」である。今後、この二つをきちんと区別して書き残していきたい。
PKI(公開鍵基盤)は通信の安全性を証明するのに用いられる。これは、「認証」の技術である。

わかりやすく言えば、「この通信は間違いなく〇〇さんからの通信だよ！」というものである。

次に認可についてである。ゼロトラストネットワークシステム構築の重要性はこちらの認可のシステムをまずメインに作っていきたい。

わかりやすく言えば、「このコマンド(アクション)は〇〇さんからの命令だけど、実行していいかな？」というものである。unixシステムのsudoなども認可などに近いような気がする。

どちらも、ゼロトラストを実現する上で欠かせない技術である。
#2.認可はどうやって行われる？
現在のほとんどのシステムの現段階の認可-「アクションを通していいか」っていうのは「管理者権限があるか」に収束すると思う。
前回話したように、ゼロトラストを実現する上で、認可のために必要な要素は管理者権限だけではない。場所、IP、などなどから作成される「エージェント」が必要である。
##エージェントとは
ネットワークエージェントとは、ネットワークリクエストをするエンティティ(端末とか)についてわかっているデータの組み合わせのことをいう。
エージェントのデータフィールドは以前述べた認可を下すための様々な情報である。挙げられるものとして、IPアドレス、位置情報などに加え、エージェントの参考スコア、ユーザの居住地、デバイスメーカなどもある。ここで大事なのは、
####データフィールドの標準が存在しないこと
である。つまり、認可を下すにあたって必要なデータ( =特徴量)が定まっていないのである。
今回のプロジェクトでは、この特徴量の算出から簡単に行ってみたいと考えている。
多分、データフィールドに関してはJSONやらXMLなどにまとめることになりそうである。
では、次にエージェントを通してどのように「認可」を下すか見ていく。
#「認可」アーキテクチャ
認可とは、先ほど述べたとおり、これ、実行していいの？というものである。端末自体の「認証」は既に済んでいるものとして考える。
ゼロトラストの認可アーキテクチャは主に4つのアーキテクチャから構成される
・エンフォーサ
・ポリシーエンジン
・トラストエンジン
・データストア

エンフォーサはデータプレーンに属していて、その他はコントロールプレーンに分かれている。
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/718725/f04783c3-9002-8af4-46ca-e09ee686c007.png" width=80%>

以下にそれぞれの特徴を書いていく。
###エンフォーサ
エンフォーサはポリシーエンジンとのやりとり(＝認可リクエストそのもの)を行う。
###ポリシーエンジン
ポリシーエンジンは、認可の判断を決定するコンポーネントである。その際にリスク分析を行うのがトラストエンジンである。ポリシー(ルール)自体は、ポリシーストレージとして別の場所(理想的にはバージョン管理システム)に格納するのが望ましい。
トラストエンジンから返されたエージェントを受け取り、ポリシーと照合して、分析を行う。
###トラストエンジン
トラストエンジンは特定のリクエストに対してリスク分析を行うシステムである。
最終的な認可の判断にこの機構から算出されるスコアを用いることになる
この判断には静的なルールに加えて、機械学習モデルも導入するのが望ましい。
そして、何よりトラストエンジンは、先述したエージェントを生成する。
###データストア
認可の判断に使われるデータストアである。システムは現在と過去の状態を保管し、認可の判断の際に、トラストエンジンとやりとりをしながらデータを取得していく。

###まとめると...
簡単な例を引き合いに出して考える。
AliceはBobの会社のサービスに近所のコーヒーショップからアクセスしようとしている。

1. AliceはBobの会社のサービスにアクセス申請をする。

2. Aliceの端末とリンクしている(内蔵されているエンフォーサ)はコントロールプレーン(ポリシーエンジン)に向かってサービスへのアクセスを要求する

3.ポリシーエンジンはエンフォーサからリクエストとコンテキストをポリシーと比較するべく、リスク分析をするトラストエンジンにそのデータを渡す。

4.トラストエンジンは受け取ったデータ、そして過去のデータなどから認可のためのスコアを算出。ポリシーエンジンに返す。

5.ポリシーエンジンはそのスコアと静的な情報(リクエストやそのコンテキスト)から認可の判断を下す。

6.エンフォーサはポリシーエンジンから認可の可否を受け取り、端末に通知する。

7.認可が下りた場合、Aliceは一時的にBobのサービスへのアクセス権を獲得する。

といったところだろう。

そのほか、ユーザ、端末、アプリケーション自体の信用はそれぞれなされなければならないので、憂慮するべき項目はたくさんあるのだが、とりあえず仮定のポリシーから認可の判断を下す、トラストエンジンの簡易版をとりあえず作ってみたいと思う。
【BigQuery】既存のテーブルスキーマを新しいテーブルにインポートする

## 使い所
- 既存のテーブルに変更を加えたいとき
- テーブルのリージョンを変更したいとき

BigQueryは既存のテーブル名の変更やスキーマの変更はできず、新しくテーブルを作り直す必要がある。
その際にカラム数の多いテーブルだと手作業で1つずつスキーマを移すのが苦行なので、既存のテーブルのスキーマをエクスポートし、新しいテーブルにインポートする。

## 前提
- [Google Cloud SDK](https://cloud.google.com/sdk/docs?hl=ja)のインストール・ログインが済んでいること。

## 手順
### 【export】 bqコマンドで既存のテーブルのスキーマを表示する
コンソールで以下のコマンドを実行する。(${}変数は自分のエクスポートしたいテーブルに置き換えること)
テーブル情報が表示されるので、"schema"キー以下の"fields"の始めから終わりをコピーする。

```
❯ bq --format=prettyjson show ${project_id}:${dataset_name}.${table_name}

{
  "creationTime": "XXXXXXXXXXXXX",
  "etag": "XXXXXXXXXXXXXX",
  "id": "${project_id}:${dataset_name}.${table_name}",
 ︙
  "schema": {
    "fields": [
      {
        "mode": "NULLABLE",
        "name": "hoge",
        "type": "INTEGER"
      },
      {
        "mode": "NULLABLE",
        "name": "fuga",
        "type": "STRING"
      },
      {
        "mode": "NULLABLE",
        "name": "piyo",
        "type": "BOOLEAN"
      }
   ]
}
︙
```

```:期待するクリップボードの中身
[
  {
    "mode": "NULLABLE",
    "name": "hoge",
    "type": "INTEGER"
  },
  {
    "mode": "NULLABLE",
    "name": "fuga",
    "type": "STRING"
  },
  {
    "mode": "NULLABLE",
    "name": "piyo",
    "type": "BOOLEAN"
  }
]
```

## 【import】 Webコンソールからテーブル作成
- クエリエディタ画面を開いて、テーブルを作りたいデータセットを選択→『テーブルを作成』をクリック
- 『テキストとして編集』を有効にし、クリップボードに用意したJSONを貼り付ける
![スクリーンショット 2020-11-02 17.36.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/282929/f202e451-fb0d-e443-a671-3b6710ff80b9.png)
認証(Authentication)と認可(Authorization)の違い

AuthenticationとAuthorizationが紛らわしいのでメモ.
<strong>注意: "ユーザ"は、人とは限りません."サーバ"は、提供者(機械or人)です.</strong>
<h5>追記 2020/11/05 </h5>
ritouさんにコメントいただきましたので、情報を修正しました！
(詳しくは修正履歴にてご確認ください)

<h1>忘れがちな Identification 識別</h1>

<strong>サーバがユーザを特定すること.</strong>
入力されたIdentifier(ID, 識別子)から、ユーザを特定する.


<h1>Authentication 認証</h1>

<strong>ユーザが本物かどうかの確認.</strong> 識別じゃないよ.
ユーザーが誰なのか特定したあとで、本当にその人なのか確認すること.
例えば、ユーザにCredential(パスワードとか認証に使うものたち)を渡してもらって、一致すればログイン.


<h1>Authorization 認可</h1>

<strong>サーバがユーザに適切な権限を与えること.</strong>
例えば、SQLのgrant文みたいなもん.
見せるだけか、投稿も許可するか.


<h1>認証と認可って分ける必要ある?</h1>

ある(と思ってる.).

アカウントを持たないユーザにサービスを提供する際は、認可のみでOK.

アカウントを持つユーザのみが対象でも、非課金サービスと課金サービスが存在する際は、
認証後に課金サービスの認可をきっちりしないとNG.

<strong>実際のところ</strong>
<font color="#95949a">
この記事では一つのサービスが、ユーザを識別認証認可をすることを想定しています.
現実では、２つのサービス間とユーザを認証する（アカウント連携、アプリとサーバのやり取りなど）
こともあります.そこではOAuth(認可)とOpenID Connect(認証・認可)が利用されています.</font>


<h1>まとめると</h1>
識別して認証して認可するのが一般的な形.
[備忘録]マクロの引数の数でオーバーロード

### はじめに
備忘録です。

### シンプル版


```haskell

// 必要次第追加
#define TEST_OVERLOAD(e1,e2,e3,NAME,...) NAME

#define TEST_1(x) x
#define TEST_2(x, y) x + y
#define TEST_3(x, y, z) x * y * z
#define TEST(...) TEST_OVERLOAD(__VA_ARGS__,TEST_3, TEST_2, TEST_1)(__VA_ARGS__)
```

### 少し一般化した版

アンスコ引数数で決め打ちのパターン

```haskell
// 必要次第追加
#define GET_VA_SIZE( e1, e2, e3, e4, e5, e6, e7, e8, e9, e10, COUNT, ... ) COUNT
#define VA_SIZE( ... ) GET_VA_SIZE( __VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 )

#define PP_CAT( a, b ) a ## b
#define PP_OVERLOAD(macro, count) PP_CAT( macro ## _, count )

#define TEST_1(x) x
#define TEST_2(x, y) x + y
#define TEST_3(x, y, z) x * y * z
#define TEST(...) PP_OVERLOAD(TEST, VA_SIZE(__VA_ARGS__))(__VA_ARGS__)
```

参考
https://www.it-swarm-ja.tech/ja/c++/マクロは引数の数によってオーバーロードできますか？/1073435042/
【Rails】UC時刻表示を日本時刻表示に変換する方法

#時刻表記変更の手順

- gem 'rails-i18n'をインストール
- config/application.rbへ記述の追加
- config/locales配下にファイル作成、記述


#gem 'rails-i18n'をインストール
`Gemfile`に以下のGemを追加します。（本番環境でも開発環境でも使いますので、一番下に記述しましょう）

```:Gemfile
gem 'rails-i18n'
```

ターミナル

```
bundle install
```

※このときサーバーを立ち上げ直すのを忘れないようにしましょう。

#config/application.rbへ記述の追加
 `config/application.rb`を開いて、追加と書かれている二行を追加します。

```Ruby
module アプリケーション名
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 6.0 
    config.i18n.default_locale = :ja 　#追加
    config.time_zone = 'Tokyo'      　 #追加
   # 中略
```

#config/locales配下にファイル作成、記述

次は`config/locales`配下に、`ja.yml`というファイルを作成しましょう。
そこに以下のように記述します。

```Ruby
ja:
  time:
    formats:
      default: "%Y/%m/%d %H:%M:%S"
```

これで、日本の時刻表記に変えられたはずです。

このように表示されているかと思います。
![スクリーンショット 2020-11-02 11.27.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/696812/02b7ed20-ae93-9710-06c5-9ec5019a3f72.png)

YがYear、mがmonth、dがdayのようになっています。表記の仕方を変えたい時は、`ja.yml`のdefaultを書き換えればいいので、ご自身の表示させたい形に書き換えてください。
Linux（コマンド思い出し編）

##今回やること
現場でインフラ全般の設計構築を担当していますが、Linuxを触ることになったので
久しぶりすぎてコマンドほぼ忘れてしまっているため復習しようと思います。
WindowsServerも触っているので、勉強したいところですが今回はLinuxを。

##今回の勉強の進め方（ざっくり）
①とりあえず使いそうなコマンド選別
　これが結構時間かかる。
　理由としては、色んなサイトを見てみるがそれぞれ個人ごとに使うコマンドが全く違うから。
　選別が難しい。。。
　資格勉強も考えたが、すぐに必要になる知識なので時間効率が悪いなぁと。

②表作成
　業務特性を見極めて使いそうなコマンドと意味を理解していく。
　まとめることで備忘録になる。
　
③まとめたやつを実際にコマンド叩いて、動きを体感する
　これは本当に必要。
　何事もインプット⇒アウトプットしないと覚えない。
　特にLinuxはコマンドは体で覚えるくらいにならないとすぐに忘れる。
　（実際に今の自分がそうです笑）
　VMでまず環境構築するところから始めないとなので、工数かかってしまうけど
　仕方なしですね。

##早速選別と表作成
業務でLinuxの何を使うまでは見てなかったーー
一番重要なところ。
RedHat系列を使うんだろうなーと勝手に予想。（違ったらその時勉強します・・・）

|コマンド|説明|
|:---|:-----:|
|pwd|ディレクトリ表示|
|cd|基本的なものだが、ディレクトリ移動|
|cat|ファイルの中身を見る|
|mv|mv 【何を】【何に/移動先】ファイル名変更や何かを移動するとき|
|tail|tail hogehoge　で末尾表示|
|grep|grep 【何を】【何から検索するか】検索コマンド|
|mkdir|ディレクトリ作成|
|rm|rm -rf 【何を】完全削除　-rfオプションは怖い|

##アウトプット
とりあえず仮想環境をCentOS8で構築したので早速起動。
![素材.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/15940f37-e2da-63e2-5d0c-a7f34c436011.png)

あれ、うまいこと入力できないのだけど・・・

あー・・・
これもしかして米国キーボード配置になってるやつだ。
![課題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/5ff54bda-7e9f-276c-63fe-aebdcfe921c7.png)
やっぱり**US**になってる。
まずはここから修正していきましょうか。

![課題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/9727b7c9-9c5c-aa5c-7f1f-ab4a882ab8af.png)
よしこれでOK。

ログ抽出したいけどドラッグできなくてログ貼り付けできず。
やり方模索した結果よくわからず、ここから深堀すると今回の趣旨外れちゃうので画像貼り付けで対応。

では色々いじくってみます。

![test.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/2bd347e1-5cf8-0f60-e72c-ebe4d1ed81ff.png)

まずい、vimの操作もろもろ忘れてるので調べて対応。笑
ここまで忘れてしまうと業務にすぐ入れないですねー。
今回勉強しておいて正解です。

![vi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/686507/0a60dcaa-b48b-b853-a7a4-65a5ce0990be.png)

さて感覚とりもどしてきたので、適当に色々コマンドうって動き確認しての繰り返しです。
Linuxは同じコマンド相当打つことになるので、勝手に覚えると思います。
ただ期間が短いとすぐに忘れてしまうので、今回みたいに勉強しないとまずいですね。

##まとめ
今回はLinuxを勉強しましたが、今の環境ではオンプレのインフラ設計構築なので
幅広い知識が求められます。

ネットワーク・FW・サーバー全般・ミドルウェアと広域なので、
満遍なくうまいこと勉強していかないと虫食いで忘れていってしまうので、
難しいところですね。

ただこの広域を触れる環境が面白いので、どんどん学習をしていこうと思います。
朝会でちょい学習

チームで実践している朝会の試みを紹介します。

# 背景
業務時間外に勉強や情報収集をすることは、チームメンバーの様々な背景が関係するため難しいです。
ただ、そのまま放置していてはスキル差が広がる一方。
なので、**業務時間内を使って業務に影響しない範囲で**チームメンバーが学習できる機会を考えました。

# 実践内容
- 毎日の朝会後、5分時間をとる。
- 5分以上経過したら中断して翌日に回す。
    - 長いとグダグダになってしまうので、タイマーを用意して時間を切る
- ネタはみんなで自由に持ち寄る。
    - 動画(youtube)、スライド、Blog、Twitter、ワークショップ(Kotlin Koans)など

# やってみてどうか
ネタが尽きたり雲行きが怪しくなってきたらやめるつもりでしたが、継続できています。（半年経過）
毎朝新しい刺激が得られる、短時間、という点が継続につながっているんじゃないかなと思います。
直近の業務に関係しないネタ(AWSとか)はあまりウケがよくなかったので、直近でみんなが興味ありそうなネタを選んだほうがよかったです（うちのチームでは）
Charlesを通信中に強制終了したらネットワークが繋がらなくなった時の解決方法

### 経緯
macOSでXcodeを使用しiOSのアプリを製作しています:raising_hand:

APIの動作確認をしたく、Charlesにて通信を確認していたところ、
通信中に動作が重くなり、Charlesが接続中のまま動かなくなってしまった為、
処理中のままアプリを終了させてしまいました。

それ以降、Charlesを起動している間でないとネットワークに接続できなくなってしまいました:scream:

### 試したこと

- **pcの再起動**
- **証明書の再発行**
- **Charlesアプリの削除**（消してしまったらネットに繋がらなかった為、ゴミ箱から復活させました）
- **macのProxyのチェックを外す**
　システム環境設定 > ネットワーク > 詳細 > プロキシ から、「構成するプロトコルを選択」のチェックを全て外しました。

![スクリーンショット 2020-11-02 15.59.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/534195/3cf63813-2348-418f-8130-32324b998031.png)

一度上記の項目を試したのですが、改善されませんでした。

記事を書くためにもう一度自分の行った作業を確認したところ、

**macのProxyのチェックを外す**を行っても、Charlesを開くと自動的にチェックがついてしまっていることに気づき、
**一度Charlesを完全に閉じてからチェックを外してネットに接続してみたところ無事繋がりました！**:clap:

その後Charlesを起動してからProxyの「構成するプロトコルを選択」をみてみるとやはり自動的にチェックが入ってしまいましたが、Charlesを閉じてみても問題なくネットワークに繋がるようになりました:ok_woman:

私の知識が浅浅のため、これは状況を踏まえた憶測に過ぎないのですが・・・

どうやら、

- Charlesを開いているときのプロキシ設定
- Charlesを閉じた時のプロキシ設定

この２つは別物のようです:thinking:

**Charlesを開いている時のプロキシ設定**は、Charlesを開いた際に自動的に適用され、Charlesを開いている間は維持されるものなので、
手動でチェックを外してみても、再度起動してしまえば元に戻ってしまう。

一方、**Charlesを閉じた時のプロキシ設定**は、自由に設定でき、Charlesを開いていない間のみ適用されるもの。

なのだと思います。


Charlesを開いているときのプロキシ設定 =>　プロキシ設定A
Charlesを閉じた時のプロキシ設定 => プロキシ設定B
と置いた時、

`（標準時）プロキシ設定B → (Charles起動中) プロキシ設定A → (Charles終了後)プロキシ設定B`
のように適用され、

Bの方は変更が維持されますが。
`（標準時）プロキシ設定Bを変更してB'となる → (Charles起動中)プロキシ設定A → (Charles終了後)プロキシ設定B’`

Aの方はCharlesの設定に適応してしまうので
`（標準時）プロキシ設定B → (Charles起動中) プロキシ設定Aを変更してA'となる → (Charles終了後)プロキシ設定B → (Charles起動中) プロキシ設定A`

もう一度起動すると変更が適用されていない。


こんな感じで認識しています:hugging:（厳密には違うかもしれません・・・）

### まとめ

仕組みはともかく、私と同じような状況に陥った方は、

**Charlesを閉じた状態でProxyのチェックを外す**

をやって見て頂いたら解決できるかもしれません:relaxed:

解説はできなくてもこれさえ共有して同じことで悩む方が減らせれば・・・

と思い初めて記事を公開してみました:information_desk_person:

詳しく解説してくださる方がいらっしゃいましたら是非お願いします:pray:
DynamoDBで、項目のみの削除と1レコード削除の方法(Dynamo独特のルールをなんとかする)

## Dynamoの面倒なルール
1レコード削除ではなく一つの項目のデータのみを削除したい場合、updateで空文字を指定して更新しようと思うが、Dynamoは空文字を指定できない。

半角スペースを入れてアップデートはできるが、それだとデータが存在していることになるし、
半角スペースで文字列比較してチェックするのもちょっと良くない。

項目のみを削除する方法、ググってもなかなか出てこなくて大変だった。

## 普通に1レコードを削除する方法
テーブル名とハッシュ値を指定してdeleteする

```typescript:anime-suko.ts
  const deleteHogeTableParams = {
    TableName: 'hogeTable',
    Key: {
      id: '114514',
    },
  }
 await documentClient.delete(deleteHogeTableParams).promise()
```

##  項目のみを削除
このように、普通のupdate()ではなく「transactWrite()」使って、
「UpdateExpression: 'Remove #hd, #nd'」って感じで項目を指定してRemoveする。

```typescript:anime-suko.ts
  const deleteHogeTableParams = {
    TransactItems: [
      {
        Update: {
          TableName: 'hogeTable',
          Key: {
            id: '114514',
          },
          ExpressionAttributeNames: {
            '#hd': 'hogeDate',
            '#nd': 'nazonazoDate',
          },
          UpdateExpression: 'Remove #hd, #nd',
        },
      },
    ],
   await documentClient.transactWrite(deleteHogeTableParams).promise()

```

## 感想
マジでDymano使っててなんもいいことない。MySQLだったら一瞬で出来ることを、Dynamoだと便利な機能が少ないし制限がひどすぎるし、ちょっとしたことでもわりと複雑な設定しなくてはならない。。。
データ取得するとき、必ずハッシュ値指定しなきゃいけないとか意味わからん。他のカラム(属性)を条件にしたかったらグローバルセカンダリーインデックスの設定ファイルを書かなきゃいけなかったり。。。

AWS使ってるけどMySQLでええやん。。。(業務の愚痴)
【PHP初心者】if else文をなくすガード節

### ガード節とは

`if else`文の入れ子構造を解消する方法です。

`if else`文の入れ子構造

~~~php
public function hoge($a, $b) {
    if ($a > 0) {
        $result = 'fuga';
    } else {
        if ($b > 0) {
            $result = 'piyo';
        } else {
            $result = 'piyopiyo';
        }
    }
    return $result;
}
~~~



ガード節で書き換えると以下のようになります。

~~~php
public function hoge($a, $b) {
    if ($a > 0) {
        return 'fuga';
    }
    if ($b > 0) {
        return 'piyo';
    }
    return 'piyopiyo';
}
~~~



### メリット

* 一時変数を使わなくて済む。
* ネストが減り、コードがシンプルになる。
* 正常処理と異常処理の区別が分かりやすくなる。



### ガード節を使う場面と使わない場面

**使う場合**

`if else`文のどちらか片方が良く起こる。

一方が正常処理でもう片方が異常処理を扱う場合によく使います。

**使わない場合**

`if else`文のどちらも同程度起こりうる。

両方とも正常処理の場合は、`if else`を用います。

リファクタリングを行う際によく出てくる手法なので、試してみてください！
「原神」のMMDをスマホのブラウザでVR・ARする

以前の投稿 「[「原神」がMMDモデルを配信してくれたので、JavascriptでMMDビューアを作った](https://qiita.com/poruruba/items/35085f3ab3db3fa17d2d)」 で、ブラウザで動作するMMDファイルのビューアを作成しました。
今回は、それをもう少し拡張して、VR表示またはAR表示してみます。

ソースコードは以下に上げておきました。

poruruba/MmdViewer
　https://github.com/poruruba/MmdViewer

こっちがVR。
![Screenshot_20201102-170805.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/4543d918-72c2-b53e-1af6-adc9b6fc0458.jpeg)

こっちがAR
![Screenshot_20201102-171048.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/41f66ca1-a3f1-79d6-f8fe-da9455108168.jpeg)

#three.jsのVR表示機能

three.jsには標準で、VRまたはARとして表示する機能があります。
ですので、それを有効にします。MMDファイルのロード部分はほとんど変わっていません。

詳細は、以下に記載があります。

How to create VR content
　https://threejs.org/docs/#manual/en/introduction/How-to-create-VR-content

※MMDビューアとして、通常のJavascript版とmodule版の2つを用意していましたが、今回はmodule版を前提としているようです。

動作環境としては、AndroidとiOSのようです。
なぜならば、OSの機能である「ARCore」や「ARKit」を使い、さらにChromeからWebARとして呼び出せる環境である必要があるためです。
私の場合はAndroidで確認しました。

基本的な変更点は以下の通りです。

①背景色を透過にするため、以下の部分をコメントアウトします。

//    this.scene.background = new THREE.Color( 0xffffff );

また、同様に、WebGLRenderer にalpha=trueの引数を加えます。

    this.renderer = new THREE.WebGLRenderer( { antialias: true, canvas: canvas, alpha: true, preserveDrawingBuffer: true } );

②以下の部分で、ブラウザのWebAR機能を有効にします。
    this.renderer.xr.enabled = true;

③以下を入れることで、VRまたはARモードに入るためのボタンを表示してくれます。

    if( mode == 'vr')
      document.body.appendChild(VRButton.createButton(this.renderer));
    else
      document.body.appendChild(ARButton.createButton(this.renderer));

④最後に、レンダラーのループ処理で、以下の通りに変える必要があります。

//    requestAnimationFrame( this.animate.bind(this) );
    this.renderer.setAnimationLoop(this.animate.bind(this));

これで終わりです！

# 動作の様子
HttpsのWebサーバに、デプロイし、Chromeブラウザからmodule版の方のページを開きます。Androidで開いてください。
　mmd_viewer/mmd_viewer_jsm/index.html

open(vr)やopen(ar)というボタンがあるかと思います。前者がVRモードで全画面表示し、後者はARモードで全画面表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/8e855499-6172-54cb-e649-b31260e7c857.png)

とりあえず、いつもの全画面表示されますが、下の方に薄く「ENTER VR」または「ENTER AR」というボタンがあります。これをクリックすると、VRモードまたはARモードになります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/f88643ff-bbc4-d34d-df57-5b11c1580581.png)

こっちがVR。
![Screenshot_20201102-170805.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/4543d918-72c2-b53e-1af6-adc9b6fc0458.jpeg)

こっちがAR
![Screenshot_20201102-171048.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/41f66ca1-a3f1-79d6-f8fe-da9455108168.jpeg)

途中、Google Play 開発者サービス(AR)のインストールを促されるかもしれません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/261826/027dea29-3256-7438-092d-b76be809a9d6.png)

#(おまけ)ステージの表示

MMDでは、モデル・モーションまたはポーズに加えて、ステージという概念があるそうです。
簡単いうと背景です。3次元になると、背景の画像ではなく、立体画像になるので、ちょっと呼び方を変えているようです。

ステージも、モデル同様に、PMXまたはPMDファイルですので、モデル・モーションまたはポーズのロードに加えて、ステージのPMXまたはPMDファイルもロードするようにしました。

#終わりに

以下の記事を参考にさせていただきました。ありがとうございました。

たった4行でできる！ブラウザ向けVRをThree.jsで実装する方法
　https://ics.media/entry/18793/

続編です。
　[「原神」のMMDキャラクタをスマホVRの世界に呼び込む](https://qiita.com/poruruba/items/89fd95f8bf00fc2154ad)
結局のところ、renderer.setAnimationLoop は使わず、上記の投稿のやり方の方がよいです。

以上
ノート等の情報を基にしたビジネス書や実用書などのランキングサイトを作りました



# はじめに

ノートの投稿記事からリンクされているAmazonの商品を集計してランキングサイトを作りました。技術書のランキングはQiitaを元にした[テック・ブック・ランク](https://www.techbookrank.com/)がありますが、私はビジネス書や実用書を読みたいため、ノートにだったらそういう情報ありそうだなと思ったので。

[Note Station | 人気のビジネス書や実用書、技術書をランキング形式で毎日更新](https://note-station.com/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844004/d2457b10-0b85-cef2-6a50-1583a041d650.png)


元々個人用に作って、書籍購入の参考にしたり、ランキング処理の勉強として作ったのですが、思ったよりも便利なのではと思い公開する事にしました。

書籍のカテゴリはたくさんあるので、2階層目までのカテゴリ情報でフィルタできるようになっています。Amazonのカテゴリを最後まで表示すると凄い細かいので解像度を荒くしています。

また、書籍以外の情報も出てくるので、それはフィルタリングしないでそのまま表示するようにしています。

## できていないこと

[TODO](https://note-station.com/todo)としてまとめてはいるのですが、主にランキング周りを改善したいと思っています。

特に、Kindleと物理本が別々に扱われているのをなんとかしようと思っています。名寄せのための情報は既に持っているのですが、スコアの計算をMySQLで行っていいるため、名寄せ処理を入れると、凄くクエリが重くなってしまい悩んでいます。

また、月や年のランキングの上位が似ているため、発見の幅が狭まっているのをなんとかしたいです。

あとは、1つの記事には他の書籍も紹介されているので、ランキング表示のところに関連書籍を合わせて表示したいと思っています。Amazonでも関連商品は1つ1つのページを辿るしかないので、リスト表示のところに関連商品も小さく表示したら、書店で本棚を見るかのような体験が出来そうかなと。

## ランキングについて

専門家ではないため難しい理論や処理は実装できないのですが、以下のことに気を配りました。

- 基本は言及している記事の数、記事のイイネの数と記事の投稿日を元に計算する
    - 投稿してから時間が経過したものは減衰するようにする
    - 減衰は集計期間によって変更する
- 同一ユーザーが毎投稿に自分の(?)書籍のリンクを貼っているものがあるので、そういうものはスコアを抑えるようにする
    - 例: 10個の記事がある場合、1人が書いているよりも10人が書いている方がスコアが高い
- ユーザー自体のスコア（ユーザーのフォロワー数など）は利用しない。重みも考慮しない。
- SNS上の情報(TwitterやHatenaBookmarkなど)もある程度考慮する

こんな感じの本が見れます。

![month.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/844004/b4346a03-90a8-ee63-5705-eabfebb8deb6.jpeg)

## 利用した技術一覧

使っている技術は特に目新しいものはありません。SPAで作ろうと思ったのですが、ページが1枚しかないので、クラシックな作りました。勉強も兼ねているので、SPA化は近いうちにやろうと思っています。

お金をなるべく使いたくなかったのでAWSやGCPではなく、ConohaのVPSを使っています。

- Crawler
    - Ruby 2.7
    - MySQL 8
    - RabbitMQ
- Web site
    - Bootstrap 4
    - SQLite
    - Nginx + Puma + Sinatra
    - Cloudflare
- Datadog

ただ、クロールや集計をするサーバとランキング情報を配信するサーバは分けています。ランキング情報の生成はWriteが1日に1回かつ、WebサイトはWrite処理がありません。なので生成したランキング情報をMySQL上に生成した後に、SQLiteファイルとしてDumpして、Webサイト用のVPSに転送しています。（集計前のデータはMySQL上で大量のレコードと大きなデータサイズなので、これを参照させたくない）

ランキング情報をSQLiteにDumpするのはレコード数が少ないからこそやっているのですが、これによってメモリ使用量もDisk使用量も小さくなり、小さいVPSで運用できています。いまのところ、それなりにサクサク(応答時間が50ミリ秒未満)と動いていると思っています。

一度使ってみて欲しいです。

[Note Station | 人気のビジネス書や実用書、技術書をランキング形式で毎日更新](https://note-station.com/)
UnrealBuildToolをデバッグしてみる

UnrealBuildTool(UBT)はエンジンやプロジェクトのc++ネイティブコードをビルドするためのツールです。
難しいことを考えずにビルドをするだけで必要な処理を解析して勝手に起動に必要なバイナリを作成してくれる便利なツールですが、
開発していると稀にUBTの動作が意図通りに行われないことに遭遇しデバッグしたくなることがあります。

本記事ではUBTのデバッグ方法について解説します。

なお UE4.25.3 + VisualStudio2019 の環境に基づいて書かれています。

#ビルド時に渡されているオプションを調べる
まずUBTを起動させるときに対象となるプロジェクトを指定しなければなりません。

基本的には `-target=[ターゲット名(プロジェクト名+Editor)] Win64 Development -Project="プロジェクトファイルのパス"` となります。

```shell:例
-Target="SimpleLoadingScreenEditor Win64 Development -Project=\"D:\dev\UE425projects\SimpleLoadingScreen\SimpleLoadingScreen.uproject\"" -Target="ShaderCompileWorker Win64 Development -Quiet" -WaitMutex -FromMsBuild -verbose
```

上手く行かない場合は-verboseログを有効にしてビルドするとログから確認できます。
-verboseオプションについてはこちらの記事をご確認ください → https://qiita.com/EGJ-Takashi_Suzuki/items/b2134bee42afaf2db766

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/b5e60679-cd6f-9a24-1247-255d9dac455f.png)


#ソリューションの設定と起動
まずソリューション中のUnrealBuildToolを選択して Set as startup project を選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/28fa0b32-653f-993c-afed-80e6053dfdbf.png)


次に、UnrealBuildToolプロジェクトのプロパティを開き、「Debug」カテゴリの CommandLineArguments に調べておいたオプションを記述します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/464248/cf118496-cec4-df57-88c4-4a882ea5d38e.png)

これで準備完了です。
あとはStepInto(F11)でプログラムの先頭から実行するか、
BuildMode.csのBuild関数や、問題の個所がわかっていればそちらにブレイクポイントを張ってからRun(F5)でデバッグを開始できます。


#おまけ

##対象のヘッダファイルにUHTが起動される判定
`Intermediate\Build\Win64\プロジェクト名\Inc\モジュール名\timestamp` と
ヘッダのタイムスタンプを比較している

##ソースファイルに対して依存関係のあるファイルの確認
`Intermediate\Build\Win64\UE4Editor\Development\YourProjectName\YourSourceFile.cpp.txt` のようなファイルに
cl-filter.exeを通じて得られた依存関係のあるファイルが出力されている
Rails6(MySQL、Ubuntu環境、Cloud9)

1 railsのgemをインストール

```
#rails6の場合
gem install rails -v 6.0.1
#rails5.2の場合
gem install rails -v 5.2.1
```

2 MySQLセッティング(Cloud9ではMySQL自体はデフォルトでインストールされている)
 
```
#これをインストールしておかないと、mysql2 gemのインストールでエラーになります。
$ sudo apt-get install libmysqld-dev
```

3 Rails new

```

$ rails new appname -d mysql
```


4 MySQL Account を作る

```
$ sudo mysql -u root   #rootユーザーでログイン
$ mysql> create user 'ユーザー名' identified by 'パスワード';  #ユーザー作成
$ mysql> grant all on *.* to 'ユーザー名';  #ALL権限付与

#作成したユーザーの確認は下記コマンド
$ mysql> select User,Host from mysql.user;
```




5 config/database.ymlの編集

```
default: &default
  adapter: mysql2
  encoding: unicode
  pool: 5
  # 以下、3行追加
  username: <username> # 設定したMySQL Accountと同一のもの
  password: <password> # 設定したMySQL Accountと同一のもの
  host: localhost
  
development:
  <<: *default
  database: appname_development # appnameのところは、rails new時のappnameになっているはずです。
test:
  <<: *default
  database: appname_test # appnameのところは、rails new時のappnameになっているはずです。
```

6 rails db:createでデータベースを作成&webpackerインストール

```
$ cd appname
$ rails db:create

#rails5の場合は不要
$ source <(curl -sL https://cdn.learnenough.com/yarn_install)
$ yarn install --check-files
$ rails webpacker:install

#config/enviroments/development.rb
config.hosts.clear
```
Cluster サンプルを読み込んだ時にエラーが出た場合

#Cluster サンプルを読み込んだ時にエラーが出た場合

こんなエラーが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/7e71bd3f-f18a-cfdc-8540-87fb176d008c.png)

気にせず「続行」。案の定「Cluster」がメニューに表示されていない

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/1386265f-2cc2-c045-187e-9e44ba5b8a73.png)


#ClusterCreatorKitをダウンロード
https://github.com/ClusterVR/ClusterCreatorKit/releases


#インポート
Unity パッケージマネージャーからダウンロードしたプロジェクトのpackage.jsonを指定してインポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/ba9783e2-9a2f-2310-3751-e5e782329e98.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/3dba0313-1ecb-0539-7b87-6ad9c7ffbff1.png)


メニューに「Cluster」が表示されればOK
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/07da7139-399d-1a06-cba6-29922977ea6c.png)


以下のようにヒエラルキーに表示される
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/2672fbd0-3e16-a4b7-be1c-c1dc2626518a.png)

#実行結果
無事サンプルで遊べた
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/119864/8ca202b2-61ac-d1bc-d64f-65dd5eb6cdb8.png)

- こちらを参考に
https://creator.cluster.mu/2020/06/11/howto_shootinggame/
正規分布 : 正規-ガンマ分布 (ベイズ推定)


# 記事の目的
正規分布と、平均と分散が未知の時の共役事前分布である正規分布を使用し、Rを使ってベイズ推定を行います。
20代男性の身長の平均と分散を事後分布で推定します。
参考：[ベイズ推論による機械学習入門](https://www.amazon.co.jp/%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E3%82%B9%E3%82%BF%E3%83%BC%E3%83%88%E3%82%A2%E3%83%83%E3%83%97%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E3%83%99%E3%82%A4%E3%82%BA%E6%8E%A8%E8%AB%96%E3%81%AB%E3%82%88%E3%82%8B%E6%A9%9F%E6%A2%B0%E5%AD%A6%E7%BF%92%E5%85%A5%E9%96%80-KS%E6%83%85%E5%A0%B1%E7%A7%91%E5%AD%A6%E5%B0%82%E9%96%80%E6%9B%B8-%E9%A0%88%E5%B1%B1-%E6%95%A6%E5%BF%97/dp/4061538322)

# 目次
[1. モデルの説明](#1-モデルの説明)
[2. 推定する分布](#2-推定する分布)
[3. 事前分布](#3-事前分布)
[4. 事後分布](#4-事後分布)
[5. 予測分布](#5-予測分布)

#1. モデルの説明
![IMG_0185.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/067fbfb6-8b7b-03e3-cf85-4e7755facce1.jpeg)



#2. 推定する分布
20代男性の身長は、平均が170で標準差が10の正規分布に従います(適当)。しかし、僕たちはそれを知りません。
この、真の分布の平均170と分散の逆数1/100=0.01を事後分布で推定します。

```R:
curve(dnorm(x, 170, 10), 100, 250, xlab="20代男性の身長", ylab="確率密度")
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/2d282518-bec1-8703-5cec-fff7b36da72f.png)




#3. 事前分布
平均の事前分布として正規分布、分散の逆数の事前分布としてガンマ分布を仮定します。
どちらもデータに適合しやすいようにパラメータを設定しています。

```R:
par(mfrow=c(1,2))
lambda0 <- 1
beta0 <- 1/100^2
m0 <- 100
lambda.mu0 <- 1/50^2
curve(dnorm(x, m0, 1/sqrt(lambda.mu0)), 0, 250,
      xlab="20代男性の平均身長", ylab="確率密度", ylim=c(0,0.3))
a0 <- 1
b0 <- 1
curve(dgamma(x, a0, b0), 0, 0.1, ylim=c(0,230), 
      xlab="20代男性の身長の分散の逆数", ylab="確率密度")
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/54bc7c50-2f06-fa5d-d580-9868efcff74b.png)



#4. 事後分布
真の分布がら100個のサンプルを取って事後分布を推定します。
事後分布は緑の曲線です。平均は170, 分散は1/100=0.01をうまく推定できています。

```R:
#データ
N <- 50
X <- rnorm(N, 170, 10)
#事後分布
beta <- N + beta0
m <- (sum(X)+beta0*m0)/beta
curve(dnorm(x, m0, 1/sqrt(lambda.mu0)), 0, 250,
      xlab="20代男性の平均身長", ylab="確率密度", ylim=c(0,0.3))
curve(dnorm(x, m, 1/sqrt(lambda0*beta)), 100, 250, add=T, col="green")
a <- N/2 + a0
b <- (sum(X^2)+beta0*m0^2-beta*m^2)/2+b0
curve(dgamma(x, a0, b0), 0, 0.1, ylim=c(0,230), 
      xlab="20代男性の身長の分散の逆数", ylab="確率密度")
curve(dgamma(x, a, b), 0, 0.1, add=T, col="green")
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/e12fff3e-8af4-7807-4a1b-982b2e58f45a.png)



#5. 予測分布
予測分布も、うまく推定できていることが分かります。

```R:
u.p <- m
lambda.p <- beta*a/((1+beta)*b)
n <- 2*a
par(mfrow=(c(1,1)))
curve(dnorm(x, 170, 10), 100, 250,ylim=c(0,0.05),xlab="20代男性の身長", ylab="確率密度")
curve(dt(x, df=n)*((1+x^2/n)^((n+1)/2))*sqrt(lambda.p)*((1+lambda.p*(1/n)*(x-u.p)^2)^(-(n+1)/2)), 100, 250,
      add=T, col="blue")
```
>
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/775500/d3d7de2d-a575-cf88-c25f-7035ec2a8a26.png)