OmniAICreator/Qiita-1.07M huggingface dataset:
LookerとBacklog Gitリポジトリを連携する

LookerのLookMLコード管理にはGitリポジトリが利用できます。

https://cloud.google.com/looker/docs/setting-up-git-connection

本記事ではBacklog Gitリポジトリを連携する手順をまとめました。

# プロジェクトに対しGitの構成

作成したプロジェクトに対しGitを構成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/f327bd41-7487-2944-d53b-393e3244c4b2.png)

# リポジトリURLの入力

Backlog GitリポジトリのURLを入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/d3040605-9965-fb4b-1f79-7ecc2769542e.png)

URLはここから取得できます。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/84c8ce2e-7472-c5d0-777c-4ffc03dc9371.png)

次にホスティングサービスを選びます。
Backlog Gitの場合は「Custom Git Configuration」です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/f14ec015-4f29-383b-e309-a139efc8122f.png)

# 認証情報の入力

ここで設定したリポジトリがあるBacklogプロジェクトに入れるBacklogユーザーのID、パスワードを設定すれば構成は完了です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/478de6a1-92cc-6c81-c514-2579b91640cc.png)

但し、この場合LookerプロジェクトでLookMLを編集、コミットしたユーザーをバックログ上のコミット履歴で識別することが難しくなります。
常にここで設定した単一ユーザーでアクセスしていることになるためです。

ちゃんと複数人のコミッターをBacklogのユーザーと紐づけて管理したい場合はもうひと手間必要です。

# ユーザー属性の追加、設定

「管理」->「ユーザー」->「ユーザー属性」より、Backlog Git認証のための追加の属性を設定します。

https://cloud.google.com/looker/docs/admin-panel-users-user-attributes#creating_user_attributes

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/11ae973d-3a27-a99e-ed02-93206b3e2a9f.png)

ここではBacklogのIDとパスワードを設定できるように追加のユーザー属性を作っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/3521f685-33ef-795f-8430-f6ffeace9e47.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/6b5685b4-66c6-836c-9cee-f6f24bf7d2db.png)

Backlogがユーザー名がLookerのユーザー情報と一致（例えばメールアドレス）するならばID項目の作成は省略できます。
シークレットととなるパスワードは送信先を制限する必要があるので、Backlog GitリポジトリのURLをワイルドカードで指定します。


追加した属性は各ユーザーが個人のアカウントページで設定できます。

![{5DB2ECAB-E045-4E79-BEA6-90E21F38D16E}.tmp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/9abae34d-02e8-d6cf-762a-dab0a6937d05.png)

これで準備ができたので先ほどの接続設定画面に戻ります。

# ユーザー属性を加えてGitリポジトリを設定

「Use user attributes for username and password.」のラジオボタンをオンにし、BacklogユーザーのID、パスワードとそれぞれのDeveloperが認証に使うユーザー属性をプルダウンから選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96507/c55d10e9-3f95-22d3-7bd1-a03d86debfd0.png)

これで構成完了です。
Lookerプロジェクトで複数人がLookMLを編集してもそれぞれのコミッターが識別されて表示されるようになります！

---

Backlog Git以外のサードパーティーのGitホスティングサービスを連携する場合も同様の手順でできそうです。
地球にやさしいエコなVMware vSphere環境を作る方法

# はじめに
- SDGsとかESGとか色々言われておりますが、一人ひとりが地球環境のためにできることをやっていきたいものですよね。
- こういった取り組みが企業の評価に直結するようになった昨今、エンジニアとしてもできることはあるはずです。
- というわけで、本記事ではvSphere DPM (Distributed Power Management) の機能を使うことでエコなVMware vSphere環境を作る方法ご紹介します。

