OmniAICreator/Qiita-1.07M huggingface dataset:
GCC10以下でAVX2のunalign load(store)がvmovdqu+vinserti128に分解されパフォーマンスが落ちる現象

# 問題点

Intrinsicを使い、AVX2対応のプログラムを書いていたところ`_mm256_loadu_xxx`がやけに遅いことがあったので原因調査をすることにした。
何はともあれ、下のコードと逆アセンブル結果を見てほしい。

* GCC 10以下（コンパイルオプション`-mavx2 -O2 -std=c++11`）

```cpp:main.cpp
#include <immintrin.h>
#include <memory>
#include <iostream>
#include <random>

int main(){
    std::unique_ptr<int32_t[]> vec(new int32_t[8]);
    vec[0] = std::random_device{}(); // 最適化防止
    _mm256_storeu_si256(
        reinterpret_cast<__m256i*>(vec.get()),
        _mm256_add_epi32(
            _mm256_loadu_si256(reinterpret_cast<__m256i*>(vec.get())),
            _mm256_set1_epi32(1)
        )
    );
    std::cout << vec[0] << std::endl; // 最適化防止
}
```

逆アセンブリして問題の部分のみを抜粋

```
call    std::random_device::_M_fini()
vmovdqu xmm1, XMMWORD PTR [r12]
mov     edi, OFFSET FLAT:_ZSt4cout
vinserti128     ymm0, ymm1, XMMWORD PTR [r12+16], 0x1
vpaddd  ymm0, ymm0, YMMWORD PTR .LC0[rip]
vmovups XMMWORD PTR [r12], xmm0
mov     esi, DWORD PTR [r12]
vextracti128    XMMWORD PTR [r12+16], ymm0, 0x1
```

なぜかvmovdquで下位128bitをロード（ストア）してから、vinserti128で上位128bitをロード（ストア）しなおしている。
16byteでアライメントされている場合は速いらしいが、アライメント調整できる場合は`_mm256_load_xxx`使うし、確保もC++17からnewにアライメント指定ができるのでそういう調整をしてほしいわけではない。(要ベンチマーク)
手元の環境（Ryzen 3900X）ではこれが原因でコンパイルしたプログラムのパフォーマンスが落ちてしまっている。

#解決策

## GCC11以上かClangを使う
GCC 11やClangではこのようなことが起こらない

* GCC 11.1（コンパイルオプション`-mavx2 -O2 -std=c++11`）

```
call    std::random_device::_M_fini()
vmovdqa ymm0, YMMWORD PTR .LC0[rip]
vpaddd  ymm0, ymm0, YMMWORD PTR [r12]
mov     edi, OFFSET FLAT:_ZSt4cout
vmovd   esi, xmm0
vmovdqu YMMWORD PTR [r12], ymm0
```

* Clang（コンパイルオプション`-mavx2 -O2 -std=c++11`）

```
call    std::random_device::_M_fini()
vmovdqu ymm0, ymmword ptr [r14]
vpcmpeqdymm1, ymm1, ymm1
vpsubd  ymm0, ymm0, ymm1
vmovdqu ymmword ptr [r14], ymm0
```

## mtuneオプションを指定する

コンパイルオプションに`-mtune="avx2に対応しているアーキテクチャ"`を指定してあげると上記のようなことが起こらず、パフォーマンスが落ちることが無い。

* GCC 10以下（コンパイルオプション`-mavx2 -O2 -std=c++11 -mtune=core-avx2`）

```
call    std::random_device::_M_fini()
vmovdqa ymm0, YMMWORD PTR .LC0[rip]
vpaddd  ymm0, ymm0, YMMWORD PTR [r12]
mov     edi, OFFSET FLAT:_ZSt4cout
vmovd   esi, xmm0
vmovdqu YMMWORD PTR [r12], ymm0
```
エンジニアではない自分がSQLをかけるようになるまで