# vSphere DPM (Distributed Power Management) とは
- 簡単にいうと、vSphereクラスタのリソースが余っていると自動的に仮想マシンをvMotionで寄せて、空いたESXiホストをパワーオフしてくれる機能です。
- リソースが不足しそうになった場合は自動的にパワーオフされているESXiホストをパワーオンし、仮想マシンをvMotionして戻してくれるので安心です。
- この機能を有効にすることで、不要なタイミングだけESXiホストの電源を落として消費電力を抑制することができます。
- [公式ドキュメント](https://docs.vmware.com/jp/VMware-vSphere/8.0/vsphere-resource-management/GUID-5E5E349A-4644-4C9C-B434-1C0243EBDC80.html)を引用すると以下の通り。
> vSphere DPM は、クラスタにあるすべての仮想マシンのメモリ リソース、および CPU リソースの度重なる需要を監視し、この需要と、クラスタのすべてのホストで使用可能なリソース キャパシティの総量とを比較します。余剰キャパシティが十分にある場合、vSphere DPM は 1 台以上のホストをスタンバイ モードにし、それらの仮想マシンを別のホストに移行したあとでパワーオフします。逆に、容量が不足しそうな場合、DRS はホストのスタンバイ モードを終了し （パワーオンし）、vMotion を使用して仮想マシンをそれらのホストに移行します。これらの計算を行う場合、vSphere DPM は現在の需要だけではなく、ユーザーが指定した仮想マシンのリソース予約についても考慮します。

# 最適なのはVDI環境
- vSphere DPMによる電力削減の効果が高い環境はどんな環境なのかを考えてみます。
- 「電力削減の効果が高い環境＝vSphere DPMがよく機能する」と考えると、リソースの需要の波が大きい環境や、需要が低い時間帯が長い環境で効果が高そうです。
- VDI環境は朝から夕方にかけてが需要のピークで、深夜から早朝にかけては極端に使用率が下がる特性があります。まさに、vSphere DPMを使うべき環境といえます。

# vSAN環境で使えないのは要注意
- vSphere DPMは、ESXiホストのリソース使用状況を見て、必要ないESXiホストをシャットダウンしてくれるものなので、ESXiホストがストレージリソースを共有しているvSANなどのHCI環境では使えない点は要注意です。
- 勝手にESXiホストが落ちてしまうと、使用可能なストレージ容量が一時的に減ってしまったり、最悪の場合はデータの可用性を維持できずに特定のデータにアクセスが出来なくなってしまいます。
- vSphere DPMを使うのは3Tier構成だけにしましょう。

# まとめ
- vSphere DPMを使うことで、電力消費量を抑えたエコなVMware vSphere環境を作ることができます。
- 特に適しているのが昼夜でリソースの需要差が激しいVDI環境で、vSANなどのHCI環境では使えない点は要注意です。
- エンジニアとして設計を見直すだけで企業のSDGs/ESGな取り組みに貢献でき、絶賛値上がり中の電気代削減にも貢献でき、良いことしかない！
メタバースの周辺情報（順天堂大学と日本IBMの事例を中心に）

# メタバース
「メタバース（Metaverse）」は、「Meta（超越した）」と「Universe（宇宙）」を組み合わせた造語で、「他者と共有体験できるオンライン上の3D仮想空間」を指しています。

米国の著名投資家であるMatthew Ball氏が2020年に同氏のブログで語ったメタバースの定義が分かりやすいのですが、同氏によれば、メタバースには以下の7つの要件があるとしています。

**＜メタバースの7つの要件＞**
Persistent（永続的である）
Synchronous and live（同時体験＆リアルタイムのライブ性）
No cap to concurrent participants（参加人数が無制限）
Fully functioning economy（参加者によるモノの制作・保有・投資・売買などが可能）
Both digital & physical worlds（デジタルと物理、両方の世界にまたがる）
Unprecedented interoperability（今までにない相互運用性）
Wide range of contributors（数多くの企業／個人がコンテンツや体験を供給する）


### 市場ポテンシャル：アクセンチュア

https://www.accenture.com/jp-ja/insights/technology/technology-trends-2022

### 市場ポテンシャル：ゴールドマンサックス

https://news.bitcoin.com/goldman-sachs-metaverse-8-trillion-opportunity/


# 順天堂大学とIBM
https://medicaldx-jp.com/news/359

## 患者との面会機会の増加
コロナ禍で患者との面会に制限がかかる中、メタバースが効果を発揮した。

## お見舞いハードル（遠慮と時間の制約）が下がる
予防医学研究者の石川善樹は、「つながり」が少ないと死亡率が２倍／お見舞いにきてくれる人の数で余命が変わると述べています。

https://www.kinokuniya.co.jp/f/dsg-01-9784838727216

## 歩けない患者がメタバース上で歩くことでプロテウス効果が
:::note info
**プロテウス効果**
オンラインゲームなどの仮想空間上のアバター（自分の分身となるキャラクター）の見た目がユーザーの行動特性に影響を与える、とされる心理効果のこと。

https://jinjibu.jp/keyword/detl/1055/
:::

<br>


>**Virtual Superheroes: Using Superpowers in Virtual Reality to Encourage Prosocial Behavior**

https://journals.plos.org/plosone/article?id=10.1371/journal.pone.0055003

<br>


>**筋肉質アバタを用いたプロテウス効果が重さ知覚に与える影響**

https://conference.vrsj.org/ac2020/program/doc/2A2-2_PR0025.pdf

<br>


>**ドラゴンアバタを用いたプロテウス効果の生起による高所に対する恐怖の抑制（基礎論文）**

https://www.jstage.jst.go.jp/article/tvrsj/25/1/25_2/_pdf/-char/ja

# 現実には実現不可能な状況の共有
メタバース上においては現実には実現不可能な環境や状況などをつくり出し、かつそれを多くの人と共通体験することができます。エンターテインメントとして現実にはあり得ない環境を体験するサービスの提供などはイメージしやすいでしょう。また、例えば研究において、シミュレーションをメタバース上で具現化し、議論を活性化させ、イノベーションを促進させられる可能性もあります。

> **認知症体験**

https://www.wakasa-iryo.com/blog/7100/

<br>

> **車椅子や義肢装具の装着が可能なマラソン大会**

https://ideasforgood.jp/2022/07/11/metathon/

# NFTを前提とした

## デジタルアートを販売するギャラリー
ブロックチェーンによって信頼性を担保されたNFTの存在により、データの改ざんや不正利用ができないようになったことで、デジタル資産の価値が保証されるのです。

https://www.spatial.io/



## 将来のダメな自分を体験


# well-beingのためのメタバース
居場所がたっくさんある＋居場所ごとに色々な人格がある

・困っている人を助けて幸せを感じるのは人間だけ
・希望を失った大人が子供の頃のようにまた夢を持てる場所

さまざまな「不」と相性の良いメタバースだが、またバースの活用によってサードプレイスをゲットした人はメタバースに残り続けるのか？・・・



## idea
・なりたい自分をアバタにすることで、プロテウス効果を狙う
・メタバースで遠慮を取り除く
・プレゼン練習（聴講者がアバタであるほうが緊張しない？）
・覗き見（サークル見学：リアルで覗き見はできないけど・・・）
minikube on docker on WSL2 の Ingress に Windows からアクセスする

minikube を使うと WSL2 上の docker 環境などをバックエンドとして開発用クラスタが構築できて便利ですよね。nginx Ingress コントローラーのセットアップだって簡単です：

```bash
# minikube クラスタを開始する
minikube start

# minikube クラスタで nginx Ingress コントローラーを有効化する
minikube addons enable ingress

# サンプルアプリと Ingress をデプロイする
kubectl create deployment web --image=gcr.io/google-samples/hello-app:1.0
kubectl expose deployment web --type=ClusterIP --port=8080
kubectl apply -f https://kubernetes.io/examples/service/networking/example-ingress.yaml

# ADDRESS 欄に IP アドレスが表示されるのを待つ
kubectl get ingress -w

#NAME              CLASS   HOSTS              ADDRESS   PORTS   AGE
#example-ingress   nginx   hello-world.info             80      5s
#example-ingress   nginx   hello-world.info   192.168.49.2   80      26s

# WSL2 内で Host ヘッダを指定してアクセスすると期待したレスポンスが表示される
curl -H 'Host:hello-world.info' http://192.168.49.2/
```

さて、Ingress は利用可能になりましたが、この状態では Windows 上のブラウザから表示できません。たとえば、NodePort なサービスをデプロイしている場合なら Windows 上のブラウザからでもアクセスできます。WSL2 のポート `N` がリッスンしている時にブラウザで `http://127.0.0.1:N` にアクセスすると、Windows が良しなに解釈して WSL2 側に通してくれるからです。しかし Ingress の場合、上記のように minukube machine を指す WSL2 上のローカル IP アドレス（`$(minikube ip)`）にアクセスしたいため勝手が違います。

## ポートフォワードで minikube machine にアクセスする

要は `$(minikube ip):80`（https の場合は `$(minikube ip):443`）を `127.0.0.1` にポートフォワードできればいいわけです。手段としては iptables でも何でもいいのですが、ここではお手軽（？）な SSH ポートフォワードを使ってみましょう：

```bash
# minikube machine の 80 番ポートを、WSL2 の 8080 番にローカルポートフォワードする
ssh -N -i $(minikube ssh-key) -L 8080:localhost:80 docker@$(minikube ip)

# 特権ポートの場合は sudo が必要
sudo ssh -N -i $(minikube ssh-key) -L 80:localhost:80 docker@$(minikube ip)
```

![ingress-minikube-wsl2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463374/36e36717-c3aa-9f82-24c6-075917b828dd.jpeg)

ブラウザの代わりに `curl.exe` でアクセスしましたが、問題なさそうですね。hosts ファイルを編集すれば、ブラウザからもアクセスできます：

![ingress-minikube-wsl2-1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/463374/db8267e8-408b-ae72-eb4b-5c617abc8d06.jpeg)

## 参考リンク

* [Minikube上でNGINX Ingressコントローラーを使用してIngressをセットアップする](https://kubernetes.io/ja/docs/tasks/access-application-cluster/ingress-minikube/)
* [curlコマンドでHTTPヘッダを扱うレシピ](https://qiita.com/youcune/items/45271a32dccb7498033f)
* [iptablesを使ってWebサーバをポートフォワーディング](https://qiita.com/showchan33/items/407bde52c44d1d8e1a6d)
* [Linuxがほぼそのまま動くようになった「WSL2」のネットワーク機能](https://atmarkit.itmedia.co.jp/ait/articles/1909/09/news020.html)
* [WSL2 上のアプリケーションに別ホストからアクセスする方法（管理者権限なし）](https://qiita.com/yokra9/items/cc81b2869ec1e9bda950)
DockerのMySQLコンテナへ初期データを投入する

## 前提
自動テスト用のデータベースサーバを作りたいけど、テーブル定義が変更される度にコンテナ内でdumpファイルを実行するのが面倒臭い！
コンテナを立ち上げる度にdumpファイルをセットしてくれないかのう、、

という課題にぶち当たった際に、以下の機能を知ったので忘備録的に残しておきます。

Initializing a fresh instance
https://hub.docker.com/_/mysql

# 最終的なディレクトリ構成
```
docker
├── docker-compose.yml
├── .env
└── initdb.d
    └── test_dump.sql
```

# 初期データを入れる方法
## docker-compose.ymlの作成

initdb.d/に置いたdumpファイルを、docker-entrypoint-initdb.d/にマウントしてくれる
```docker-compose.yml
version: "3"
services:
  mysql:
    image: mysql:8.0
    container_name: test
    volumes:
      # initdb.d配下にある.sh, .sql and .sql.gz拡張子をアルファベット順に実行出来る
      - ./initdb.d:/docker-entrypoint-initdb.d
    environment:
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USER}
      - MYSQL_PASSWORD=${DB_PASS}
      - MYSQL_ROOT_PASSWORD=${DB_PASS}
      - TZ=${TZ}
    ports:
      - 3306:3306
```
```.env
DB_NAME=test_database
DB_USER=test
DB_PASS=test_password
TZ=Asia/Tokyo
```

## dumpファイルをinitdb.d/に配置する
```
[cyber_diver@server initdb.d]$ ls
test_dump.sql
```

## コンテナを立ち上げる
```
[cyber_diver@server docker]$ docker-compose up -d
```

## コンテナに入ってマウントされたファイルを確認する
test_dump.sqlが生成されていることを確認
```
[cyber_diver@server docker]$ docker exec -it test bash
bash-4.4# cd docker-entrypoint-initdb.d/                               
bash-4.4# ls
test_dump.sql
```

## テーブルが作られていることを確認

やったぜ
```
bash-4.4# mysql -uroot -p test_database
Enter password: 
...

mysql> show tables;
+------------------------------------------------------------+
| Tables_in_test_database                                    |
+------------------------------------------------------------+
| test_table                                                 |
+------------------------------------------------------------+
1 rows in set (0.04 sec)
```
ファイルのディスク容量圧迫の原因調査

# 【ファイルのディスク容量圧迫の原因調査】
ディスクの容量を圧迫している原因を特定する。

## サーバの容量を確認
- dfコマンドでサーバのサイズを確認
    - -hオプション：サイズ単位(人間がわかりやすいように)
```
$ df -h
ファイルシス   サイズ  使用  残り 使用% マウント位置
/dev/vda1         50G   43G  7.6G   85% /
devtmpfs         1.9G     0  1.9G    0% /dev
tmpfs            1.9G     0  1.9G    0% /dev/shm
tmpfs            1.9G  664K  1.9G    1% /run
tmpfs            1.9G     0  1.9G    0% /sys/fs/cgroup
tmpfs            379M     0  379M    0% /run/user/XXX
```
- ディスクの容量は50G
    - そのうち85%が使用済みということがわかった。
- tmpfsは一時ディレクトリ、物理メモリ上にキャッシュファイルや作業用ファイルを置いている。

## duコマンドでディレクトリの使用量を確認
- duコマンド：カレントディレクトリ下のディスク使用量をディレクトリごとに集計して表示
    - -sオプション：カレントディレクトリのディスク使用量を表示（サブディレクトリのディスク使用量は表示しない）
    - -mオプション：メガバイト単位で表示
- sortコマンド
    - -nオプション：数値
    - -rオプション：降順に並べる
- `/var/`以下のファイルを確認していく。
    - 多いものから絞り込んでいくことにした。

```
$ sudo du -sm /var/* | sort -nr
20968	/var/www
5120	/var/swapfile
4729	/var/log
293		/var/cache
152		/var/lib
79		/var/ossec
8		/var/spool
1		/var/tmp
1		/var/db
0		/var/run
0		/var/opt
0		/var/mail
0		/var/lock
0		/var/local
$ sudo du -sm /var/www/* | sort -nr
20968	/var/www/example
0		/var/www/html
0		/var/www/cgi-bin
$ sudo du -sm /var/www/example/* | sort -nr
20573	/var/www/example/shared
361		/var/www/example/releases
35		/var/www/example/repo
1		/var/www/example/revisions.log
0		/var/www/example/current
$ sudo du -sm /var/www/example/shared/* | sort -nr
20470	/var/www/example/shared/log_data
102		/var/www/example/shared/bundle
2		/var/www/example/shared/composer.phar
1		/var/www/example/shared/tmp
0		/var/www/example/shared/node_modules
$ sudo du -sm /var/www/example/shared/log_data/* | sort -nr
8732	/var/www/example/shared/log_data/example-batch_log
5628	/var/www/example/shared/log_data/example-lib
101		/var/www/example/shared/log_data/delete_product_image_batch20210909.log
-- snip --
```

## lsコマンドでファイルの詳細を確認
- lsコマンド
    - -lオプション：長いフォーマットで表示。ディレクトリを指定した場合、最初にトータルのブロック数を表示し、ディレクトリ内のファイルの情報を表示
    - -tオプション：ファイルの更新日が新しい順に表示
    - -rオプション：並び順を降順にする

```
$ cd /var/www/example/shared/log_data/example-batch_log/
$ ls -ltr
合計 20
drwxr-xr-x+ 4 app app 4096 12月 21  2018 2018
drwxr-xr-x+ 4 app app 4096  7月  3  2019 2019
drwxr-xr-x+ 4 app app 4096  8月  8  2020 2020
drwxr-xr-x+ 4 app app 4096  9月  1  2021 2021
drwxr-xr-x+ 4 app app 4096  7月  1 19:03 2022
```
```
cd /var/www/example/shared/log_data/example-lib
$ ls -hltr
合計 5.6G
-rw-rw-r--+ 1 app app 5.6G 11月  4 10:01 logger.log
```

## その他
- 1年以上経過しているログはサーバーから削除すると良さそう
- AWSのS3等にログを保存しておくと尚良さそう

## 参考
https://www.suzu6.net/posts/113-command-du/

https://atmarkit.itmedia.co.jp/ait/articles/1606/27/news018.html
無限次元空間を想定する理由

ある問題を解決するのに、いろいろな方法がある。　


 <この項は書きかけです。順次追記します。>


# 経験を網状に織り成す　
自己または関係者の経験を体系的に整理して、問題解決を図る方法。　

Data Robotなどの機械学習を使う方法の一つでもある。　
 

経験を網状に織り成す方法でも、整理の仕方によっては、無限次元空間を想定して、既存のデータから関連の深い次元に絞り込む場合がある。　

経験を出発点にすれば、無限次元空間を想定しないとは限らない。



# 体系的な模型を作る　

体系的な模型を作ろうと思ったら、まず、無限次元空間を想定することをお勧めする。　


この方法が絶対とは言わない。　

最終的に一次元空間に就職させたいとしたら、無限次元から始める必要はないかもしれない。　

いやなのは、何か決め打ちにするような人たちがいる場合。　


たとえば、「Humility（謙虚）」、「Respect（尊敬）」、「Trust（信頼）」という三次元が大事だという人がいたとしよう。　

お金持ち相手の有償サービスであれば、成立しうるだろう。　

お金を持っている人が、お金を持っている人を相手にサービスするのであれば、「Humility（謙虚）」、「Respect（尊敬）」、「Trust（信頼）」があればうまく行くい確率が高いことは想像しやすい。　

不特定多数への無償のWebサービスであればどうだろう。　

インタネットに限らず、電子計算機資源は戦争のための技術として発展してきている。　


# 戦争
まず、軸として必要なのは「戦争」に対する対応だろう。　

9.11の文脈では、戦争に関係のない地域もなければ、戦争に関係のない空間もない。　

ありとあらゆる場所が、過去の戦争の爪痕をのこしており、それを引きずって生きている。　

次に考慮に入れたいのは、京アニ事件かもしれない。　

自分が一番悔やむのは、これだけ京アニの愛好者だったのに、京アニ本社に行ったことがないことが大きな問題点だったと。　

建築の専門家ではないが、安全の専門家として、何か言えたことがあるはずだ。　

3.11の時にくずれかけて工場が稼働しなくなった建物に、3.11より前に訪問し、違和感を感じたことがある。違和感はお伝えしたが、「大丈夫」という返事だった。　

阪神大震災の前に、ロサンゼルスで高速道路がずたずたになった時に、テレビの画面である専門家は言った。日本ではこんなことは起こらない。嘘だったね。　

誰が、その時点でまともそうなことを言っても、根拠を示さない発言を信じてはいけない。　

あるWebサービスで、何か指針を作ろうとした場合、手元にあるデータを解析し、そのデータを根拠とした発言すればよい。エンジニアをどこかのありえない桃源郷に誘導しているのでなければ。　

自動運転技術が兵器そのものであることは、自動運転ヘリコプターが禁輸になったことkらも想定の範囲内だろう。　どんな技術も戦争に利用されたらおしまいだ。　それを防ぐ方法が、簡単にはないから、ひとまず、無限次元空間を想定するところから始めようとしている。


# 仮説

「Humility（謙虚）」、「Respect（尊敬）」、「Trust（信頼）」は役にたつかどうかは、それぞれについて詳細化してみる。　


戦場で「Humility（謙虚）」は何の役にたつだろうか。　

防衛方法は、ありとあらゆる可能性を考慮して、大事そうなことに限定して対応することは可能かもしれない。「Humility（謙虚）」ではないかもしれない。　

戦争相手には、どこまでの防衛手段になるだろうか。　

核戦争が、エンジニアにとっての、２０世紀の三大負債の一つという意見がある。　
核爆弾を開発してしまったエンジニアたちが、核戦争に反対したことには「Respect（尊敬）」の念を禁じえない。自分たちがそうならないという保証はどこにもないのだろう。　

IT業界にいる限り、知らず識らずに、強大な兵器作成に協力していたことになるかもしれないのだから。　

戦争で「Trust（信頼）」が役にたつかどうかは、「Respect（尊敬）」と同様、不確定だろう。　

相手が核兵器に都を伸ばさないというのは信頼だけでは成り立たないという論法で、ここまで核開発が伸びてきた。原子力発電所の方式が、核爆弾の副産物または、原子力発電所自体が核爆弾の副産物だという仮説は、電力業界の仕事をすると聞こえてくる。　

強い方についたら生き延びられるという保証はないことが9.11以降のエンジニアの生き方ではないのだろうか。　

# 公共の福祉　

権利と義務の前に。仮説（147）

https://qiita.com/kaizen_nagoya/items/47d4e992d0fd340403fd

「公の秩序又は善良の風俗」を何だと思っているかを示さずに、何かの指針を示すのはいかがなものだろう。　

誰かが、何かをやってから、それは「公の秩序又は善良の風俗」に反しているというのは後出しじゃんけんだと思われても仕方がない。　

「公の秩序又は善良の風俗」は、戦争に対する対応と、犯罪に対する対応と、自然災害に対する対応を歴するとよいだろう。　

現在存在するデータから、どういう方向性が、過去の公共の福祉に役立ったことを、集約的であれ、部分的であれ、表示せずに抽象的な言説を振り回すのはエンジニアの仕事ではないだろう。　

では、お前は何のデータを示しているのかという問いに対しては、すべての記事そのものを、機械学習にかけてみれば、その一端がわかるはずだということを記録して筆を置く。　

 ＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞

# 文書履歴(document history)
ver. 0.01 初稿 　20221108




























京アニ
【SwiftUI】PreviewでRunScriptが走らないようにする

# はじめに
Preview時にRunScriptが走ってPreviewが長くなるという問題に直面したので、Previewの時はRunScriptを実行しないようにします。

# 現在のスクリプト
[こちら](https://qiita.com/SNQ-2001/items/4ad7600e1bc9d90c839a)のスクリプトをサンプルとして使います
```shell
export PATH=/opt/homebrew/bin:$PATH

if which mint >/dev/null; then
    # SwiftFormat
    xcrun --sdk macosx mint run swiftformat .
else 
    echo 'warning: mint not installed.'
fi
```

# 修正後のスクリプト

```shell
export PATH=/opt/homebrew/bin:$PATH

if which mint >/dev/null && [ \"$ENABLE_PREVIEWS\" == \"NO\" ]; then
    # SwiftFormat
    xcrun --sdk macosx mint run swiftformat .
else 
    echo 'warning: skip run script'
fi
```

:::note info
**ポイント**
`[ \"$ENABLE_PREVIEWS\" == \"NO\" ]`
ここでPreviewか判定しています
:::

# 参考記事
https://qiita.com/temoki/items/5fddc026b4817c6ce5ff
【Perl初学者】keys関数

# keys関数とは

ハッシュのすべてのキーを取得することができる。取得するキーの順序は不定。
ハッシュのリファレンスを引数として渡す場合は、デリファレンスをする必要あり。

例)
```;hello.pl
my $score = keys(%$hash);#複雑なハッシュの場合は%{$hash}とする
```
ハッシュのキーと値をすべて出力
```;hello.pl
my $foods = {'apple' => 'りんご', 'banana' => 'バナナ', 'orange' => 'オレンジ'};
for my $food (sort keys(%$foods)) {
  print "$food:$foods->{$food}\n";
};
```
Elixirで気軽にスクリプト

[シェルスクリプト]が苦手なので、いつも[Elixir][なぜElixir？]で気軽にスクリプトを書いています。

[escriptで実行ファイルを作る]方法がありますが、もっと簡単に気軽にやりたいのです。

[なぜElixir？]: https://elixirschool.com/ja/why
[シェルスクリプト]: https://ja.wikipedia.org/wiki/%E3%82%B7%E3%82%A7%E3%83%AB%E3%82%B9%E3%82%AF%E3%83%AA%E3%83%97%E3%83%88
[escriptで実行ファイルを作る]: https://elixirschool.com/ja/lessons/intermediate/escripts

## 論よりRUN

### `toukon.exs`ファイルを作る

```elixir
❯ echo 'IO.puts("闘魂🔥")' > toukon.exs
```

`闘魂🔥`を表示するElixirコードが書かれたファイルが出来ました。早速`elixir`コマンドで実行してみたいと思います。

注意：サンプルコードにある`❯ `はコマンド入力待ち状態であることを示す表示([コマンドプロンプト])です。コピーするときはそれを取り除いてください。

[コマンドプロンプト]: https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%9E%E3%83%B3%E3%83%89%E3%83%97%E3%83%AD%E3%83%B3%E3%83%97%E3%83%88

### `elixir`コマンドで実行

```bash
❯ elixir --help
Usage: elixir [options] [.exs file] [data]
...
```

```bash
❯ elixir toukon.exs
闘魂🔥
```

闘魂が燃えました。

### ファイル名で実行

試しに[シェルスクリプト]みたいにファイル名をコマンドとして使えるようにします。

何も準備せずにやるとエラーが出ます。順番に対処していきます。

#### エラー1: permission denied

ファイルを実行する権限が必要です。

```bash
❯ ./toukon.exs
zsh: permission denied: ./toukon.exs
```

[chmod]でファイルへのアクセス権を変更します。

```
❯ chmod a+x ./toukon.exs
```

[chmod]: https://ja.wikipedia.org/wiki/Chmod

#### エラー2: syntax error

ElixirコードがElixirコードとして認識されていないようです。

ファイルを実行する環境にElixirコードを実行したいとお願いする必要があります。

```bash
❯ ./toukon.exs
./toukon.exs: line 1: syntax error near unexpected token `"闘魂🔥"'
./toukon.exs: line 1: `IO.puts("闘魂🔥")'
```

スクリプトファイルに[shebang]を追加して起動時にスクリプトを読み込むインタプリタを指定します。

Elixirのインタプリタを使いたいので以下のようにおまじないを書きます。

```elixir
#!/usr/bin/env elixir
IO.puts("闘魂🔥")
```

お気に入りのテキストエディターで直接編集した方が早いかもしれませんが、以下のようなコマンドでもファイルの中身を入れ替えることができます。

```bash
❯ cat <<-EOF > ./toukon.exs
#!/usr/bin/env elixir
IO.puts("闘魂🔥")
EOF
```

再度あらためてファイルを実行してみます。

```elixir
❯ ./toukon.exs
闘魂🔥
```

闘魂が燃えました。

[shebang]: https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%90%E3%83%B3_(Unix)

### Mix.install

[Mix.install/2]を用いて、Elixirスクリプトの中で直接Elixirパッケージをインストールすることも可能です。

```bash
❯ cat <<-EOF > ./weather.exs
#! /usr/bin/env elixir
Mix.install [{:req, "~> 0.3.0"}]

weather =
  case Req.get!("https://wttr.in?format=3") do
    %{status: 200, body: body} -> body
    _ -> "error😭"
  end

IO.puts(weather)
EOF
```

```bash
❯ chmod a+x ./weather.exs
```

```bash
❯ ./weather.exs
Washington, District of Columbia, United States: ⛅️  +56°F
```

[Mix.install/2]: https://hexdocs.pm/mix/Mix.html#install/2

闘魂に関してはこの記事がおすすめです。職種を問わずひらめきが得られると思います。

https://note.com/awesomey/n/n4d8c355bc8f7


## ご参考までに

https://qiita.com/piacerex/items/e0b6e46b1325bb931122

https://qiita.com/torifukukaiou/items/1edb3e961acf002478fd

https://qiita.com/piacerex/items/e5590fa287d3c89eeebf
[Xcode] [App Store]　周りのあれやこれや

## 初めに
Unityでゲームアプリをリリースする上でXcodeおよびAppStore関連で詰まった所
意味の分からなかった単語などを自分なりに復習材料としてまとめました。
初めてQiitaで記事を書くので文章等、下手で読みづらいと思いますが、ご了承ください。

所々あとで見返すように書いてます。

## Xcode関連
まず初めに、XcodeにてValidateを行った際に下記のようなエラーが吐かれました
(厳密にはエラーかどうかわかりませんが)
![xcode.Error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1079865/829c0776-3c0d-c111-4440-92ac6a0640ff.png)
- non-public selectorsになぜなってしまうのか考えてみた時
①asset周りでのエラー(Unity側でアプリアイコンの画像が.pngだから~~と注意が出ていたので)
②ゲーム内にバグがある。
③xcode自体に問題がある。 

そもそもValidateとは？

| 単語 | 意味 | 参考サイト |
| --- | --- | --- |
|Validate |iOS アプリケーションを IPA ファイルとしてビルドするために行ったArchiveしたアプリがアップロードしても大丈夫か検証すること|https://www.create-forever.games/unity-ios-app-store-ipa3/#:~:text=Player%20Settings%20%E3%82%88%E3%82%8A-,Validate%20App%20%2F%20Distribute%20App,%E3%81%99%E3%82%8B%E3%80%8D%E3%80%81%E3%81%A8%E3%81%84%E3%81%86%E3%82%A4%E3%83%A1%E3%83%BC%E3%82%B8%E3%81%A7%E3%81%99%E3%80%82 |

- 結果として3番のXcode自体の問題として解決することができました。
自分が使っていたXcodeのバージョンが最新の14(2022/11/8)だったのですが
バージョン13.3を入れ直して行ったところうまくいきました。



複数のXcodeを使うときに参考にしたサイト
(https://fukatsu.tech/xcode-multiple)

Xcodeを扱うのは余り慣れていなかったので、
どんどんいじっていくべきだなと反省,,,




## AppStore関連

| 単語 | 意味 | 参考サイト |
| --- | --- | --- |
| Certificate| 俺はApple Developerだよ的な証明書|　1年で切れるから更新忘れるな俺！|    
| Provisioning Profile| App ID と Certificateと端末IDを足したもの | 頑張って中身理解してください(https://zenn.dev/miyataka/articles/64083d85c5bbca)　　 ←わかりやすい！！|
| App ID| App IDはアプリを特定し、アプリと開発チームと関連付けるためにAppleが使用します。| MT.Hackable C'mon!!!| 
| Bundle Identifier|バンドルIDは、アプリケーションを識別ために使われます。 こやつでAppConnectと繋げてる| com.社名.ゲーム名| 



## 記事を書き終えて
最後の方雑になったから、一気に書くか日を跨ぐなど工夫した方がいいと勉強になりました。
まぁ書かないよりはよかです。
以上。
paiza.ioでelixir その53

# 概要
paiza.ioでelixirやってみた。
IO使ってみた。

# サンプルコード

```

IO.chardata_to_string([0x00E6, 0x00DF])
|> IO.puts
IO.chardata_to_string([0x0061, "bc"])
|> IO.puts
IO.chardata_to_string("string")
|> IO.puts

IO.gets("What is your name?\n")
|> IO.puts

IO.inspect(<<0, 1, 2>>, width: 40)

[1, 2, 3]
|> IO.inspect(label: "before")
|> Enum.map(&(&1 * 2))
|> IO.inspect(label: "after")
|> Enum.sum()
|> IO.puts

IO.iodata_length([1, 2 | <<3, 4>>])
|> IO.puts

bin1 = <<1, 2, 3>>
bin2 = <<4, 5>>
bin3 = <<6>>
IO.iodata_to_binary([bin1, 1, [2, 3, bin2], 4 | bin3])
|> IO.inspect

bin = <<1, 2, 3>>
IO.iodata_to_binary(bin)
|> IO.inspect

IO.puts("Hello World!")
IO.write("sample")
IO.puts(:stderr, "error")

Enum.each(IO.stream(:stdio, :line), &IO.write(&1))

IO.warn("variable bar is unused")




```

# 実行結果

```
æß
abc
string
What is your name?
a

<<0, 1, 2>>
before: [1, 2, 3]
after: [2, 4, 6]
12
4
<<1, 2, 3, 1, 2, 3, 4, 5, 4, 6>>
<<1, 2, 3>>
Hello World!
samplehello


```

# 成果物

https://paiza.io/projects/NqMuOgj4YB0PprBTHr2kAQ?language=elixir


以上。
【インフラエンジニア】フリーランスになるまで(予定)

# フリーランスになる(予定)までの道のり

本記事はフリーランスに数か月後になると決意を固めた男の経緯を綴っていく
なお、2022年11月現在ではまだインフラエンジニアの正社員として働いている。


## そもそもお前誰？

私の経歴を軽く語っておこう

1. 運用/監視:2年
2. セキュリティアナリスト(SOC):1年
3. サーバ構築/設計:2年


上記を見てもらえればわかるように、インフラエンジニアとしての経歴を良い感じに
積んできた。しかしながら前職では炎上案件に突っ込まれ転職。
転職後はSESをメインとした会社で派遣契約を結びサーバの構築/設計を行っている。
AWS案件を触れなかったのがネックで、現在AWSプラクティショナーを必死に勉強している。

## なぜフリーランスになろうと決意したのか
転職したのが9月。手取りは28万円程。案件単価は55万。
うちの会社は案件単価、案件内容を詳細に社員に公開している。
それが売りだと思い転職を決意した。仕事内容は恵まれており平和な毎日を
くらしている。


だが待ってほしい。
案件単価は55万　手取りは28万(あえてぼかさせて頂く。)

**会社...ピンハネしすぎでは？** 

となったわけである。


## 実際に案件をさがしてみた
でるはでるは今の自分で十二分に業務を遂行できそうな案件が、
**50万～70万でごろごろと**
これをみて転職後数か月でフリーランスになろうと決意した。

物価高がやばすぎて現状の手取りでは満足に貯蓄もできないというのも理由の一つである。 

## フリーランスのエージェントに登録

実際にフリーランスの案件を紹介してくれるエージェント3社に登録
笑ってしまったのがテンプレートとして推奨しているスキルシートが
わが社が使用しているスキルーシートと完全に(配色は違ったが)一緒なこと。
このスキルシートは全国共通なのか？と苦笑しつつスキルシートを送付。

今週～来週にかけてエージェントさんとの面談なので、気を張らずに楽しんでいきたい。

以上。進展があり次第更新をする予定。皆さんの参考になればと思います。
ミク歌でStable DiffusionとDance Diffusionを使ってみた

実は、辺境のYouTubeチャンネルに、素人臭い初音ミクの歌とかバ美肉動画とかを偽名でアップロードしてるんですが、最近の流行に乗っかって色々試してみました。技術的な解説というよりも、実践的な体験談になります。

## 背景をStable Diffusionで描く

ミク歌MVの背景画像作成にはStable Diffusionが良さそうです。なお、Google Colabで有害画像を生成してBANされるのが怖いので、ローカルで頑張ることにします。グラボが貧弱(nVidia GeForce GTX 1660、6GB)で苦戦していたのですが、<b>Stable Diffusion web UI</b>の登場により劇的に楽になりました。導入方法はこちらのサイトを参考にさせていただきました。

https://note.com/npaka/n/nc8b0e9a91d97

で、txt2imgを使って絵を作ります。写実的な雰囲気にしたい場合、カメラ属性指定と3D sculpt指定が効きます。歌詞の内容に合わせて「雨の夜に、群衆をバックにガーゴイルの像が立っている」という絵が欲しくて、以下のようなプロンプトを用いました。

```
a pan shot, front focus on a chimera gargoyle statue, crowds on a rainy street, reflecting electric light, modern building, heavy rain, SIGMA 85 mm F/1.4, 1/10 sec shutter, great detail, a masterpiece, 3D Sculpt
```

作った動画はこちら。

https://youtu.be/Bw37hQEO77s

もう一つ曲を作ったけど、そちらの背景はフラクタル画像を動画にできるkalles fraktaler 2というソフトを使いました。Stable Diffusionもアニメーションにできるのだけど(stable-diffusion-animation)、まだ使いこなせないです。

https://youtu.be/J1hU8IZkDHY


## Dance Diffusionの音源を使う

次はDance Diffusionです。長い曲を作るのは難しそうですが、サンプリング素材として使うことにしました。AIに芸術が奪われるというテーマで一曲書いたので、その中に4,5個のAI素材を入れてみました。作った動画はこちら。背景もStable Diffusionです。

https://youtu.be/EugGqztNRZI

Hugging Faceに以下サービスがありました。以下のサイトで6秒間までならお手軽に作れます。モデルmaestro-150kで作ったピアノの音の他、水の音や男の声を使いました。

https://huggingface.co/spaces/harmonai/dance-diffusion


## AI音読サービスで英語の解説動画を作る

ついでにもう一つ。僕は昔からバ美肉がやってみたくて、VroidStudioで作ったモデルをBlenderで編集したり3teneで動かしたりして遊んでいたのですが、高級なマイクも良い声も持っていないし、なかなか満足なものが作れていませんでした。でも、AI音読サービスなら奇麗な声で解説動画を作ることができます。しかも、発音に自信が無くても英語圏を相手にVTuberができるようになります。今回は以下のサイトを使いました。

https://ondoku3.com/

こちらのサイト、有償プランは980円からですが、5000文字までならクレジット明記前提で無料になっているようです。試したい人向けのコツとしては、Microsoft Wordとかに書いた文章をWindowsに音読させて、満足いく状態まで原稿を完成させてから、文字数制限のあるサイトにコピペするのがいいと思います。作った動画はこちら。

https://youtu.be/LDlFHc96u9c

なお、英訳もAI（DeepL）の助けを借りてますが、それだけでは流石にダメで、特に英語の歌詞については、韻を調べたり、ネイティブの英会話講師に見せてコメントをもらったりしています。あと、欧米圏の詩の韻律についての知識も必要で、それこそアリストテレスの『詩学』の時代からダクテュロス・ペンタメトロスとかの規律があって、彼らは強弱調をすごい意識するらしいのですが・・・もう分からんですよそんなこと。今日アップした曲はまだネイティブからのフィードバックをもらっていないので、何か変だったら指摘ください。

## AI技術を使って創作してみた感想

以上、僕のような一般人にとっても、AIは何かを作るための便利なツールになってきたと思います。逆に、一つのテクニックだけに鍛錬を集中させてしまうと、その技術がAIに奪われたときに厳しい状況に置かれる可能性もあります。更にもっとAIが進歩すれば、個々人の作家性すら奪われてしまうのでは、というような恐怖も感じます。が、個人的にはそこまで心配していません。動画を見てくれた人は分かると思いますが、僕は絵も作曲も映像制作も、素人ですからね。逆に興味が広く浅く散らばりすぎて、何もできなくなりがちな人間です。そういう人間にとっては、<b>表現したいこと</b>が無くならない限り、それを助けるツールは多い方が良いと思います。
PMCONF2022見たものまとめ

本当にどの講演もタメになる内容ばかりで、時間見つけて録画を後追いで見ております。
自分がこれから目指していく方向はこっちだなあ〜。。。

# 見た講演
- **PM初心者が「MyPM像」を確立するまでのストーリー**
- **メタバースで再評価されるデザイン思考**
- **UXのプロ集団が提供するプロダクトマネジメント**
- **プロダクトマネジメントと人間中心設計～デザイナーからPMへのキャリアシフト～**
- **PMと民主主義**

その中で印象に残ったやつのまとめ
## PM初心者が「MyPM像」を確立するまでのストーリー
[前回記事参照](https://qiita.com/otsukatakashi/items/731ccdfd323939aad717 "pmconf2022で見たPM初心者の心構えのお話")

## PMと民主主義

コンウェイの法則のPM版あるんじゃね的な話からスタート。

民主主義自体ってどうなの？良いだけのものではない。しかしなんで政治でそれが使われるかというと、
色々な政治手法の中で一番マシだよねというものだから採用されている。
パフォーマンスよりもプロセスの正統性を重視したもの。
誰も取り残してはいけない設計には多様な視点が必要。
組織や会社、働き方に関する意思決定にはプロセスの納得感が重視される。これらのことは民主的に決めるのは正当性がある。

ただ企業のプロダクト開発としては民主主義がいいとは言い切れない。プロダクトビジョンを最短距離で実現するためにはそういうわけにもいかないこともある。

プロダクトマネージャーは *優しい終身の独裁者になる* ことを勧める。
**PdMは調整ではなく、決定をしよう**ということ。責任を持って、決定する。

アプローチとしては…
投票集めても参考まで。決めるのはオーナー。プロダクトビジョンをそれぞれ持ち寄るのではなく、まずオーナーがビジョンを示す。意思決定者は持ち回りや評価で交代などせず、原則オーナーは変えない。など

独裁とは書いたが、自分の好きにやっていいわけではなく、各社のMVVに従うことが前提である。
**コミットメントと説明責任。成果を出し、なぜこうしたかを語れることが必須。**

「決めることから逃げない。意思決定の量と質こそが学びと成果」

## プロダクトマネジメントと人間中心設計～デザイナーからPMへのキャリアシフト〜

UI/UXデザイナーから社内向けアプリ開発チームのPdMへ転向した方の講演。
PdMすることで人間中心設計を突き詰めていったというお話。
自分もここに似た方向性で進んでいけるかもしれないと感じた。

## UXのプロ集団が提供するプロダクトマネジメント

クライアントワークでのプロダクトマネジメントを主とした会社の話。大資本相手にPdMをするのでマネジメント業務に集中できるらしい
toB相手に期間限定で確実に成果を出すという点では、非常に難しい仕事と思われるが、それ専門の会社はレベルが高そう、、、、という印象でした
stable-diffusionでの作成ポイントまとめ

# AIによる呪文の違い

stable-diffusionとNovelAIでは、強調構文などに違いがあります。
Twitter等で情報を集めているとだんだん情報が混ざってしまい、わからなくなってきたので、整理を目的として公式の記述等を翻訳(deepl)したり、色々と書きたいと思います。

2022/11 現在、NovelAIには触れていないのでそちらについては疎いです。
飽きるまでは適宜更新していきたいと思っています。

# stable-diffusion
* 基本構文
単語同士の結合は ', '(カンマ)で行う。


* 強調構文
( )を使用すると、囲んだ言葉に対するモデルの注目度が上がり、
[ ]を使用すると注目度が下がります。
指定がない場合、係数は1.1となり括弧の数だけ乗算します。
指定する場合は文字の後ろに「:〇.〇」といった形で指定します。
また、( )[ ]自体をpromptに利用したい場合、下記例文のようにバックスラッシュを利用してください。

```
a (word)   - 単語への注目度を【1.1 】上げる
a ((word)) - 単語への注目度を【1.21】上げる (= 1.1 * 1.1)
a [word]   - 単語への注目度を【1.1 】下げる 
a (word:1.5)  - 単語への注目度を数値分かける (= 1 * 1.5)
a (word:0.25) - 単語への注目度を数値分かける (= 1 * 0.25)
a \(word\) - プロンプトにリテラル()文字を使用する
```
https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Features#attentionemphasis

* Negative prompt
ユーザーがモデルに余分な負荷や要件を課すことなく、見たくないものを指定できる方法です。
Stable Diffusion の通常の奇形 (余分な手足など) を除去する事ができます。
一時話題になった元素法典では、この機能に注目して作成されたものが多かったです。

https://github.com/AUTOMATIC1111/stable-diffusion-webui/wiki/Negative-prompt

https://note.com/sa1p/n/ne71c846326ac

# AI / モデルによる違い・ポイント
* NovelAI では強調構文の指定が異なります。
* モデルによって学習元の都合上、単語間をスペースで繋げるよりもアンダーバー(_)でつなげる時が良い物もあります。
* 絵文字でのprompt指定が可能のものもあります。(✌等)
* コマンド操作不要で使えるソフト「NMKD Stable Diffusion GUI」ではシームレス画像の作成が可能です。

# イラスト系AI作成でのポイント
Twitter等で見つけた情報をまとめます。

* 「NovelAIっぽい絵」を「平面的なイラストっぽい絵」で出力する方法
ネガティブプロンプトに「3d」を強調度合い変えて入れる

https://twitter.com/8co28/status/1587004598899703808

* 整っているイラストでよく見るpromptワード
    * ((masterpiece)), ((best quality))

# 最後に
何かあったら追記します。
コメントで他にも耳寄りな情報、ポイントがあれば教えてもらえると嬉しいです！
Visual Studio x Vim: insert, vim modeの動作をvimと同じにする。



## 問題点

Visual StudioでVimを扱う際にCtrl-CやCtrl-Vなどがvim modeでもコピー, ペーストとして扱われてしまう。本来vimだとCtrl-Vはブロック選択で使うので、このキーバインドを取られるとVimの良さを生かせない。

## 解決方法

`ツール -> オプション -> キーボード` にて、Visual Studio Codeを選択するだけ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1771055/f25cd4f9-87e7-f40f-366d-e5530801b558.png)


## その他

vsvimrcというのがあるので、ホームに作成するとさらに細かく設定できる。

https://github.com/justinmk/config/blob/master/.vsvimrc
c# SOAPリクエストに認証headerを追加する方法（System.ServiceModelを使用する場合）

# header認証情報：
<soapenv:Header>
<creInfo xmlns: vc ="http://test/">
<username>admin </username>
<password>admin</password>
</creInfo>
</soapenv:Header>
![截屏2022-11-08 19.28.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/368087/52e5bcf4-47ed-8457-a21e-f6b4abdea70d.png)


# C#でheaderを定義
    [System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.8.4084.0")]
    [System.SerializableAttribute()]
    [System.Diagnostics.DebuggerStepThroughAttribute()]
    [System.ComponentModel.DesignerCategoryAttribute("code")]
    [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://test/")]
    public class creInfo
    {
        public string username;
        public string password;

        public clientInfo(string username, string password)
        {
            this.username = username;
            this.password = password;
        }
    }
# サービスの参照の前に、認証headerを設定し、シリアライズする
      ServiceClient client = new ServiceClient();
      
      creInfo myHeader = new creInfo("admin", "admin");
        OperationContextScope scope = new OperationContextScope(client.InnerChannel);

        MessageHeader header = MessageHeader.CreateHeader("creInfo", "", myHeader);
        OperationContext.Current.OutgoingMessageHeaders.Add(header);

        client.execute(param);

# 参照サイト
        
https://www.cnblogs.com/jhlong/p/10763358.html

https://qiita.com/songoku/items/dcef2700b32a98123bb2
UnityのiOS版→Xcodeビルド時にccacheを使う

Unityで出力したiOS版プロジェクトからccache使う方法がわかってきたのでメモ。

# 作業環境（2022.11.08時点）

- MacOS Ventura 13.0
- Xcode 14.1
- xcode-select --install を実行してあること
- Homebrew 3.6.9
- ccache 4.7.3 
- Unity 2020.3.37f1
- iOS 16.1

### 参考URL

ccache で Unity の生成する Xcode プロジェクトのビルドを高速化する
https://zenn.dev/pobo380/articles/1a5d838ee857e1

M1 環境で Homebrew 導入コマンドを Xcode から叩けない場合の対処法
https://qiita.com/hugehoge/items/0f805c1a264488f7807c


## ccacheのインストール

`brew install ccache`

## ccache_wrapper の作成

```bash
#!/bin/bash

if [ -d "/opt/homebrew/bin" ]; then
  export PATH=$PATH:/opt/homebrew/bin
fi
if [ -d "/opt/homebrew/sbin" ]; then
  export PATH=$PATH:/opt/homebrew/sbin
fi
if [ -d "/usr/local/Cellar/ccache" ]; then
  export PATH=$PATH:/usr/local/bin
fi

if type "ccache" > /dev/null 2>&1; then
    export CCACHE_SLOPPINESS=pch_defines,time_macros
    exec `which ccache` $DT_TOOLCHAIN_DIR/usr/bin/clang -Xclang -fno-pch-timestamp "$@"
else
    exec $DT_TOOLCHAIN_DIR/usr/bin/clang "$@"
fi
```

M1/M2環境のMacではXcodeからのビルド時にHomebrewパスが見えないという問題があるため、直接PATHを記載した。
同様にIntel Mac環境でもccacheのフォルダを確認できたらパスを追加するという処理を記載。
（より柔軟な対応をするのであれば参考URL先のほうが良い対応であるけれど、今回は場当たり対応で問題ないので直接指定）

## Unityのビルド後アクションの追加

参考記事「[ccache で Unity の生成する Xcode プロジェクトのビルドを高速化する](https://zenn.dev/pobo380/articles/1a5d838ee857e1#%E3%82%A8%E3%83%87%E3%82%A3%E3%82%BF%E6%8B%A1%E5%BC%B5%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B)」の内容をもとにcsファイルを追加

## Xcodeでビルドを実行

ccache 初回実行
```
20221108_151250_1665295970954 - 20221108_151502_1665296102141
Cacheable calls: 812 /  812 (100.0%)
Hits: 0 /  812 ( 0.00%)
Direct: 0
Preprocessed: 0
Misses: 812 /  812 (100.0%)
Local storage:
 Cache size (GB): 0.25 / 5.00 ( 4.95%)
```
ビルド時間は132秒（131187ミリ秒）

2回目、プロジェクトCleanを行い再度のビルド（内容に変更なし）
```
20221108_151607_1665296167122 - 20221108_151615_1665296175946
Cacheable calls: 1624 / 1624 (100.0%)
Hits: 812 / 1624 (50.00%)
Direct: 812 /  812 (100.0%)
Preprocessed: 0 /  812 ( 0.00%)
Misses: 812 / 1624 (50.00%)
Local storage:
 Cache size (GB): 0.25 / 5.00 ( 4.95%)
```
ビルド時間は8秒（8824ミリ秒）

https://twitter.com/Ruw/status/1589873609170104326
EPUBファイルがKindle上で文字化けするのを修正する

# 背景
EPUB形式の本をダウンロードしてKindleに送信して読もうとしたところ、日本語部分が文字化けしていて読めません。Kindle Paperwhite端末でもAndroidのKindleアプリでも文字化けが発生しました。

# 対処法
### 結論
EPUBファイルの中にあるXHTMLファイルのmetaタグを以下のように修正しました。
```html
<!-- 修正前 --> <meta charset="utf-8"/>
<!-- 修正後 --> <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
```

### 手順
EPUBファイルを編集するために[Sigil](https://sigil-ebook.com/)というソフトウェアをインストールしました。SigliでEPUBファイルを開くと次のような画面になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601327/71a33ff6-1325-eb41-bbb5-d73c02edf369.png)
EPUB形式の電子書籍の本文はXHTMLで構成されていることがわかります。

metaタグを含む行を探して上記のように変更します。少しめんどくさいのですが、Textディレクトリに存在する全てのXHTMLファイルに対して修正を施せば完了です。

# 参考文献
- [kindlegenやkindle Previewer3で文字化けする](https://faster-than-the-sol.blogspot.com/2020/08/kindlegen.html)
- [kindle に HTML を送ってみたメモ](https://zisakuzien.exblog.jp/22328056/)
C++20でstd::formatを使おうとしたらコンパイラ側でまだ実装されていなかった話

## 要約

<https://cpprefjp.github.io/reference/format/format.html>

```cpp
string message = format("The answer is {}.", 42); // => "The answer is 42."
```

を読んで、  
「最近の C++ は Python みたいなフォーマットで文字列の書式を指定できるようになったんか！めっちゃ便利やん！」  
と思って C++20 で std::format を使おうとしたが、`GCC` と `libstdc++` ではまだ std::format() が実装されていなかったというお話

## 環境・バージョン

```log
~$ g++ --version
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0
```

## コンパイルしようとしたらエラーが発生

```cpp:hello.cpp
#include <format>
#include <iostream>

int main()
{
    std::cout << std::format("The answer is {}.", 42) << std::endl;
}
```

```log
$ g++ -std=c++2a hello.cpp
hello.cpp:1:10: fatal error: format: No such file or directory
    1 | #include <format>
      |          ^~~~~~~~
compilation terminated.
```

## GCC libstdc++ のドキュメントを読んでみる

<https://gcc.gnu.org/onlinedocs/libstdc++/manual/status.html#status.iso.2020>

![gcc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675511/73de3339-98d0-cc77-18d5-f78692034f2a.png)

「Text formatting」のStatus(実装されたバージョン) が空欄になっている  
つまり、まだ実装されていないという状態...  

## 回避策

### A. std::format() が実装されているコンパイラを使う

<https://en.cppreference.com/w/cpp/compiler_support>  
![compiler_support.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/675511/e7697286-ab96-395b-a7f6-24227c3a73be.png)

`Clang libc++` と `MSVC STL` は実装済なので、このどちらかを使う

### B. [{fmt}](https://github.com/fmtlib/fmt) を使う

[{fmt}](https://github.com/fmtlib/fmt) は std::format の実装  
依存関係を追加して、ライブラリを使えば良い

## おわりに

C/C++ は文字列の書式周りがやや不便だなと感じました...
Ubuntu カーネルのビルド

カーネルをビルドする。
（参考）
https://wiki.ubuntu.com/Kernel/BuildYourOwnKernel


（できれば）Docker をインストールする（参考参照）。

新しいカーネルを削除する。

```
$ sudo apt-get --purge remove linux-image-unsigned-xxxx
linux-modules, linux-modules-extra も削除。
$ sudo update-grub2
$ sudo reboot
```

ビルドしたカーネルをインストールする。

```
$ sudo dpkg -i linux-modules-xxx.deb
$ sudo dpkg -i linux-image-unsigned-xxx.deb
$ sudo dpkg -i linux-modules-extra-xxx.deb
```

再起動して、新しいカーネルになっているのを確認する。

（参考）
https://qiita.com/iganari/items/fe4889943f22fd63692a
https://weblabo.oscasierra.net/docker-centos7/
GASとLINE Messaging APIで多言語翻訳ボットを作ってみた！

# これを使ってできること
翻訳をしたい単語や語句、文章があるとき、Google翻訳やDeepL翻訳などの翻訳サービスを使用することがあるかと思いますが、これらの翻訳サービスの欠点は、一つの翻訳対象言語しか選択できません。
例えば、日本語の原文を英語だけでなく、韓国語や中国語にも翻訳したいとき、英語・韓国語・中国語を一度に選択して各言語の翻訳文が参照できません。
そこで、一度に５言語でも１０言語でも選択可能、かつ、選択した言語の翻訳文をまとめて返してくれる「 **`多言語翻訳ボット`** 」をつくりました:point_up:

**◆コードがGASの複数のスクリプトにわたり長くなるため、全ソースコード記載された多機能翻訳ボットの作成方法については電子書籍にしました。**:point_down:
Amazon Kindle本

https://www.amazon.co.jp/%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E8%B6%85%E5%88%9D%E5%BF%83%E8%80%85%E3%81%A7%E3%82%82%E3%81%A7%E3%81%8D%E3%82%8B%EF%BC%81Google-Script-Messaging-API%E3%81%A7%E5%A4%9A%E8%A8%80%E8%AA%9E%E7%BF%BB%E8%A8%B3%E3%83%9C%E3%83%83%E3%83%88%E3%82%92%E3%81%A4%E3%81%8F%E3%82%8D%E3%81%86%EF%BC%81-%E5%AE%9F%E8%B7%B5%E3%82%BD%E3%83%BC%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%89%E4%BB%98%E3%81%8D-ebook/dp/B0BLBR7YBC/ref=sr_1_1?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=2V3GK519VVIJH&keywords=line+gas+%E7%BF%BB%E8%A8%B3&qid=1677124914&sprefix=line+gas+%E7%BF%BB%E8%A8%B3%2Caps%2C287&sr=8-1



# 完成形
 
LINE公式アカウントのトーク画面下部に表示される **「表示」「追加」「削除」** のメニュー（リッチメニュー）を作成。

:large_blue_diamond: **「表示」** をタップしたとき
◆選択中の言語が **ない** 場合
　“`選択中の翻訳対象言語はありません`”と返信。
◆選択中の言語が **ある** 場合
　選択中の翻訳対象言語がリストボタンとなって表示。

:large_blue_diamond: **「追加」** をタップしたとき
◆言語選択モードになり、選択可能な言語リストが表示される。

:::note info
※言語を選択したいときは、 その都度 **「追加」** を押して表示されるリストから選択する必要があります。（←ちょっとこれは面倒な動作にもなる…(;^_^A）
:::

:large_blue_diamond: **「削除」** をタップしたとき
◆選択中の言語が **ない** 場合
　“`選択中の翻訳対象言語はありません`”と返信。
◆選択中の言語が **ある** 場合
　削除する言語の選択リストボタンが表示される。

![demo.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784430/b54bbdea-67ec-5bc5-8886-b1db402bf416.gif)

:::note info
選択している言語があれば、次回以降、そのまま翻訳したい内容を送信すると、
最後に設定した言語で翻訳文が返ってきます。
:::

もちろん、選択可能言語リストに日本語が含まれていて、それを翻訳対象言語に選択した場合、
日本語以外の言語の原文を送信すると、日本語に翻訳された文が返ってきます。
☟
![demo2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2784430/677c6c47-2357-ddbb-a053-60a333451c98.gif)

:::note warn
**多言語翻訳ボットの欠点＜改善すべき点＞**
●「追加」「削除」を選択した後は、忠実に「選択可能言語リストから翻訳対象言語を選ぶ」、また、「削除言語リストから削除したい言語を選択する」をしないとバグが起きます。😿
:::


:end:
非同期処理のメモ

```server.go
go service.LastAccessUpdater.Run(ctx)
// このdeferでsignal受けた後同期的に溜まっているものがあったらupdateするようにする
defer service.LastAccessUpdater.Flush(ctx)
```

```handler/auth.go
// bufferに追加
h.LastAcccessUpdater.Add(user.UserID)
```

```service/last_access_updater.go
package service

type LastAccessUpdater interface {
	Run(context.Context)
	Add(string)
	Flush()
}

type LastAccessUpdaterImpl struct {
	sync.Mutex

	loginManager service.LoginManager
	buffer       []string
}

func NewLastAccessUpdater(l service.LoginManager) *LastAccessUpdaterImpl {
	return &LastAccessUpdaterImpl{
		loginManager: l,
		buffer:       make([]string),
	}
}

func (b *LastAccessUpdaterImpl) Add(userID string) {
	b.Lock()
	defer b.Unlock()

	b.buffer = append(b.buffer, userID)
}

func (b *LastAccessUpdaterImpl) Run(ctx context.Context) {
	interval := 5*time.Second
	ticker := time.NewTicker(interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			b.Flush(ctx)
		case <-ctx.Done():
			b.Flush(ctx)
			return
		}
	}
}

func (b *LastAccessUpdaterImpl) resetBuffer() map[TeamChannelViewerUpdateBufferKey]int64 {
	b.Lock()
	defer b.Unlock()

	buf := b.buffer
	b.buffer = make([]string)
	return buf
}

func (b *LastAccessUpdaterImpl) Flush(ctx context.Context) {
	buf := b.resetBuffer()

	for _, userID := range buf {
		// update処理
	}

}
```

非同期で実行する処理があった際bufferに入れ、それをgo routineで定期的に処理するようにしている

デプロイ等でapiサーバーが死んだ時も処理されるよう、signalを受け取ってflushするようにしている
AWS-CLIでよく使うコマンド

AWS-CLIでよく使うコマンドを記述しておきます。

# S3バケットからファイルを一括ダウンロードする
```
$ aws s3 cp s3://コピー元バケット名  パソコンのコピー先フォルダ  --recursive
```

https://blackbird-blog.com/aws-s3-cli-download

# 複数のprofileを使い分ける
これにより複数のAWSアカウントを使い分けられます。

```
$ aws ・・・ --profile [設定したプロフィール名]
```

https://qiita.com/sakai00kou/items/b3284b93145967d25c86


今後も気がついたら追加していきます。
paiza.ioでelixir その52

# 概要
paiza.ioでelixirやってみた。
Regex使ってみた。

# サンプルコード

```

Regex.compile("foo")
|> IO.inspect

Regex.escape(".")
|> IO.inspect

Regex.match?(~r/foo/, "foo")
|> IO.inspect

Regex.named_captures(~r/c(?<foo>d)/, "abcd")
|> IO.inspect

Regex.names(~r/(?<foo>bar)/)
|> IO.inspect

Regex.opts(~r/foo/m)
|> IO.inspect

Regex.replace(~r/b/, "abc", "d")
|> IO.inspect

Regex.run(~r/c(d)/, "abcd")
|> IO.inspect

Regex.scan(~r/c(d|e)/, "abcd abce")
|> IO.inspect

Regex.source(~r/foo/)
|> IO.inspect

Regex.split(~r{-}, "a-b-c")
|> IO.inspect





```

# 実行結果

```
{:ok, ~r/foo/}
"\\."
true
%{"foo" => "d"}
["foo"]
"m"
"adc"
["cd", "d"]
[["cd", "d"], ["ce", "e"]]
"foo"
["a", "b", "c"]

```

# 成果物


https://paiza.io/projects/gmPLW-JjBt_aDcSskc14Ww?language=elixir

以上。
ActiveDirectoryのユーザーのパスワードが正しいかをサクッと確認したい

# 概要

管理者アカウントではなく、PCを使用している一般ユーザーのIDとパスワードでリモートデスクトップが必要な場面がある。
その為にユーザーから連絡をもらって、手作業でパスワードの控えをとっている。

ActiveDirectoryのサーバー上でコマンド打って『ユーザーのIDとパスワード一覧csv』のようなものが出力できれば、そんなことしなくてよいのだが…。
調べたところ、そういったことができなさそうだったのでやむなく…。

手作業ゆえの問題…。
控えているパスワードが間違っている（連絡ミス、入力ミス） or 古い情報（更新漏れ）かもしれない。

パスワードが正しいかどうかは、検証用PCでログインできるか試しにやってみれば分かる。
でも、いちいちそれやるの面倒くさい。
（確認するユーザー数が多いと結構な手間）

パスワードが正しいかどうかをコマンドでサクッと確認したい。

そんな時。

# やり方

PowerShell起動して下記コマンド。

```powershell:サンプル
$de_ = New-Object System.DirectoryServices.DirectoryEntry(
"LDAP://ドメイン名.local", 
"namae-dayo", #ユーザーID
"pass-dayo" #パス
) 
echo $de_
```

パスワードが正しければ下記のようなレスポンス。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/112f8cb8-c79f-c07e-1e32-2013f2eaef17.png)

パスワードが間違っていれば下記のようなレスポンス。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/706116/29f3db74-ef3f-4974-98e4-dd9a9fb346ec.png)

# 蛇足

~~ユーザーの存在チェックとしても使える。~~
↑『ユーザー名 **または** パスワードが正しくありません』っていうレスポンスだから、よくよく考えたらユーザー存在チェックには使えないと気づいた。

ユーザーが存在しているのが確定で、その上でパスワードが合っているか、の確認になら使える。

# 参考サイトさん

https://blog.engineer-memo.com/2013/11/30/powershell-%E3%81%A7-active-directory-%E3%82%92%E6%93%8D%E4%BD%9C%E3%81%99%E3%82%8B%E3%81%84%E3%81%8F%E3%81%A4%E3%81%8B%E3%81%AE%E6%96%B9%E6%B3%95/

# バージョン

Windows 10 Pro 21H2 OSビルド 19045.2193
JSONデータ型を試す（Oracle Database 21c)

近年Oracle DatabaseはJSONデータ型の対応が強化されてきました。Oracle Database 19cでは文字列型に対する IS JSON 構文や、JSON_OBJECT関数等が強化されました。

# JSONデータ型
Oracle Database 21cではネイティブなデータ型としてのJSON型が提供されています。以下の例では json1 テーブルの val 列が JSON 型になっています。

```SQL:
SQL> CREATE TABLE json1(id NUMBER PRIMARY KEY, val JSON);

表が作成されました。

SQL> DESC json1
 名前                                    NULL?    型
 ----------------------------------------- -------- ----------------------------
 ID                                        NOT NULL NUMBER
 VAL                                                JSON
```

JSON型の列は {DBA|ALL|USER}_JSON_COLUMNSビューで検索できます。

```SQL:
SQL> SELECT * FROM USER_JSON_COLUMNS WHERE TABLE_NAME='JSON1';

TABLE_NAME           OBJEC COLUMN_NAME          FORMAT    DATA_TYPE
-------------------- ----- -------------------- --------- -------------
JSON1                TABLE VAL                  OSON      JSON
```

FORMAT列に出力される「OSON」は、ネイティブ・バイナリ形式のJSONデータ型を示し、更新や検索を高速化するためのOracle独自の内部フォーマットであることを示しています。

# JSONデータの格納
```SQL:
SQL> INSERT INTO json1  VALUES (100,
               '{"PONumber"             : 1600,
                 "Reference"            : "ABULL-20140421",
                 "Requestor"            : "Alexis Bull",
                 "User"                 : "ABULL",
                 "CostCenter"           : "A50",
                 "Special Instructions" : null,
                 "AllowPartialShipment" : true}');

1行が作成されました。

SQL> COMMIT;

コミットが完了しました。
```

# OSONフォーマット
OSONデータ型はOracle Database 21cの独自フォーマットです。入力されたデータは再フォーマットされ、不要なスペース等は削除されます。

```SQL:
SQL> INSERT INTO json1 VALUES (200, '{"PONumber"   :   2000     }');

1行が作成されました。

SQL> COMMIT;

コミットが完了しました。

SQL> SELECT val FROM json1 WHERE id=200;

VAL
------------------
{"PONumber":2000}
```

OSONフォーマットは古いバージョンのクライアントから検索すると正しく表示できません。下記はOracle Database 21cで格納したJSONデータをOracle Database 19c Clientを使って検索した例です。

```SQL:
SQL> SHOW sqlpluscompatibility
sqlpluscompatibility 19.0.0
SQL>
SQL> SELECT * FROM json1;

        ID　VAL
----------　--------------------------------------------------------------------------------
       100　7B22504F4E756D626572223A313630302C225265666572656E6365223A224142554C4C2D32303134
30343231222C22526571756573746F72223A22416C657869732042756C6C222C2255736572223A22
```

VARCHAR2型に上記と同じデータを格納したところ、VARCHAR2型の方がデータ長は短くなりました。JSON型のデータには検索や更新のための情報が付加されているのだと思われます。

```SQL:
SQL> CREATE TABLE text1 (id NUMBER PRIMARY KEY, val VARCHAR2(2000));

表が作成されました。

SQL> INSERT INTO text1 SELECT * FROM json1;

1行が作成されました。

SQL> COMMIT;

コミットが完了しました。

SQL> SELECT length(val) FROM json1;

LENGTH(VAL)
-----------
        186

SQL> SELECT length(val) FROM text1;

LENGTH(VAL)
-----------
        162
```
Postgres クエリ結果を一列に表示する

## 1. 目的
あるクエリの結果。
| poke_name | waza |
|:-:|:-:|
| ピカチュウ  | でんこうせっか  |
| ピカチュウ  |  十万ボルト |
| コラッタ  | でんこうせっか  |
| コラッタ  | しっぽをふる  |

これを
下のように一発で取りたい

| poke_name | wazas |
|:-:|:-:|
| ピカチュウ  | でんこうせっか,十万ボルト  |
| コラッタ  |  でんこうせっか,しっぽをふる |

## 2. DB構成
ポケモンテーブル
| poke | type |
|:-:|:-:|
| pk  | serial primary key  |
| name  |  varchar(20) |

技テーブル
| waza | type |
|:-:|:-:|
| pk  | serial primary key  |
| name  |  varchar(20) |

ポケモンと技のテーブル
| poke_waza | type |
|:-:|:-:|
| poke_key  | integer  |
| waza_key  | integer  |


## 3. 結論
```sql
SELECT 
    p.name AS poke_name, 
    array_to_string(
        ARRAY(
            SELECT w.name
            FROM poke_waza pw
                JOIN waza w ON w.pk = pw.waza_key
            WHERE p.pk = pw.poke_key
        ), ','
    ) AS wazas
FROM poke p
```
結果
| poke_name | wazas |
|:-:|:-:|
| ピカチュウ  | でんこうせっか,十万ボルト  |
| コラッタ  |  でんこうせっか,しっぽをふる |

<details><summary> 何も考えずにとる </summary>

```sql
SELECT 
    p.name AS poke_name, 
    w.name AS waza_name
FROM poke_waza pw
    JOIN poke p ON p.pk = pw.poke_key
    JOIN waza w ON w.pk = pw.waza_key 
```
| poke_name | waza |
|:-:|:-:|
| ピカチュウ  | でんこうせっか  |
| ピカチュウ  |  十万ボルト |
| コラッタ  | でんこうせっか  |
| コラッタ  | しっぽをふる  |

</details>

# 4. ざっくりと解説
メモ程度です。
``array()``
``array_to_string()``


### 4-1. ARRAY()
内側から。
クエリの結果が配列として返るらしい。

https://www.postgresql.jp/document/9.2/html/sql-expressions.html#SQL-SYNTAX-ARRAY-CONSTRUCTORS


https://www.postgresql.jp/document/9.2/html/arrays.html

```sql
-- イメージ
SELECT 
    p.name AS poke_name, -- 例えば「ピカチュウ」
    array_to_string(
        ['でんこうせっか','十万ボルト'], 
        ','
    ) AS wazas
FROM poke p    
```

### 4-2. array_to_string()
| 引数 | 説明 |
|:-:|:-:|
|  第一引数  |   配列  |
|  第二引数  |  分割する文字  |
|  第三引数  |  Nullのときに代わりとなる文字  | 

https://www.postgresql.jp/document/9.2/html/functions-array.html#ARRAY-FUNCTIONS-TABLE

```sql
-- イメージ
SELECT 
    p.name AS poke_name, -- 例えば「ピカチュウ」
    'でんこうせっか,十万ボルト' AS wazas
FROM poke p
```

## 5. 経緯
ピカチュウ行が重複するのが嫌で、
ピカチュウの技リストを取得するクエリを使っていた。
そうすると、もちろんコラッタに対しても同じクエリを使う。


ポケモンのリスト（30匹にLIMITしていた）をとってくるクエリを1回、
それぞれの技リストを取得するので30回
クエリを発行していた。

10秒くらいかかってクエリの発行回数が多いことに気が付いた。

## 6. 参考

https://kaerouka.hatenablog.com/entry/2013/12/13/043627

## 感想
1.3秒くらいになってとりあえず良しとする。
DBはまだまだ勉強することが多いなあ。

ピカチュウは例えですえ
Ruby モジュールとは

PHPerがRuby on Railsを書くことになったので、備忘録として
PHPをやってきて、モジュールという概念を知らなかったので

## モジュールの書き方

```module.rb
module モジュール名
　　処理
end
```
モジュール名は必ず英数字の大文字で始める

## モジュールとクラスの違い
・モジュールはインスタンスを作れない
・モジュールは継承できない

## モジュールを使う目的
・名前空間の提供
・インスタンスメソッドとして取り込む(Mix-in)
・モジュールをオブジェクトに取り込む(extend)
・モジュール関数

## モジュールを使った名前空間の提供
Ruby on Railsのコードを見ていて、この使い方が一番多いのかなという印象
PHPでいうところの名前空間(namespace)と同じ使われ方

呼び出しは ::演算子を使い、モジュール名::モジュール名　またはモジュール名::クラス名　のように使う

## インスタンスメソッドとして取り込む(Mix-in)
PHPでいうところのtrait?
Rubyは多重継承を許さず、Mix-inという仕組みを用意している
Mix-inを使ってincludeされたモジュールのメソッドは、クラスのインスタンスメソッドになる。

```Human.rb
module PerfectHuman
  def walk
    puts "歩く"
  end
end

module SwimmingHuman
  def swim
    puts "泳ぐ"
  end
end

class Human
  include PerfectHuman, SwimmingHuman
end

obj = Human.new

obj.walk
#=> 歩く
obj.swim
#=> 泳ぐ
```

## モジュールをオブジェクトに取り込む(extend)
モジュールに定義されたメソッドは、オブジェクトのインスタンスに、特異なメソッドとして取り込むこともできる

```Move.rb
module Move
  def walk
    puts "歩く"
  end
end

obj = Object.new
obj.extend Move
obj.puts
```

クラス定義内でもextendは使用でき、取り込まれたモジュールのメソッドはクラスメソッドになる
```Move.rb
module Move
  def walk
    puts "歩く"
  end
end

class Human
  extend Move
end
Human.walk
```

## モジュール関数
Rubyの組み込みモジュールとして定義されているもの。
module_function :メソッド名　と記述される
Ruby nilってnullと違うの？

元々PHPをやっていて、Rubyのnilというものが気になったのでメモ

## nilとは
Rubyでは「null」ではなく「nil」が利用される

Rubyは全てがオブジェクトなので、nilは、NilClassに属している。
nilはNilClassの中の唯一のインスタンス。

nil判定を行う際は、NilClassの中の定義されたメソッドを使用する必要がある。
→　こちらの件についての追記
nil? メソッドは確かに NilClassクラスに定義されていますが，Objectクラスにも定義されていて，どんなオブジェクトに対しても使えます。
でないと nil 以外のオブジェクトに対して NoMethodError が出て nil 判定できませんからね。
Object クラスの nil? メソッドは常に false を返しますが，NilClass クラスの nil? メソッドはそれを「常に true を返す」メソッドとして上書きしています。

@scivolaさん、ご指摘ありがとうございました！

## nilの判定

### nil?
nil?では、対象オブジェクトがnilかどうかを確認する。nilの場合true、そうでない場合はfalseが返ってくる。

### blank?
blank?はnilに加えて、空白文字列、空の文字列などもtrue、そうでない場合はfalseが返ってくる。Railsのメソッドのため、「require 'active_support'」が必要

### present?
present?はblank?の逆で、nil、空白文字列、空の文字列などの場合はfalse、そうでない場合はtrueが返る。

### empty?
nil判定には使えないメソッド。
empty?では空白値を調べることは可能ですが、nilは判定できない

## nilガードを使おう！
nilガード、個人的にはPHPなどのnullセーフ同じようなものかなと勝手に考察しましたが、少し勝手が違うみたいですね。(PHPだとnullに対してメソッド呼び出しを行わないようにするための物だったので)

変数 ||= 指定値
||=　と記載することで、変数が「nil」の時に指定値を代入することが可能です。