## はじめに
[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)の6日目の担当は、[Qiita株式会社](https://qiita.com/organizations/qiita-inc)プロダクトマーケティングGの中泉（[@zumi0](https://qiita.com/zumi0)）です！よろしくお願いします！

この記事では、エンジニアではない自分がSQLをかこうと思ったきっかけから、かけるようになるまでにやったことをまとめていきたいと思います！そのため、この記事では非エンジニアの方に向けて書いている部分もあります。その辺りをご理解いただき読んでいただけると嬉しいです。

この記事が、エンジニアではない方がSQLを学ぶきっかけになったら嬉しいです。


## SQLとは
そもそもSQLとは何ぞやということですが、WikipediaでSQLを調べると以下のようにまとめられていました。

```
SQL（エスキューエル[1][ˈɛs kjuː ˈɛl] ( 音声ファイル)、シークェル[1][ˈsiːkwəl] ( 音声ファイル)、シーケル[2]）は、関係データベース管理システム (RDBMS) において、データの操作や定義を行うためのデータベース言語（問い合わせ言語）、ドメイン固有言語である。
```
[引用元](https://ja.wikipedia.org/wiki/SQL)

簡単にいうと、SQLとはデータベースを操作するための言語です。
このような言い方をすると色々な方面からお叱りを受けるかもしれませんが、今回は非エンジニアの方向けに書いているので、その辺りはご容赦ください。

## SQLをかこうと思ったきっかけ
自分がSQLをかこうと思ったきっかけは、社内のBIツールを使ったことでした。弊社ではBIツールとして[Redash](https://redash.io/)を使っていて、Redashでは基本的にSQLを記述することでデータ抽出を行います。SQLをかけない人がデータ抽出をする際は、SQLがかけるエンジニアに依頼する必要がありました。

誰かに依頼すると、結果が返ってくるのに時間がかかることや、依頼された人の時間を奪ってしまうことになります。そこで自分がSQLをかけるようになれば、そういった問題がなくなると思い、SQLをかこうと思いました。

## SQLをかくためにやったこと
### [TechAcademyのWebアプリケーションコース](https://techacademy.jp/course/rails-2)
社内の研修で、[TechAcademyのWebアプリケーションコース](https://techacademy.jp/course/rails-2)を受講する機会がありました。このコースはWebアプリケーションコースでSQLがメインではないですが、SQLを解説している箇所があります。

そこでは、主に以下の内容を学びました。

- テーブルからデータの抽出（SELECT,FROM）
- データの絞り込み（WHERE,IN,LIKEなど）
- テーブル同士の結合（JOINなど）
- etc


簡単な内容ではありますが、SQLの基本や実際に実行することができたので、自分の中で「SQLはこういうものなんだ」と知ることができました。

### クエリをひたすら読む
SQLがどういったものか知ったり実際に触ってみた後は、ひたすら社内にあるクエリを読みました。
ここでいうクエリとは、SQLでかかれたデータベースに対する命令文のことを指しています。

自分は全体を勉強してからやってみるということが苦手だったので、すでにあるクエリを読んで勉強する手法を取りました。クエリによく出てくるかき方や構文を調べたり質問することを繰り返し、どんなことがかいてあるか理解していきました。

### 読んだ内容を使ってクエリをかく
クエリをひたすら読んだ後は、その内容を使ってクエリをかいてひたすら実行していました。

最初のうちはすでにあるクエリの必要な部分をコピペして一部を直し実行するだけを繰り返しました。慣れてくると、色々なクエリ同士を組み合わせて実行することもできるようになりました。この過程でたくさんのエラーに出会ったわけですが、しっかりとエラー文を読み理解できるよう努めました。自分で調べてもわからない場合はエンジニアに質問して理解していました。

## さいごに
今回の記事では、エンジニアではない自分がSQLをかくきっかけやかけるようになるまでにやったことをまとめました。自分が特にSQLをかけるようになるまでにやってよかったと思っていることは、すでにあるクエリを読み、正しいかき方やよく使われるかき方を身につけることです。最初から自分で一からクエリをかくということは大変なので、すでにあるものを使い理解するといいと思います。


---

[Qiita Advent Calendar 2021](https://qiita.com/advent-calendar/2021/qiita)の7日目は、[Qiita株式会社](https://qiita.com/organizations/qiita-inc)プロダクト開発Gの[@wataru86](https://qiita.com/wataru86)が担当します！
どんな記事か楽しみです！
D言語くんと秘密のレポート3 （脆弱性対応作業の流れと記録）

# はじめに

今回も今回で、 @simd_nyan 氏が公開されているTwitter在住のD言語くんbotがRTしたツイート各種を見るためのビューアーを更新していきます。

ビューアーは、TypeScript+Reactをベースに、Material-UIを使いつつparcelでバンドルしている構成です。簡単さと安全さで個人的鉄板構成です。

しかし今回は時間不足のため機能追加ができず、今年の分のデータ(URL)が増えただけです。
昨年自動再生機能をつけたので、これでほぼ完成してしまった感があります。（再生速度は切り替えたいかも）

こちらのリンクからご確認ください。

- D言語くんツイートビューアー
    - https://lempiji.github.io/dman-tweet-viewer/

__参考画面__

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11612/18360174-de96-542e-7016-865c92879f90.png)

# 脆弱性対応の作業日記

更新しました！ではちょっと物足りないので、作業日記です。

結構ミニマム構成とはいえ、作成から数年経過しているのでGitHubからセキュリティアラートが飛んできました。
これを3件ほどぽちぽちすると `package.json` が更新されるので、適宜ビルドとデプロイを流してやれば良くなります。

これに加え、通常は `npm outdated` で古いバージョンが残っていないか確認したり、 `npm audit` で脆弱性などの報告がないか追加の確認を行います。

試しに行ってみると色々出るわ出るわということで、この原因となるパッケージを特定して更新していく作業の流れを記録していきます。

## まずは `npm outdated`

何はともあれ鉄板コマンドです。

`npm outdated` コマンドを実行すると、使っているバージョンや最新バージョンなどが表示されます。
脆弱性の有無などで文字の色が変わるようで、特に赤い文字がやばいことから確実に更新対象とする必要があります。

また、これには `Wanted` という列があり、今使っているバージョンなら最低限これにしろ、といった感じのバージョンが表示されます。これが1つ更新の目安になります。

内容を確認したら、 `package.json` に記載されたバージョンをこれに更新していきます。
Wantedの列についてはほとんどがパッチバージョン、稀にマイナーバージョンの更新程度なので、この時点では破壊的変更はありません。

書き換えたら `npm install` でインストールし、再度 `npm outdated` を実行して問題のあるパッケージが粗方消えることを確認します。

## `npm audit`

こちらは脆弱性の有無を確認するコマンドです。

これを実行して何も出なければ終了だったのですが、いかんせん出るわ出るわという感じでした。~~どうせ入力ゼロのアプリならまず安全だろうとか思いつつ~~しっかり対処していきます。

例として1つ抜粋すると、以下のような出力があります。
この時点で、 __Severity: high__ （重大度: 高）とあるので結構まずいですね。

```console
glob-parent  <5.1.2
Severity: high
Regular expression denial of service - https://github.com/advisories/GHSA-ww39-953v-wcq6
fix available via `npm audit fix --force`
Will install parcel@2.0.1, which is a breaking change
node_modules/glob-parent
  chokidar  1.0.0-rc1 - 2.1.8
  Depends on vulnerable versions of glob-parent
  node_modules/chokidar
    @parcel/watcher  <=1.12.1
    Depends on vulnerable versions of chokidar
    node_modules/@parcel/watcher
  fast-glob  <=2.2.7
  Depends on vulnerable versions of glob-parent
  node_modules/fast-glob
    parcel  1.8.0 - 1.12.4
    Depends on vulnerable versions of @parcel/logger
    Depends on vulnerable versions of fast-glob
    Depends on vulnerable versions of node-forge
    node_modules/parcel
```

`npm audit fix --force` を実行すれば良さそうですが、このコマンドだと地味に影響範囲が読めないので、その直後にある `Will instal parcel@2.0.1, ...` を参考にそれだけアップデートしてみます。
`package.json` のバージョンを書き換えて `npm install` です。

終わったら `npm audit` を実行してチェックしてみると、一発でエラーがすべて消えました。元を辿ると `parcel` が古かったのだとわかります。

というわけでこれで無事に脆弱性の対応は目途が付きました。

## Parcelの破壊的変更への対応

今回は1点、モジュールバンドルに使っている `parcel` のバージョンが 1.12.4 から 2.0.1 になったことで破壊的変更がありました。
メジャーバージョンが上がっているので、これで無事ビルドも通らずエラー祭です。

これについては以下のドキュメントにある `script` タグに対する `type="module"` の追加などを行っています。

https://parceljs.org/getting-started/migration/

また、`package.json` の `main` にReact+TypeScript向けの `.tsx` を設定したのがダメになり、無難に `index.html` を設定するよう書き換えています。
これで無事にビルドも通るようになりました。

# 終わりに

前日の夜になってから書き始め、無事に深夜のうちに作業を終えることができました。当日朝の公開は担保出来て一安心です。

とはいえ久しくこういう作業やっていなかったので、勝手をすっかり忘れていて時間がかかりました。
作業途中で寝てしまったりしたのですが（正直）、parcelの破壊的変更対応もあってトータル3時間くらいと結構かかった気がします。

というわけでD言語くんのRTしたツイートを眺めるアプリの更新作業記録でした！
脆弱性対応の流れということで1つ参考にしてみてください！
ProxmoxでClusterからノードを削除する方法

#ProxmoxVE 7でクラスターを削除する。
自分が作業しているうえで詰まったのでメモ書き。
クラスターを構成しているサーバーの一台がブートディスクが破損して起動しなくなってしまい、オフラインのまま操作ができなくなってしまった。

Proxmoxの生き残ってるノードのコンソールから操作する。
もしくはSSHでコンソールが開ければよい

###ノードの一覧の確認
```
#クラスターに属するノードを参照する
$pvecm nodes

Membership information
--------------------------
    Nodeid      Votes Name
         1          1 hp1 (local)
         2          1 hp2
```
今回はnode 2を削除する前提で書いていく。

###マスターノードの切り替え
必要ないかもだけれども。
一応マスターノードを1に切り替えておく

```
#マスターノードを切り替える
$pvecm e 1
```

###ノードの削除
ノードを削除する

```
#ノードを削除する。(番号は必要に応じて変更)
$pvecm delnode 2
Killing node 2
```

###webUIからの削除をする。
この状態だとWebUIに表示されたままなので一部のディレクトリを削除する。

```
#ディレクトリから一部のファイルを削除する
rm -r /etc/pve/nodes/〇〇〇(ノードの名前)
```

これで削除されるはず。rmコマンドってあんまりよくないのかな。mvでtmpに移動させた方がいいのか。
障害対策は開発チームと二人三脚で行こう！

##はじめに
QA業務をやっていて、本番障害を減らしたいという思いはみんな持っていますよね。

本番障害を減らすために障害対策をしたのに、
QAコストはあがって障害はそこまで減らない。。。
みたいな事はないでしょうか。

今回は障害対策に取り組むにあたって、わたしが気を付けている事を共有させて頂きます。

##障害対策の流れ
まず障害対策を実施する流れについて、大雑把に記載するとこんな形になるかなと思います。


**①原因調査**
・発生原因の調査
・QA未検知の原因調査
　（必ずしも未検知であるかは状況によります）

**②対策検討**
・原因に応じた対策の検討

**③実行**
・対策の実行

**④測定**
・対策が実行されているかの確認
・効果が出ているかの測定

**⑤改善**
・測定結果からよりよい対策があるか検討
・効果が出ている事を確認できれば対策の継続実施


上記の流れで対策を進めていく際に、
私が特に気を付けているポイントを紹介できればと思います。

##対策検討時に開発チームを巻き込もう！
**対策検討時にQAだけではなく開発チームを巻き込む！**
これとっても大切だと思っています！
それがなぜかというと下記の理由からです。


QAでのみ障害対策を実施するとテストケースが増加し続け、QAコストの増加につながる
↓
コスト増加を抑えるにはそもそもの不具合混入を減らす開発上流工程での対策が必要
↓
開発上流工程での対策には、実際に開発を行っている開発チームを巻き込む必要がある


また上流工程での対策案については以下のようなことが考えられます。
①データ作成時にバリデーションチェックを入れる
②データマージ時にバリデーションチェックを入れる
③仕様書フォーマットの統一

効率よく障害対策を実施するためにも
開発チームを巻き込む必要がある事がお分かりいただけたかなと思います。

##どうやって巻き込むの？
ですが、開発チームを巻き込もうといっても、
どうすれば良いのか、何からすれば良いのか。と、
頭を悩ませる方も多いのかなと思います。
（私もその一人です！）

そこで、わたしが開発チームを巻き込む際に気を付けている事を共有します。

**①目線を変える**
QAだけでなく開発チームと協力して対策を進めたいので、
開発チームの目線に立ってみるようにしています。

QAは障害を減らしたい。という事の優先度が高いかもしれないですが、
開発チームは障害を減らす。よりも売り上げを増やしたい。とか、
ユーザー満足度を上げたい。という事の方が優先度が高いかもしれません。

相手の目線に立って、
なにを大切にしているのか。なにが優先度が高いのか。辺りを意識できると
巻き込む方法やアプローチ方法の検討が捗るかもしれません。

**②定量的なデータを集める**
開発チームを巻き込む際に手ぶらでは説得できないので材料を集める必要があります。
今の現状が○○なので、□□をすることで、現状の○○を△△にします。
これを実現するために協力してください！
みたいに話を持っていけるよう、なるべく定量的なデータを集めるようにしています。

障害数、障害の優先度別の数、お問い合わせの受信数など、
ユーザー影響を数値として伝えられると良いかと思います。

そしてQA目線だけのデータ収集だけでなく、
開発チームの目線も意識してデータを集められると良いかなと思います。

**③キーマンを見つける**
説得材料が集まってきて次は実際に巻き込むために動き出すかなと思うのですが、
どなたに話を持っていくと良さそうかを見極めるのが重要かと思っています！

品質に対して意識の高い方。コストに対して意識の高い方等、
定量データを元にアプローチ方法を考えてキーマンを見つけましょう。

まずはQA内、そして開発チームで味方になってくれそうな人を見つけて、
仲間を増やしておくのも有効だと思っています！

**④最後は情熱**
そして最後は情熱ですね！！
やりぬくぞという強い意志をもって動き出すようにしています！
（パッション大切！！）

##最後に
障害が出ると、確認対応でQAコストは勿論
修正対応で開発チームのコストも膨れ上がってしまうので、
未然防止や再発防止で障害を減らすことができると
QAだけでなく開発チームもハッピーになれます。

なので障害の再発防止対策については、
QAだけに閉じずに開発チームを巻き込んで、二人三脚で実施する形にしましょう！

ありがとうございました！
npmでdependenciesのみをインストールする際の注意点

## 結論

node_modulesの中身を確実にdependenciesのみにしたい場合

- npm v6 の場合 → `npm prune --production`
- npm v7 ~ の場合 → `npm i --production`

→ npm v6の場合、`npm i --production` では、インストール済みのdevDependenciesのパッケージが削除される訳ではないことに注意

## 経緯

AWS Lambdaのレイヤーとしてアップロードしたいパッケージ群があり、以下のような流れでインストールしたい状況がありました。

1. devDependenciesのパッケージも含めて全てインストールし、関数をビルドする。
2. node_modules内を、実行時に必要なdependenciesのパッケージのみにしてzip化する。

この時、2の段階で `npm i --production` を行なった場合、npmがv6かv7以降かによって結果が異なるようです。

### npm v6の場合

v6で `npm i --production` を行うと、新たにインストールされるパッケージはdependenciesに記載のもののみになりますが、既にインストールされているdevDependenciesのパッケージが削除される訳ではないようです。

既にインストールされたdevDependenciesのパッケージを削除したい場合は、 `npm prune --production` というコマンドが利用できます。

https://docs.npmjs.com/cli/v6/commands/npm-prune

コマンドの説明では、devDependenciesのパッケージを削除するとありますが、dependenciesのパッケージがインストールされていない場合はそのインストールも同時に行ってくれるようです。

したがって、node_modulesの中身を確実にdependenciesのパッケージのみにしたい場合は、 `npm prune --production` を実行するだけで十分なようです。

### npm v7以降の場合

v7, v8では、`npm i --production` を行うと、dependenciesのパッケージのみインストールされ、既にインストールされたdevDependenciesのパッケージの削除まで行ってくれるようです。

これは実質的に `npm prune --production` と同じ挙動になっているようです。

## 所感

dependenciesのみをインストールしたいがインストール済みのdevDependenciesは残しておきたいというケースは考えにくいため、やはりv7以降の挙動が便利だと思いました。

## 参考

https://stackoverflow.com/questions/9268259/how-do-you-prevent-install-of-devdependencies-npm-modules-for-node-js-package
Angular12と13でbuild cache設定は違うよ

これは [Angular Advent Calendar 2021](https://qiita.com/advent-calendar/2021/angular) の4日目の記事です。

2日目の[2021年のAngular振り返り](https://kasaharu.hatenablog.com/entry/20211202/1638403248)を読んで、Angular12にアップデートしたけど、ビルドキャッシュ忘れたじゃんと思い設定を調べてました。

公式ドキュメントを見ると、angular.jsonに `"cache"`の設定を追加してねとあった。
でも、jsonファイルに追加したらエラーが出て追加できず...。

https://angular.jp/cli/cache

おかしいな〜っと思いググってみたら、angular12では`NG_PERSISTENT_BUILD_CACHE`を使うとのこと。

https://twitter.com/angular/status/1409587406144081920?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1409587406144081920%7Ctwgr%5E%7Ctwcon%5Es1_&ref_url=https%3A%2F%2Fzenn.dev%2F

https://netbasal.com/make-your-build-faster-in-angular-v12-ca041b37946e

ちなみにangular13だと`NG_PERSISTENT_BUILD_CACHE`は非推奨になるらしいので、angular.json内で設定する必要があるそうです😲

https://newreleases.io/project/github/angular/angular-cli/release/13.0.0-next.9


以上、小ネタでしたが参考になれば幸いです。
[iOS] Crashlyticsとクラッシュ レポートツールを併用する話

この記事は、ゆめみ [Advent Calendar 2021](https://qiita.com/advent-calendar/2021/yumemi) の３日目の記事です。
ちょっと間に合わなかった

# はじめに

Firebase Crashlyticsはよく使われるクラッシュ検知ツールです
別のクラッシュ検知ツールからCrashlyticsへ載せ替えが必要になったのですが
一定期間は元のツールとCrashlyticsを併用して欲しい要件へ対応した際のメモです

## 環境

* OS：macOS Big Sur 11.6.1
* Swift：5.5
* Xcode：13.0 (13A233)

## 現象

クラッシュレポートがCrashlyticsか他ツールのどちらかにしかレポートされない

## 原因

クラッシュ検知ツールは概ねtop-level error handlerを利用して、クラッシュ検知などを行なっていると考えられます
ただtop-levelとあるため、一つしか登録できず複数のクラッシュ検知を有効にした場合に、競合してしまう場合があります

## 対応

### 1. 致命的な例外(NSException)の場合

```swift

func exceptionHandler(exception: NSException) {
    UserDefaults.standard.setValue(ExceptionModel(exception), forKey: "record")
}

NSSetUncaughtExceptionHandler(exceptionHandler)

```

### 2. Swiftランタイムエラーの場合

```swift

let signalHandler : @convention(c) (Int32) -> Void = { (signal) in
    UserDefaults.standard.setValue(ExceptionModel(signal), forKey: "record")
    exit(signal)
}

for code in [SIGABRT, SIGBUS, SIGFPE, SIGILL, SIGSEGV, SIGTRAP] {
    signal(code, signalHandler)
}
```

### 3. 起動時

```swift
if let record = UserDefaults.standard.object(forKey: "record") as? ExceptionModel {
    UserDefaults.standard.removeObject(forKey: "record")
    // TODO: Crashlytics & crash report tool recording
    print(record)
}
```

## 解説

NSSetUncaughtExceptionHandlerを使うとキャッチされなかった致命的な例外をハンドリングすることができます
しかし、これだけだとSwiftのランタイムエラーがハンドリングできないので、シグナルハンドラを利用して補足します
シグナルハンドラ内では、データの保存のみ行います
起動時に、エラーレコードがあればCrashlyticsやクラッシュ検知ツールへレコードを送信し、レコードは削除します

## 問題点

Crashlyticsやクラッシュ検知ツールが提供しているリッチなログ(スタックトレース等)は自力で取得しないと、レポートされません
いい感じにログ収集してくれる`ExceptionModel`の作成が必要です

## 備考

実際にはPLCrashReporterなどを使うか、この様な要件は回避しましょう

# 参考

- [NSSetUncaughtExceptionHandler(_:)](https://developer.apple.com/documentation/foundation/1409609-nssetuncaughtexceptionhandler)
- [How should I use NSSetUncaughtExceptionHandler in Swift](https://stackoverflow.com/questions/25441302/how-should-i-use-nssetuncaughtexceptionhandler-in-swift/31770435#31770435)
- [Diagnosing Issues Using Crash Reports and Device Logs](https://developer.apple.com/documentation/xcode/diagnosing-issues-using-crash-reports-and-device-logs#//Apple_ref/doc/uid/DTS40008184-CH1-ANALYZING_CRASH_REPORTS-EXCEPTION_CODES)
- [PLCrashReporter](https://github.com/microsoft/plcrashreporter)
【Unity】InputSystem：MouseのSensitivityはどこ・・・？

# 課題
InputSystemに乗り換えたはいいが、
旧InputManagerの設定項目「Sensitivity（感度）」が見つからない！

## こまった場面の具体例
「Cinemachine」の「VirtualCamera」に「CinemachineInputProvider」をアタッチして「InputSystem」に対応したぜ！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1054787/7e7c4f17-e7d0-abb0-7e7c-a2fbb4d41edd.png)

[※こちらを参考にさせていただきました](https://nekojara.city/unity-cinemachine-input-system)

カンタンにゲームパッドとマウスに対応できたと思いきや…
ゲームパッドのスティックで取得できる値は最大「1」なのにマウスは「10」とか「100」とか取得できるのでカメラが超高速回転！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1054787/0fda5f54-f561-7da1-f138-64560dd66220.png)

ゲームパッドの場合は0～1の範囲で、
マウスの操作の場合は移動量を取得してくるので、
桁が異なるようですね。

感度を0.1あたりに設定したいと考えました。

## 解決方法
[Processors](https://docs.unity3d.com/Packages/com.unity.inputsystem@1.0/manual/Processors.html)を用いて補正することにしました。

実際に設定してみます。
まずInput Actionsの設定画面でマウスを選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1054787/bc00476c-c0b7-31f9-988d-fa7dc17b7afe.png)

Processorsを右のプロパティ欄で設定しましょう。
今回は「Scale Vecor2」を追加します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1054787/09ad1f0d-b8d3-df3b-f872-90832d016ac9.png)

お好みで設定して「Save Asset」ボタンを押しましょう。
これが感度に相当する値となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1054787/ec608655-57a9-5506-fda0-736360ffb873.png)

# 解決！
感度を0.1に設定したときと同じような感覚で操作できるようになりました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1054787/7018a17e-55ee-d815-b929-41a018e8192b.png)
# 補足

下記の環境で撮影しました。
`Unity:2020.3.20f1`
`InputSystem:1.0.2`
`Cinemachine:2.6.10`
議事録をお願いするときに気を付けていること

# はじめに

議事録の書き方については[素晴らしい記事](https://qiita.com/y_saeko/items/44f3f7054a033960de23) が既にあるので、

 - 他人（主に新人さん）が書いた議事録をチェックするとき
 - 議事録取りをお願いするとき

に気を付けていたことを書きます。

# 事前準備
- 「会議の目的」「議事録を取る目的」を伝える
   - 会議の性質によって求められる議事録の質は変わる
        - （例）社内定例の備忘のためだから、決定事項だけ書いていればいいよ
        - （例）プロジェクト進捗を記録し、お客様への納品物証憑とするから、しっかり書いてね

- 記録方法を伝える  
    - 文体：「だ、である調」or「ですます調」

- 議事録フォーマットを渡す
    - （もしあれば）過去の議事録を参考に渡す
- （出席者が事前にわかっている場合）出席者を教える
 - 難読名の方は一発変換できずに手こずる場合があるので、事前に変換辞書登録しておくと◎。

# レッツ会議
- 画面共有と議事録取りは別の人に頼む
    - スライド切り替えながらメモを取るのは慣れるまでは大変
- 議事進行者には会議の最初に「議題」、最後に「決定事項」「TODO」を読み上げ・共有するよう頼む
    - 議事録取る側にとってめっちゃありがたい   

# 議事録出してもらう
新人さん・プロジェクト参加ほやほやの方には、下記2点をお願いしています。

- 作業時間は「会議と同じ時間」でよい。時間をかけすぎない
    - （例：会議が1時間なら議事録作成時間は1時間）
    - 議事録取りに限らず、新人さんにお願いする事柄は「目安時間」を指示する 

- 発言の取捨選択（判断）はしなくてよい   
    - 不明部分は「聞いた通りに書く」「印をつける」（赤字、コメントなど）
        - 質問には添削時に答える

    - 議事録にするか悩む内容（雑談、オフレコの話題など）も、とりあえず全部書いてもらう
        - 頑張って書いた内容を「書いちゃダメ」って言われて凹んだ経験があるので…
        - 難しい判断は先輩がやればよい。少しずつ慣れていけばOK！

# レッツ添削
- 当たり前ですが、書いてもらった議事録をそのまま提出してはいけません。確認＆必要に応じて添削しましょう。

# 確認内容
- 会議日時（曜日）、出席者のチェック
    - 日付と出席者名は意外と間違えやすいポイントなので見ておくこと 
- 話し言葉をそのまま書いていないかチェック
    - 業界によって許容範囲は異なるが、
    - 話し言葉をそのまま書いていないかチェック（ビジネスらしい書き言葉に変換する）

## 会議で頻出する話し言葉→書き言葉の変換例
日本語会議では「副詞」に話し言葉が出やすいです。文頭は要チェックですね。

|話し言葉  |書き言葉  |
|---|---|
|終わらせる |完了させる/ 完遂する |
|じゃなくて |ではなく  |
|ちゃんと|きちんと  |
|これからも |今後とも  |
|後で |後ほど  |
|さっき |先ほど  |
|すぐに |早急に  |
|ないです  |ございません  |
|だけでなく  |のみならず  |
|やる |実行する  |
|いろいろな |様々な  |
|ちょっと |少々  |
|いっぱい |多くの  |
|たくさん |多くの  |
|とても |非常に  |
|多分 |おそらく  |
|了解です|承知いたしました  |
|させていただきます|いたします  |
Pythonをsudoで実行するとシステムのpythonが呼び出されるときの対処法


## 問題

`python app.py`を`sudo python app.py`で実行すると、例えvenv環境にいてもシステムのpythonが呼び出される。

この不手際によって、f-stringsでのシンタックスエラーが出たり、インポートエラーが起きたりすることがある。

インポートエラーは別のpythonが呼び出されていると気づくことが多いが、f-stringsのシンタックスエラーはわかりにくい。f-stringsはpython3からの対応でpython2は対応しておらず、システムのpythonが２系のためエラーが起きる。

## 解決策
~~Pythonをsudoで呼び出さないでください。~~

@syamamura さんのコメントに書いてあるとおり、使いたいpythonへのpathを指定すれば良いです😅

```shell
$ sudo /path/to/python app.py
```
UbuntuでM5StackをUSBデバイスとして認識させる

ひとりアドベントカレンダー３日目

昨日の環境移行記事を書いた後で、事前にやっていたPCにM5Stackを認識させたりする部分に一切触れてなかったので、数を稼ぐ意味でもそのあたりを書いておきます。

# 環境

- Xubuntu 20.04
- 当時の対象デバイス：ATOM ECHO

```
$ uname -r
4.13.0-38-generic
```

# 手順

1. CP210xのドライバ導入
1. USBデバイスにアクセスできるよう、パーミッションを設定
1. 毎回パーミッション設定はしなくて済むように追加設定

## CP210xのドライバ導入
まず[M5Stackのページ](https://docs.m5stack.com/en/download)からUSBシリアルのドライバ CP210x_VCP_Linux.zip をダウンロード、展開しました。
Linuxのデバイスドライバのセットアップは初めてでしたが、以下のページ等を参考に行ってみました。
[UbuntuでESP32を使う際のVCPセットアップメモ \- Qiita](https://qiita.com/_kazuya/items/36baed86150d4fa6aaea)
[シリアルUSBアダプターをLinuxで使うには \| 近藤科学](https://kondo-robot.com/faq/usb-adapter-for-linux)

``` bash
make
sudo make install
sudo cp cp210x.ko /lib/modules/4.15.0-142-generic/kernel/drivers/usb/serial/
sudo modprobe cp210x
```
USBケーブルで接続後、```dmesg```で認識したのを確認しました。
確認したつもりでしたが、改めて今回見てみたところATOM ECHOはCP210Xではない別のデバイスとして認識されていたよう

``` bash
[  926.650383] usb 3-1: new full-speed USB device number 4 using xhci_hcd
[  926.792208] usb 3-1: New USB device found, idVendor=0403, idProduct=6001
[  926.792214] usb 3-1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[  926.792219] usb 3-1: Product: M5stack
  中略
[  926.854612] usbcore: registered new interface driver ftdi_sio
[  926.854879] usbserial: USB Serial support registered for FTDI USB Serial Device
[  926.854984] ftdi_sio 3-1:1.0: FTDI USB Serial Device converter detected
[  926.856051] usb 3-1: Detected FT232BM
[  926.856389] usb 3-1: FTDI USB Serial Device converter now attached to ttyUSB0
```
さらに以下のページによればCP210xのドライバはディストリビューションの一部として含まれているとの記述があり、ドライバ導入はやらなくても認識できていたのかもしれません。
[Ubuntu Linux v18\.0\+ のセットアップ :: AWS IoT EduKit](https://edukit.workshop.aws/jp/getting-started/prerequisites/linux.html)

## USBデバイスにアクセスできるよう、パーミッションを設定

作業が不要だったかどうかはさておき、USBケーブルで接続すると```/dev/ttyUSB0```として認識されました。
そしてさっそく書き込もうとしたところアクセスが拒否された。
見てみるとotherには読み書き権限がない。よって、権限を追加して対応

``` bash
$ ls -l /dev/ttyUSB0
crw-rw---- 1 root dialout 188, 0 Dec  3 23:26 /dev/ttyUSB0
$ sudo chmod 666 /dev/ttyUSB0
$ ls -l /dev/ttyUSB0
crw-rw-rw- 1 root dialout 188, 0 Dec  3 23:26 /dev/ttyUSB0
```

しかし、これだと繋ぎなおすたびに権限を設定する必要があって、ちょっと不便を感じるところ。

## 毎回パーミッション設定はしなくて済むように追加設定

調べたところ、いや今から考えると調べなくても状況をよく観察すれば分かることだが、dialoutグループに属せばいいということで以下を実行
[\[小ネタ\]Ubuntu でttyUSB0\(USBシリアル変換\)が権限関連で使えない場合の対処方法 \- Qiita](https://qiita.com/chromabox/items/b3ceaab6efa6edde2bda)

``` bash
sudo gpasswd -a ユーザ名 dialout
```

これでようやくスムーズに書き換えできるようになりました。
【超初心者向け】Python  if文  比較演算子まとめ

if文は、プログラムの中で条件分岐によって処理を行いたい時に使用します。

if文は、真(True)か偽(False)によって判定を行います。
(「True(真)」または「False(偽)」のいずれかの値をとる組み込み型のことを「bool型」という)

今回は、if文を書く時に初心者が覚えづらい「比較演算子」について超簡潔にまとめます。


#a == b       
 a=bであればTrue
(「=」の数は2つ！)       

#a != b        
a≠bであればTrue

#a < b         
aがbより小さい値であればTrue
(a=bの時はFalse)

#a > b         
aがbより大きい値であればTrue
(a=bの時はFalse)

#a =< b       
aがbの値以下であればTrue
(a=bの時もTrue)

#a => b        
aがbの値以上であればTrue
(a=bの時もTrue)

#a in b        
aがbの要素であればTrue

#a not in b    
aがbの要素でなければTrue

#a is b        
aとbが同じオブジェクトであればTrue

#a is not b    
aとbが同じオブジェクトでなければTrue
オンプレで動くHeroku互換システムと、最新のNuxt3で『はにゃーん』を作ったった

『[クソアプリ Advent Calendar 2021](https://qiita.com/advent-calendar/2021/kuso-app)』３日目の ひかる@alclimb でございます。

昨日の２日目は @nabettu さんによる『[Twitterに誰でもドット絵を投下できるサービスを作ったよ](https://qiita.com/nabettu/items/fa79c73aca3c504ec016)』でした！(作ったドット絵をテキストとしてコピーできるって発想にシビれます)

さて、今年で２回目の参加ですが、今年はオンプレで使える Heroku 互換システムである `Dokku` と、今年の10月にベータ版がリリースされた `Nuxt3` を使って、**技術検証欲で Web サービスを作ってみました。**

## (1) 作ったもの概要

![mockuper.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67192/a255fda1-1d75-b13b-342c-5978f2684975.png)

『はにゃーんボタン』を押すと はにゃん はにゃん 喋ります。**※音が出るのでご注意⚠**
用途は考えて無いので、『ちょっと疲れたなー』って時にでもどうぞ。

Web サービスの内容は適当で申し訳ないのですが、でもでも、はにゃんはにゃん聞いてるのは楽しかったです。こちらからどうぞ↓

https://hanyan.std9.jp/

## (2) システム構成

### サーバー側
サーバー側には `ConoHa VPS`, `Ubuntu`, `Dokku`, `Redis` を使用しています。
Redis はカウンターのデータベースとして使用しています。

### クライアント側
クライアント側には `Nuxt3` を使用しています。まだベータ版なので、資料が少なく、バグなのか仕様なのか、使い方が悪いのか、非常に困惑しましたが楽しかったです。


## (3) Dokku の構築方法

> **⚠ご注意**
> 構築しながらメモしたもので、まだ再現試験をしておりません。この通りに作業してもどこかで躓くかも… はにゃーん🤣

あらかじめ Ubuntu 20.04 LTS を用意します。サーバー上で以下のコマンドを実行します。

```shell
# 
# (1) Dokkuホスト上での共通設定
#  - Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-65-generic x86_64)
#  - Dokku v0.26.6
# 

# Dokkuインストール
$ wget https://raw.githubusercontent.com/dokku/dokku/v0.26.6/bootstrap.sh;
$ sudo DOKKU_TAG=v0.26.6 bash bootstrap.sh

# Dokkuのデプロイ先ブランチを変更する (master => main)
$ dokku git:set --global deploy-branch main

# 
# (2) Dokkuホスト上でのアプリケーション設定
#  - アプリ名: hanyan
#  - ドメイン名: hanyan.example.com
# 

# アプリケーションを作成
$ dokku apps:create hanyan

# Redisデータベースの作成とリンク
# 作業中のログに『REDIS_URL』が表示されるのでメモしておきます。後ほどRedisClientから接続する際に使用します。
$ sudo dokku plugin:install https://github.com/dokku/dokku-redis.git redis
$ dokku redis:create hanyan-redis
$ dokku redis:link hanyan-redis hanyan

# アプリケーションとドメインを連携
$ dokku domains:set hanyan hanyan.example.com

# 
# (3) SSL 対応
#  - LetsEncrypt通知メール: foo@example.com
# 

# Dokkuプラグインを追加
$ sudo dokku plugin:install https://github.com/dokku/dokku-letsencrypt.git

# メールアドレスの設定
$ dokku config:set --global DOKKU_LETSENCRYPT_EMAIL=foo@example.com

# LetsEncryptを有効化
$ dokku letsencrypt:enable hanyan

# 証明書を自動更新する設定
$ dokku letsencrypt:cron-job --add
```

ローカル環境での操作は以下の通りです。私は `Windows 10 64bit v21H2` ですが、SSH の設定と git の push 操作ができれば環境に左右されません。

```
# sshキー関係の設定
#   RLoginなどのソフトでsshのキーを生成
#   生成した秘密鍵をクライアント側の「C:\Users\<ユーザー名>\.ssh\id_rsa」に保存
#   生成した公開鍵(id_rsa.pub)をリモート側の「/home/dokku/.ssh/authorized_keys」に書き込み

# デプロイの準備 (gitのpush先にDokkuホストを追加)
$ git remote add dokku dokku@example.com:hanyan

# デプロイ (Dokkuにpushする)
$ git push dokku main:main
```

なお、Dokku は『ゼロダウンタイムデプロイ』に対応しているので、Web サービスのプログラム更新時にサービスを停止させる必要がありません。その辺も Heroku と同じですね。

## (4) おわりに

書きたいことは沢山あるのですが、タイムリミットのためここまでです。最後までご覧いただきありがとうございました～

はにゃーんボタンもよろしくお願いします！

https://hanyan.std9.jp/

明日は、@pik さんです！よろしくお願いします～
プログラムの「インターフェイス」って何？

他の記事を読んだ（勉強の痕跡）なので
下記のリンクから、元記事様へ行ってくださいまし。。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/3394c8a2-6eba-c908-091e-b851521069e4.png)
（引用元：https://kaitoribob.com/wp/column/amazon-fire-tv-stick%E3%81%8C%E3%83%86%E3%83%AC%E3%83%93%E7%94%BB%E9%9D%A2%E3%81%AB%E6%98%A0%E3%82%89%E3%81%AA%E3%81%84%E6%99%82%E3%81%AE5%E3%81%A4%E3%81%AE%E5%AF%BE%E5%87%A6%E6%B3%95/）


## ワタシ的インターフェイスとは、
指すだけで丁度良い電気が流れる「コンセント」（＝規格）みたいなもの。

SymfonyはPHPなのに「インターフェイス」の宣言などがあり「Java」みたいで難しい。
そもそもなんでこれインターフェイスの宣言が必要なのかと思ってしまうので、
いろんな記事を読み漁った。

https://www.gixo.jp/blog/5159/

https://teratail.com/questions/70213

https://tech.quartetcom.co.jp/2018/12/02/symfony4-autowiring-interface/

https://techacademy.jp/magazine/17414

https://style.potepan.com/articles/17088.html

http://www.tohoho-web.com/java/interface.htm

https://techacademy.jp/magazine/29628

https://www.atmarkit.co.jp/ait/articles/1511/02/news016.html

一番良いと思った例文を持ってきた。

# インターフェイスの定義

```php
<?php
interface フルーツ {
   public function 値下げを適用();
   public function 価格の表示();
   public function 価格の設定($値段);
}
```

フルーツのインターフェイスをあらかじめ設定しておく。

#クラスの実装

```php
<?php

class りんご implements フルーツ {
   private $値段 = 1000;
   public function 値下げを適用() {
      // 常に2割引
      $this->値段 = $this->値段　* 0.8;
   }
   public function 価格の表示() {
      return $this->値段;
   }
}

class ぶどう implements フルーツ {
   private $値段 = 2000;

   public function 値下げを適用() {
      if ('30' == date('d')) {
         // 30日なら半額
         $this->値段 = $this->値段 / 2;
      }
   }

   public function 価格の表示() {
      return $this->値段;
   }
}

class レモン implements フルーツ {
   private $値段 = 500;

   public function 値下げを適用() {
      // 値引きなし
   }

   public function 価格の表示j() {
      return $this->値段;
   }
}
```

**３つのクラスで「値下げを適用()」メソッドの処理内容が異なっているものの、**
**３つのクラスは必ず「値下げを適用()」メソッドを持ちます。**

**それぞれの値引き内容は、このメソッド内の実装部分だけを見ればいいので、**
**ソースの内容を理解しやすいといえるでしょう。**

ふむふむなるほど。

---
**インプリメンツには、条例を施行する、規約を実施する、という意味があります。**
**interface　っていうのが条例で、implements　がそれを施行する**

---
っていう意味か。フムフム。

## インターフェイス最大のメリット

役割ごとにカテゴライズされた各レイヤー間にインターフェース（契約）を設けることによって、
各レイヤー間を疎結合にし（依存度を低くし）、変更に強いアプリケーション作ることができる

あーそうゆーことね、完全に理解した。
嘘です。以上です。
Unityで自力描画。

この記事は、Unity Advent Calendar 2021 4日目の記事になります。

前日締切だったコンペへの提出が終わったあとのテンションで書きなぐったため、割と文章がおかしかったらごめんなさい。
もしかしたらあとで体裁を整えるかもしれません。

### 概要
Unityで弾幕STG等のオブジェクトを大量に出せるゲームを作るため、軽量な描画コマンドを記載する資料になります。

※実際のところBatchRendererGroupだったり、当たり判定組み込む場合JobSystem使えばもうちょっと速度出せるとおもうんですが、踏み込んだ最適化アプローチだったりするので、まずは楽にオブジェクトを出せるアプローチを記載することにしてます。

### こんな描画してるよ

![E_--_eHVkAEhmhH.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/142645/4c4fd0ee-0b8c-4e2d-5fc9-bf47e0c13624.jpeg)

割と手加減しているのですが、この時点で敵・エフェクト合わせてオブジェクトが1000個くらい画面に出てます。
更に言うと以下の状態です。

* フレーム制御かけてる（つまりCPU負荷が大きくなったらフレーム更新がされなくなる）
* 当たり判定を付けてる（量が膨大すぎたので2フレームで1回程度。CPU負荷に影響）
* 各オブジェクトに対して行動を指定している（CPU負荷に影響。スクリプト言語使っているため負荷は多め）
* アニメーションを制御している（UnityのAnimationがかゆいところに手がとどかないヤツなので自分で制御する仕組みを作った。内部ではマテリアルの切り替えが発生しているため、割とGPU負荷多め）
* クォータニオンで変形かけてる（その分CPU/GPUに負荷あり）
* PostProcessをかけてる（GPU負荷が高くなる）

これで問題なく、しかも楽に書けるので、Unityってすげえと思いました。
とりあえず描画であれば大量にできるわけですね。

バッチがどうなってるかは状況に依存しますが、割とまとまった描画になってると考えます。

### どういうアプローチで描画するか

https://docs.unity3d.com/ja/current/ScriptReference/Graphics.DrawMesh.html

DrawMesh命令で描画するだけ。

* どういう図形で（立体で）
* どういうマテリアルで（テクスチャ・合成方法で）
* どこの座標に
* どういう回転や拡大縮小して

描画するかを指定できます。

API自体は3Dの関数になるため、2D想定だと、以下の制御が必要と思料。

* スプライト扱いで描画するため２枚のポリゴンを生成
* Z方向も指定（ビルボードであれば方向は固定）
* テクスチャはMaterialに設定し反映

これで見た目2Dの描画ができてしまいます。
実際にはカメラを平行投影にする・カメラ描画の順位を変更する等の制御が必要ですが。

#### Unityで描画命令を書いたことないはずだが

Unityでは通常GameObjectにRendererをアタッチ、もしくはシーンに登録した時点で描画されます。

GameObjectに各種Rendererをアタッチしている状態だと、言ってしまうと「勝手に描画される」んですね。
そのおかげであまり描画を気にせず取り扱うことができるんですね。

たとえば、図形をシーンにドラッグ＆ドロップすると即時に描画されますよね。
あれは、最初からレンダラーがコンポーネントとして登録されているため、即時に描画される仕組みになっています。
（実際コンポーネント見てみるとレンダラーがアタッチされているはず）

### 他のコンポーネントとの連携

上でGameObjectとは関係なく描画コマンドを実行できることは記載しました。
じゃあGameObject・Collider等との関連性はどうなるのか？

答えは「GameObject等と関連しない形で描画ができる」です。

各コンポーネントは本来GameObject上にアタッチすることで効果を発揮するため、
DrawMeshを行った場合、実際の座標に関係させないことが可能になります。
GameObjectを取り扱う場合、各コンポーネントをアタッチすれば即動いてくれる敷居の低さがUnityの便利さではあるのですが、これらを使わないという選択肢も可能になるわけですね。

逆に言うと描画した座標と関連するように各コンポーネントを使うためにはC#で座標を制御する等での処理が必要になるため、Editor上での動作にはむいてない形になります。

### 描画を別コマンドで実行して何がしたいのか

自分の場合だと、「GameObjectを１個のオブジェクトジェネレータとしたい」です。

Unityにおいて、GameObjectをInstantiateするのは処理が重い、というのは割と知られていますが、同時にデータ量も多く、メモリ周りにも処理負荷がかかります。（ヒープもその分使っちゃうと、GC周りにも影響があるかと思います）

よって、大量のオブジェクトを動かす場合、GameObjectを敵や弾のマネージャとして、描画は別コマンドで実行、みたいなことを行うアプローチも出てくるわけです。

上記のケースではGameObjectで描画命令を発行するというアプローチは有用かと思います。

### Unityの便利機能を使わない理由はあるのか

Unityのレンダリングエンジンを組み込むことができ、
かつCPU・メモリの負荷をへらす動きができます。

激しい動きときれいな画面が同居する形になります。
よって、派手なアプローチがいっぱいできるわけです。

その代わり最終的な実装は面倒になります。
具体的にはGameObjectのUpdate関数に依存するコンポーネントと対象座標を紐付ける場合、そのバインド処理を書く必要がありますし、上記の通り描画命令を書く必要があります。
なお、描画命令についてはパイプラインやバッチング、カメラの設定に依存するので、書き方によっては性能が劣化したり、描画順によっては想定したように描画ができなかったりします。

自分の場合、描画のバッチングが有効になるようにマテリアルごとに描画をまとめたりしてできる限り描画が高速に行えるように内部で制御してます。
（実装の関係上アニメーションさせる際各オブジェクトが別マテリアル扱いになってしまうので、メモリにアニメごとのポリゴンを置いてそれを大量描画する形にしてバッチングが有効になるようにする等）

これは、自前でフレーム制御を行っていることとそれに伴って当たり判定やコントロールのタイミングを制御する必要があるために、上記のアプローチを取っています。

### 終わりに

割とこういうの書く機会もないので、一度かいてみました。
せっかくだからこういう需要が少ない記事を紛れ込ませるのもひとつということで。
（自分はUnityでも頑張って弾幕STG作りたい派です）

### 宣伝

現在インディーゲーム「Cry Pic.」開発中です。
上記の知識や描画を使って、大量の弾やエフェクトを描画してます。
php: いろいろなリダイレクト

リダイレクトしたいURL
https://sample.domain/xxx
↓
https://xxx.jp

#★PHPでかく場合
```php
  /**
     * @Route("/xxx", name="xxx")
     */
    public function index()
    {
        header('Location: https://xxx.jp', true, 301);
        exit;
    }
```

#★Symfonyで書く場合

```php
    /**
     * @Route("/xxx", name="xxx")
     */
    public function index()
    {
        return $this->redirect('https://xxx.jp', 301);
    }
```

#★.htaccess でやる場合

```
(Rewrite Engine on の下に追記する)
    RewriteCond %{QUERY_STRING} ^$
    RewriteRule ^xxx$ http://xxx.jp/? [R=301,L]
    RewriteCond %{QUERY_STRING} ^$
    RewriteRule ^xxx/sub$ http://xxx.jp/sub? [R=301,L]
```

#★AWSでやる場合

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/b57b4baa-a64f-69e1-350b-3d235251361d.png)

個人的には、AWS管理画面からリダイレクトさせた方が安全そう
status:301（引っ越しました）を返せるリダイレクトが SEO的にも好ましいです。
Blazor with Zeu.js

Zeu.jsは様々なデータをビジュアル化し、アニメーションで表示するJavaScriptライブラリです。
今回はBlazor WebAssemblyアプリで、Zeu.jsを動かしてみたいと思います:zap::zap::zap:

**Zeu.js**

https://github.com/shzlw/zeu

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/110304/15abeaad-a230-bbd2-365e-574597287301.gif" width=80%>

今回はバリバリのJavaScriptライブラリを使って、Blazorアプリケーションを作っていきたいと思います:thumbsup:

[**Demo**](https://blazorwithzeujs-4a68f.web.app/)

https://blazorwithzeujs-4a68f.web.app/

[**サンプルコード**](https://github.com/kimux8/BlazorAppWithZeuJS)

https://github.com/kimux8/BlazorAppWithZeuJS

#canvasの初期化

Zeu.jsは`canvas`を使ってますので、それぞれのコントロールを初期化する処理をC#側から呼び出します。

```c#:Index.razor
      <div class="col-lg-8">
        <div class="row">
          <div class="col-lg-8">
            <h1>MY COMMAND CENTER</h1>
            <div><a href="https://github.com/shzlw/zeu" style="font-size: 18px;">by Zeu.js</a></div>
            <div style="font-size: 22px; font-weight: bold;">US-EAST-01</div>
          </div>
          <div class="col-lg-4">
            <h2>TIME</h2>
            <canvas id="digital-clock" width="200" height="50"></canvas>
          </div>
        </div>
        
        <canvas id="heartbeat" width="730" height="150"></canvas>  👈ここに配置
      </div>
```

```html:index.html

    <script>
        window.Init = (_) => {
            /* Heartbeat */
            heartbeat = new zeu.Heartbeat('heartbeat', {
                viewWidth: 730,
                speed: 2,
                fontColor: COLOR.lightGrey,
                maxQueueCapacity: 50
            });
            heartbeat.scaleByHeight(150);
    // 中略
    </script>
```

`canvas`の初期化は `OnAfterRender`の初回レンダリング時に行うようにします。

```c#:Index.razor
@code{
    protected override  void OnAfterRender(bool firstRender)
    {
        if (firstRender)
        {
            JSRuntime.InvokeVoidAsync("Init", new object[] { });
        }
    }
}
```
#コントロールへ値のセット
コントロールの初期化が行えればあとは簡単です。
`inject`されたJavaScriptの呼び出し機能を使用して、`script`のファンクションにセットしたい値を渡すだけです。

```html:Index.raozr
    <script>
        window.valueChangeHertbeat = (p1, p2) => {
            heartbeat.beat({
                color: p1,
                space: p2
            });    
        }
    </script>
```

```c#:Index.razor
@code{
    void  OnClick()
    {
        var r = new Random();
        var ret = @"#" + System.Drawing.Color.FromArgb(r.Next(256), r.Next(256), r.Next(256)).Name.Substring(2);

        // Heartbeat
        JSRuntime.InvokeVoidAsync("valueChangeHertbeat", new object[] {ret,r.Next(0,10) });
    }
}
```

#JavaScriptライブラリを使う
BlazorはJavaScriptを使わずにC#だけでWebアプリケーションをコーディングできるのが大きな特徴でありますが、逆にJavaScriptとの親和性の高さも大きな特徴です。
UIに関してのユーザービリティやビジュアルなギミックは、純粋にBlazorだけで表現するのはまだまだ難しいですね:open_mouth:
いつか、すべてをC#でコーディングできる日がやってくるのでしょうか:rocket:
Flask入門①～文字の表示～

##はじめに
python自体は触れていたけど、フレームワークの知識が全くないことに気づきました。
まずは代表的なDjangoの説明を見てみたけど、**いきなりこれは…ハードルが高い！**と開始2秒で撃沈:sob:

フレームワーク触るのやめようと思ったけど、調べていたら「Flask」なるものを発見。
機能がもっとシンプルだし、自分でもまだ何とかなりそうと期待を持てたので学ぶことにしました。

##flaskのインストール
```python
conda install flask
```
普段のモジュールをcondaで管理しているので、pipではなくこっちでインストール(condaでも実施確認)。
環境は以下の通り。

* windows10
* flask2.0.2
* python3.8.10

##動作確認
```python:flask1.py　
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#flaskモジュールのインポート
from flask import Flask

#flaskオブジェクトの作成
app = Flask(__name__)

#「/」にアクセスがあったときに、'Hello world'を表示
@app.route('/')
def index():
    return 'Hello world'

#pythonで実行されたときに処理をする
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
```
appという名前のオブジェクトを作成して、実行内容を書く(ここでは'Hello world'の表示)。スクリプトが実行されると、'Hello world'が表示される。

ブラウザでlocalhost:5000にアクセスすると、表示されていることを確認。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/b7d0b557-4a57-f797-03d3-eded46fc7388.png)

##応用～おみくじの作成～
まずは簡単なものからスタート。ランダムに運勢を出してくれる、おみくじを作成してみました。

```python:flask2.py
#!/usr/bin/env python
# -*- coding: utf-8 -*-

#flaskモジュールのインポート
from flask import Flask

#flaskオブジェクトの作成
app = Flask(__name__)

#「/」にアクセスがあったときに、'Hello world'を表示
@app.route('/')
def index():
    import random

    #おみくじの種類
    omikuzis = ['大吉','吉','中吉','小吉','末吉','凶']

    #番号をランダムに選ぶ
    number = random.randint(0,6)

    #おみくじを表示
    omikuzi = omikuzis[number]
    print('今日の運勢は{}です。'.format(omikuzi))

#pythonで実行されたときに処理をする
if __name__ == '__main__':
    app.run(debug=True, host='0.0.0.0', port=5000)
```

まずは上記のコードで実施したらエラー画面が出ました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/93841324-bd8d-bd35-c9b8-3cf553476a57.png)

説明分を読むと、returnで実行していないことが原因らしい。そこで次のようにコードを書き換えてみました。

```python
#おみくじを表示
omikuzi = omikuzis[number]
return '今日の運勢は'+omikuzi+'です。'
```
これで再度localhost:5000にアクセスしたら、ちゃんと運勢が表示されてました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/e5bbb65c-6ebe-5827-fe59-fe79924679b1.png)

吉ということでそこそこよさそう。もう1回実施してみた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1259951/0b9e4e2f-62e9-21b2-fa8d-eae223cba60e.png)

たまには小吉になることもあるようです。

##まとめ

* Flaskが起動できた
* おみくじマシン作れた

次はhtmlの操作を扱ってみようと思います。
drwxrwxrwx って結局なんなの？


#drwxrwxrwx
```
$ chmod 777 directory_name
$ ls -l
```
とやると、ディレクトリの左がこうなるけど、結局いまいち
なんなのか、どれだったら正解なのか、よく分かってない。

「777 は駄目だ！危険だ！ 755とか754とか751にしなさい」
って先輩に言われたのでやってみると

```sh
$ chmod 755 directory
```

#drwxr-xr-x
なにが変わったんだろう？よくわからんなって思った時に読んでね。

#区切り方
**「d」「rwx」「rwx」「rwx」と区切る**

最初の「d」　は「これはディレクトリ」って事です。

最初が「-」（ハイフン）だったら、それはファイルです。

その後の rwx が「r=読む」「w=書く」「x=実行」
順番はこのようになっています。

「d」「自分」「グループ」「全員」

MacのFinderの「情報を見る」と同じです。

#数字との関連性

7 = rwx

6 = rw-

5 = r-x

4 = r--

1 = --x

chmod  777 で全員が読み書き実行できる。なるほど危険だ。
git commitするだけでコミットメッセージの自動追加と自動プッシュ

# はじめに
`git commit -am "コミットメッセージ"` をよく使うのですが、コミットメッセージに自動で今の時間が追加されて、その後にpushまでしてくれたら嬉しいですよね。
gitのhooksでそれを実現しました。なお、このスクリプトはBSD版シェルで動作します。

# 作ったもの
`git commit -am "コミットメッセージ"` を実行すると、

>2021-12-04-00:00:00
>コミットメッセージ

というコミットメッセージでコミットされる。同時に`git push`が実行される。

# やり方
1\.  `.git/hooks/`に`prepare-commit-msg`を作る。
2\.  `prepare-commit-message`を次のように編集する。 

```sh:prepare-commit-msg
#!/bin/sh
COMMIT_MSG_FILE=$1
echo "prepare-commit-msg"
DATE=$(date '+%Y-%m-%d %H:%M:%S')
sed -i '' -e "1i\\
$DATE" $COMMIT_MSG_FILE
cat $COMMIT_MSG_FILE
```

これはコミットメッセージの１行目に現在時刻を挿入するスクリプトです。OSXのBSD版shellでsedコマンドを正常に動かすためにsedの途中で改行を入れています。
ここでは確認のために内容を出力しています。

3\. `.git/hooks/`に`post-commit`を作る。
4\. `post-commit`を次のように編集する。

```sh:post-commit
#!/bin/sh
echo "hook post-commit"
git push
```

## 補足
初回pushでの--set-upstreamを自動で設定するために、
`git config push.default current`
を予め実行しておくとより使いやすいと思います。

また、hooksの実行を停止するオプションはありません。pre-commitとcommit-messageフックは`--no-verify`オプションでオフにできますが、post-commitとprepare-commit-messageには効かないからです。
これは、この２つのフックの想定されている使い道がこのような自動化でないからだと考えられます(参考:[Git Hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks))。使用する際は、個人リポジトリで使うのが賢明かもしれません。
【Laravel】Str::isでは改行を扱えませんよという話

# 環境

PHP 8.0
Laravel 8.x
Docker(Laravel Sailで構築した環境を使っています)

# 目的

Laravelのヘルパ関数Str::isを使っていてハマった時の備忘録にすること

# Str::isって何よ？

ある文字列Aの中に、別の文字列Bが含まれているかどうか判定してくれるヘルパ関数です。いくつか例を挙げておきます。

```PHP
use Illuminate\Support\Str;

$matches = Str::is('foo*', 'foobar');

// true

$matches = Str::is('baz*', 'foobar');

// false
```
引用元(一部改変):[Laravel 8.x ヘルパ Str::is](https://readouble.com/laravel/8.x/ja/helpers.html#method-str-is)

# ある日のこと...

しゃっちょさん「キーワードの判定が改行に反応してくれないんだけど...」

私が参画していたプロジェクトでは問題のStr::is関数を使って、キーワードが特定の文字列に含まれているかどうかを判定していました。そこで以下のような事象が上がってきたのです。

```PHP
use Illuminate\Support\Str;

$matches = Str::is('foo*', 'foo\nbar');

// false
// !?
```
キーワード判定される文字列に改行があると正しくキーワード判定されないのです。これは問題です。先ほどの引用元のドキュメントにも書いてありますが、アスタリスクはワイルドカードとして扱われるので`true`が返って良さそうなものです。

# さぁ調査だ

なぜ`true`が返らないのでしょうか？ドキュメントの記述はえらいあっさりしていて参考にならなかったのでLaravel本体のコードを確認してみることに。Str::is関数のコードを抜粋します。


```
    public static function is($pattern, $value)
    {
        $patterns = Arr::wrap($pattern);

        if (empty($patterns)) {
            return false;
        }

        foreach ($patterns as $pattern) {
            if ($pattern == $value) {
                return true;
            }

            $pattern = preg_quote($pattern, '#');
            $pattern = str_replace('\*', '.*', $pattern);

// 【重要】このif文の条件式でキーワード判定をしている
            if (preg_match('#^'.$pattern.'\z#u', $value) === 1) {
                return true;
            }
        }

        return false;
    }
```

コードを見ると内部的にはStr::isはPHP組み込みの`preg_match`関数を使ってキーワード判定をしているようです。どうやらこの辺に落とし穴がありそう。

# 解決策

解決策をbefore->afterで掲載します。

before(再掲)

```PHP
use Illuminate\Support\Str;

$matches = Str::is('foo*', 'foo\nbar');

// false
// !?
```

after(文字列結合が冗長ですが分かりやすくする為にあえてこう書いています)

```PHP
use Illuminate\Support\Str;

$matches = preg_match('/[\s\S]*'.'foo'.'[\s\S]*/', 'foo\nbar');

// true
```

参考:[エスケープシーケンス「\s\S」を利用する](https://www-creators.com/archives/2589#1sS)

# なぜこれで解決するのか(原因も含めて)

問題の`preg_match`関数が改行に反応しなかったのは先ほどのStr::is関数のコードの中のこの部分が原因でした。抜粋して再掲します。

```
$pattern = str_replace('\*', '.*', $pattern);
```

元の`$pattern`に入っている`\*`を`.*`へ置換しています。PHPの正規表現では`.`は任意の1文字を表し、`*`は0回以上の繰り返しを表します。少なくとも正規表現をかじった程度の私のような人はそういう認識でしょう。よって最終的な`$pattern`変数では元々のLaravelでのコード内でのワイルドカード(`*`)が適切な正規表現(この場合は`.*`)に変換されている***ように見えます。***

しかし、PHPの正規表現では`.`は***改行を除く任意の1文字を表すのです。***
すなわち`.*`したとしてもその先に1つでも改行があればマッチしないと判定されるということです。

解決策のコードではワイルドカードの部分で

- 空白、タブ、フォーム フィードなどの任意の空白文字を表す`\s`
- 空白以外の任意の文字を表す`\S`

これらを組み合わせることで改行を含めた全ての文字に対応する文字通りの「ワイルドカード」を実現しています。あとはそれを`*`で繰り返すだけです。

# 最後に

間違いのご指摘や少しでも気になったことはコメントを頂けますととても嬉しいです！
M1 Pro MacBook Pro が届いて最初にやったこと

MacBook Pro (14-inch, 2021) が届いて最初にやったことをメモ。
---
1. Xcode のインストール
  - Xcode を App Store からインストール
1. X Quartz のインストール
   - https://www.xquartz.org/
1. Homebrew のインストール
   - https://brew.sh/index_ja
1. Python 3, wget, nkf, unar のインストール
   - ```$ brew install python3 wget nkf unar```
1. ImageMagic のインストール
   - ```$ brew install imagemagick```
1. VScode のインストール
   - ```$ brew install visual-studio-code --cask```
1. Emacs のインストール （ https://formulae.brew.sh/cask/emacs )
   - ```$ brew install --cask  emacs```
1. GnuPlot のインストール ( https://formulae.brew.sh/formula/gnuplot )
   - ```$ brew install gnuplot```
1. Gimp のインストール ( https://formulae.brew.sh/cask/gimp )
   - ```$ brew install --cask  gimp```
1. Inkscape のインストール
   - ```$ brew tap homebrew/cask ```
   - ```$ brew install inkscape ```
1. R のインストール ( https://formulae.brew.sh/cask/r )
   - ```$ brew install --cask r ```
1. TeX のインストール ( https://texwiki.texjp.org/?TeX%20Live%2FMac )
   - ```$ brew install --cask mactex ```
   - ターミナル再起動
   - ```$ sudo tlmgr update --self --all ```
   - ```$ sudo tlmgr paper a4 ```
1. Maxima のインストール  ( https://formulae.brew.sh/formula/maxima )
   - ```brew install maxima```
1. GPG のインストール
   - ```brew install gpg2 pinentry-mac```
1. その他
   - Chrome, Firefox, Edge
   - MS Office, Libre Office
   - Zoom, OBS
   - Skype, WhatsAppk, Keybase
   - Dropbox, Evernote
   - AppCleaner
   - Google 日本語入力
OpsRamp 外形監視（Synthetic Monitoring）

2021年OpsRampアドベントカレンダー12月4日分の投稿です。

# 概要

OpsRampでもWEBサーバの応答性能などをモニタリングする外形監視が可能です。
今回はQiitaに対してHTTPSの監視を設定してみたいと思います。








# 外形監視の設定

### 利用できる外形監視の一覧

| 項目 |
| :-- |
| HTTP/HTTPS |
| DNS |
| PING |
| SIP (VoIP) |
| TCP/UDP |
| IMAP/POP3/SMTP/RTT (Mail) |
| SSL |
| FTP |
| SCRIPT -HTTP Synthetic Transaction |


※OpsRamp公式ドキュメント
https://docs.opsramp.com/solutions/monitors/synthetic-monitors/



### 監視ロケーション
ロケーションは最大3つ選択できます。

| ロケーション |
| -- |
| Asia Pacific　（Singapore, SG） |
| Europe / Middle East　（Longon, England, UK / Frankfurt, DE） |
| North America　（Atlanta, GA, USA / Atlanta, GA, USA-2） |



### 設定手順（HTTPSの場合）

外形監視を利用するには、クライアント（≒テナント）作成時に設定したマネジメントプロファイルで有効にする必要があります。外形監視を有効にしたいマネジメントプロファイルをクリックします。

| ![2021-1128-1728-33.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/0b889c8c-641a-caad-6798-602146762a30.jpeg) |
| :-- |


"Synthetics Agent"をONにします。

| ![2021-1128-1727-50.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/24d19245-785a-a075-187b-d24cdcf7792f.jpeg) |
| :-- |


それでは監視の設定を追加していきましょう。
"Resources" > "Synthetics" > "Add" をクリックします。

| ![2021-1128-1742-51.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/ca3eb8a1-1a5e-361b-a774-9af5dc758956.jpeg) |
| :-- |


"HTTPS"を選択します

| ![2021-1128-1641-52.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/76f612af-bf71-7e47-9350-12c029fa6a35.jpeg) |
| :-- |


HTTPS監視に必要な設定項目が表示されるので入力して"Save"します。
※今回はログインなどしないので"Authentication Type"は指定しませんでした。

| ![2021-1128-1745-29.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/6d6f8b22-4ca0-a1d5-a9a4-201458fb73b9.jpeg) |
| :-- |


このままだと何も監視してくれないので、監視テンプレートを割り当てます。
追加されたHTTPS監視をクリックします。

| ![2021-1128-1746-22.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/cd052374-7457-d49f-b90e-d3a590f9a855.jpeg) |
| :-- |


"Monitors" > "割り当てるテンプレート" をクリックします

| ![2021-1128-1747-08.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/950c6e16-1f40-165b-731c-0dbbb8aa5681.jpeg) |
| :-- |


コレクターは"Synthetics"のままにして、任意のテンプレートを割り当てます。

| ![2021-1128-1747-26.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/8fc53fe1-6eb7-c773-bc50-d78c97c81174.jpeg) |
| :-- |


これでHTTPS監視が始まりました。



# 動作確認

数分すると”Metrics"にグラフが表示されます。デフォルトで8項目のメトリクスが取得されています。

| ![2021-1128-1748-42.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/45324052-c50b-c30a-de99-37c914645b29.jpeg) |
| :-- |


| ![2021-1128-1749-18.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/333529/f5f45e18-d25e-834d-4d42-9f89785213fb.jpeg) |
| :-- |



他にも監視項目があるので今後試してみたいと思います。



おわり。
class構文って何？どう使うの？

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/216132/7576dfae-e547-96ce-230a-89fa0f6f6705.png)

「class構文」って普段jQueryとWordPressだけ使ってたら絶対に見ない。
知らずに遭遇したら「class構文アレルギー」になっちゃうので、免疫を付けたい。

なので、いろんな記事を漁りました。JSとPHPで、理解しやすい方から学ぶスタイル。

https://www.sejuku.net/blog/49551

https://www.willstyle.co.jp/blog/2435/

https://techacademy.jp/magazine/14654

http://www.tohoho-web.com/js/class.htm

https://qiita.com/JPNYKW/items/248f99c94c00c3d1aa27

https://html5experts.jp/takazudo/17355/

一番わかり易い例文は、コレだと思いました。JSです。

```html
  <body>
    <script>

      class Person {
          constructor(名前) {
              this.なまえ = 名前;
          }
          say() {
              console.log("こんにちは。" + this.なまえ + "です");
          }
      }
 
      var nishi = new Person("西 大輔");
      nishi.say();
 
      var pikkoro = new Person("ピッコロ大魔王")
      pikkoro.say();

    </script>
  </body>
```

実行すると、コンソールに表示される文字は

```
こんにちは。西 大輔です
こんにちは。ピッコロ大魔王です
```

javascriptで、昔ながらの書き方だと

```javascript
function Person(名前) {
    this.setName(名前);
};

Person.prototype = {
    setName: function(名前) {
        this._なまえ = 名前;
    },
    getName: function() {
        return this._なまえ;
    },
    say: function() {
        console.log('こんにちは。' + this._なまえ + 'です');
    }
};

var nishi ="西 大輔";
Person.say(nishi);

var pikkoro = ("ピッコロ大魔王")
Person.say(pikkoro);
```

急に「体になじむ感じ」がしてきました。（newしてないから微妙にちがうかも？）

つまりJavascriptの `function()` の下に `prototype` を書くのと一緒だということ。

インスタンス（分身）を生成するから、引数を保持したままで、

いろんな呼び出し方でくり返し使えるよっていう、シンプルにそれだけだと思う。

「コンストラクタ」とは「最初に実行されるやつ」です。
「一番上に書く」のと何が違うのか？多分一番上に書くより先に実行されるということでしょう。

以上です。
GitHubでSSHキーを設定する

## 事前準備
- GitHubに登録済みであること
※後日リンク追加

## 1. 秘密鍵/公開鍵を作成

鍵を保存するディレクトリ作成。すでに存在する場合は作成不要。

```
$ mkdir ~/.ssh
```

秘密鍵/公開鍵ペアを作成(実行場所はどこでも)。

```
$ ssh-keygen -t ed25519
Enter file in which to save the key (/Users/(username)/.ssh/id_ed25519):
Created directory '/Users/(username)/.ssh'.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
```
コマンドを実行したら、Enterを3回押す。
保存場所とパスフレーズの設定だが今回はしない。
鍵ペアが`~/.ssh`に作成される。

秘密鍵：`id_ed25519`
公開鍵：`id_ed25519.pub`


## 2. GitHubに公開鍵を設定

公開鍵をクリップボードにコピー。

```
$ pbcopy < ~/.ssh/id_ed25519.pub 
```

GitHubに公開鍵を設定。

1. [GitHubのssh設定](https://github.com/settings/ssh)を開く
2. `New SSH key`をクリック
3. `Title`に適当な名前を入力
4. `Key`に先ほどコピーした公開鍵をペースト
5. `Add SSH key`をクリック


GitHubにSSH接続できることを確認。

```
$ ssh -T git@github.com
Hi (account name)! You've successfully authenticated, but GitHub does not provide shell access.
```


## 関連
https://qiita.com/mz_mz_mz/items/4510f7c4abb839f000b7

## 参考
- [GitHubでssh接続する手順~公開鍵・秘密鍵の生成から~](https://qiita.com/shizuma/items/2b2f873a0034839e47ce)
- [気付けばssh-keygen -t の後にrsaでなくed25519と打つことが推奨されていた](https://tech.asahi.co.jp/posts/20231005-bbf6)
毎日誰かのプルリクを脳死でマージするアドベントカレンダー にWebGLエフェクトのライブラリ「react-vfx」つっこんでみた

https://qiita.com/advent-calendar/2021/full-scratch-awesome-app-nextjs

の3日目です。

リポジトリはこちら

https://github.com/TeXmeijin/anyway-merge-app

2日目は @sassy_watson さんでした

https://qiita.com/sassy_watson/items/9d0010fc99b7b0ee7ec5

---

なんかこのツイート

https://twitter.com/Meijin_garden/status/1455062665160638470

を見て面白そうだなーと思い勢いで参加してみました、参加当時からグラフィック系のライブラリ入れてみようと思っていました

p5.jsやthree.jsとかも考えていましたが、なんとなく気になっていたのと入れるだけでなんとなく見た目変わってくれて面白かったのでreact-vfxを入れてみました。

https://blog.amagi.dev/entry/react-vfx

https://amagi.dev/react-vfx/

https://github.com/fand/react-vfx

入れてみたはいいけど

```
THREE.WebGLRenderer: Error creating WebGL context.
```

とエラーが出てWebGLが動かない。なんでだろうなあと調べてたら
いつのまにか自分でChromeの設定でハードウェアアクセラレーションがオフにしていたようでした

https://masshiro.blog/webgl-chrome/

https://masshiro.blog/a/does-my-browser-support-webgl.html

---

該当プルリクはこちら

https://github.com/TeXmeijin/anyway-merge-app/pull/6

---

いきなりちょっと亜流なもの入れちゃいましたが、今後どうなることやら。
なんか知らない人とチーム開発するのは不思議な気持ちですね、
このアドベントカレンダーに参加した結果他の人がどういうもの作るか、どう書くのかがより気になってなぜか毎日見てしまっています。笑
明日4日目は @okumura_daiki さんです、よろしくお願いいたします〜