OmniAICreator/Qiita-1.07M huggingface dataset:
AWS SOA取得に苦戦(2回不合格)したので振り返る。

# SOAに合格できました！！！

![スクリーンショット 2023-02-26 23.40.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1620925/44e3dc92-a63d-3c3d-9a91-7a6ce248c9be.png)
(マスクが適当でスミマセン)


表題の通りSOAに合格することができましたので、合格までの道筋を振り返りとして残していけたらなと思います。
同じくSOAで苦しんでいる方の一助となれたら幸いです。

## 2度も不合格となる、、、
タイトルにもある通り２回もSOAに落ちてしまいました。
今振り返ると正しい勉強ができていなかったな。。。と思います。

反省として`テスト勉強のためのテスト勉強`になっていたのだと思います。
昨年の8月にSAAを取得したのですがその際は、Udemyのハンズオンを軽くさらうことと2種類の問題集を反復して解くことが主な勉強方法で、あまり体系的な勉強ができていなかったのだと思います。
正直SAAはそこまで重箱の隅をつつくような問題は出ず、基本的なサービスの概念がわかっていれば全く問題のない印象でした。

しかしSOAはそう簡単にはいきませんでした。
SAAの時と同じような学習方法で1ヶ月ほど勉強してから挑んだのですが「知らない単語がある、、、」と絶望したのを今でも覚えています。
またこの時点で自分はもっといろんな問題を解けば受かるだろうと問題集を変えてそれを反復で解くという学習法を選んでしまいます。（本当に今考えると甘いなあと思います。。。）

# 反省から修正した勉強法
まずテストの際に知らない単語は覚えて帰ろうとテスト中に単語名を覚えて帰り道の電車の中でスマホでドキュメントを漁るなどをしました。こうして悔しさの感情と記憶を結びつけ忘れないようにしました笑

メインの教材として
- [青本](https://www.amazon.co.jp/AWS%E8%AA%8D%E5%AE%9A%E8%B3%87%E6%A0%BC%E8%A9%A6%E9%A8%93%E3%83%86%E3%82%AD%E3%82%B9%E3%83%88-AWS%E8%AA%8D%E5%AE%9ASysOps%E3%82%A2%E3%83%89%E3%83%9F%E3%83%8B%E3%82%B9%E3%83%88%E3%83%AC%E3%83%BC%E3%82%BF%E3%83%BC-%E3%82%A2%E3%82%BD%E3%82%B7%E3%82%A8%E3%82%A4%E3%83%88-NRI%E3%83%8D%E3%83%83%E3%83%88%E3%82%B3%E3%83%A0%E6%A0%AA%E5%BC%8F%E4%BC%9A%E7%A4%BE/dp/481560908X/ref=sr_1_2_sspa?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=6DY66A4T8SFQ&keywords=aws+soa&qid=1677424456&sprefix=aws+so%2Caps%2C192&sr=8-2-spons&psc=1&spLa=ZW5jcnlwdGVkUXVhbGlmaWVyPUFYVE9SMjE2WjNCVDkmZW5jcnlwdGVkSWQ9QTAxMzI5OTkxQU0wQUk3UjFYNFBXJmVuY3J5cHRlZEFkSWQ9QTJOSlZROFpXMDhLNkUmd2lkZ2V0TmFtZT1zcF9hdGYmYWN0aW9uPWNsaWNrUmVkaXJlY3QmZG9Ob3RMb2dDbGljaz10cnVl)
- [BlackBelt](https://aws.amazon.com/jp/events/aws-event-resource/archive/?cards.sort-by=item.additionalFields.SortDate&cards.sort-order=desc&awsf.tech-category=*all)
- [Udemy](https://www.udemy.com/course/aws-associate/)
- [teckstock](https://techstock.jp/)

を活用しました。



具体的な使い方として青本の方は3回は通して読み、暇な時は斜め読みなどしていました。

次にTeckStockで問題を解き、分からなかった問題はBlackBeltで適宜調べノートに書きどこが理解できていなかったのかを明らかにしていきました。

そしてラボ対策としてSAAのものでは有りますがUdemyのハンズオンをこなしました。(初めてAWSを触った時に比べこのサービスはなぜこのように操作するのかといった部分が少し理解できた感じがしたことを覚えています)

またSOAの重要な部分である`Cloudwatch`,`Cloudformation`,`IAM`,`SystemManager`に関しては`BlackBelt`で知らなかったことをノートに書き取るなどしました。（特に`CloudFormation`の各設定値の振る舞いだったり、組み込み関数などに関しては文面だけではわかりにくいことが多くUdemyのハンズオンを照らし合わせながらの勉強法をしました。）

# 3回の受験を終えて

以下のことを学び、気づきました。

- `テストのためのテスト`になってはいけない
- 問題は最後までしっかり読んで判断する

どちらも当たり前のことですね、、、

まず > `テストのためのテスト`になってはいけない　に関して、そもそも試験の目的はAWSの知見の確認、取得そして扱えるようになることであるので受かることだけに対して執着しているとかえってテストは合格への遠回りだと感じました。

要所要所で単語の意味を覚える方法では点と点が線としてつながらず、体系的な学習ではないということを今回の苦戦した勉強期間に痛感しました。反省から修正した勉強法の王目で記述した内容をもとに勉強したことで既存の模擬問題で解いたことないタイプの問題が来ても柔軟に対応できるはずです。

もうひとつの > 問題は最後までしっかり読んで判断する　はSAAでも感じましたが問題を読んでいく中で思い浮かぶサービスがあると思うのですが最後の一文まで読み取って判断することが大事だなと思いました。どうしても模擬試験を解く勉強法を続けているといつの間にか斜め読みして即判断してしまいがちですが、落ち着いて解くことが大事です。

# 最後に
最後まで読んでいただいた方ありがとうございました。まだまだ未熟者ですが、学んだ知識を業務に生かせるよう学習を継続していきたいと思います。また勉強方法や考え方は人それぞれだと思いますので、参考程度にこんな勉強法もあるなくらいだとありがたいです。

次はDVAをとりたい思います。試験勉強されている方、しようと思っている方、一緒に頑張りましょう〜！
Python全く分からん自分のアウトプット　その6

6日目：今日もやっていくぞ！！！、、、の前に、

自分の中でものすごいことを知ってしまったからここに残しておく。
今まで何食わぬ顔で「if」って「もしも〜だったら」って意味で考えてたけど、気づいた。
普通の英語そのままじゃなくて「〜だったら〜の行動を取ってね」っていう命令文だったことに…！！

しかも「else」はこういうのがあるんだなー程度に思ってたけどちゃんと「〜じゃなかったら〜の行動よろ」って命令文だったことにも気付いた…！！

そして、更に俺はマジックカード「融合」を発動！！「if」と「else」を融合！
「〜じゃなかったら次に〜の行動を取ってね」「if」と「else」の間！！
融合召喚！！🙏「elif」！！！！！
…やばいYPがバレる💦
やっぱりふと疑問に思ったら調べるってことを日常や仕事中に行う癖がついててよかったと思った瞬間だった。
さあ気を取り直してやっていくぞ！！！！！




◎以下調べたこと、疑問に思ったこととかのメモ◎


クラス・・・「設計図」。要は「もの」を錬成するために用意する錬成陣。

インスタンス・・・「もの」。錬成するとできるもの。

インスタンス変数
メソッド・・・「インスタンス｡メソッド名()」
self・・・インスタンス自身を指す


ｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰ

今回は前半けっこうスムーズに出来たが後半複雑になってくるとわけワカメ状態になる。
ここは慣れと数をこなしていくのが無難か？
次もPythonコース4の続きからやっていこう。

PS｡再来週の3月11日までにアプリをひとつ作ろうと思う。
参考になるサイトを探したら、前回やった部分の応用のような感じの構造に見えたのでやってみる。
つくるアプリは「対戦相手をランダムで決められるアプリ」。これは友人達とのいつものオンライン対戦中にふと頭に浮かんだ。みんなに感謝。
次に何か作るなら導入したいツール

# 概要
次のプロジェクトでも導入したいツールを備忘として残す

## make
- 概要
オレオレコマンドを定義できる
git add. -> git commit　などを一発で実行したいときに便利

- 使い方
    1. Makefileを定義する (サンプルはterraformの場合)
    1. Makefileと同じ階層でコマンドを実行する

Makefileサンプル
```
install:
        asdf install
        tflint --init

lint:
        teraform fmt -recursive && \
        terraform validate && \
        tflint

init:
        terraform init

plan:
        terraform validate && \
        terraform plan

apply:
        terraform validate && \
        terraform apply        
```
下記で使用可能
```
make init
make plan
make apply
```
- 参考
https://www.miraclelinux.com/tech-blog/0icygs

## asdf
- 概要
必要なツールをコマンド一発でインストールできる
- 使い方
    - [インストール](https://asdf-vm.com/guide/getting-started.html)
    - .tool-versionsを定義
    - .tool-versionsと同じ階層でasdf install　実行
.tool-versionsサンプル
```
nodejs 16.15.0
terraform 1.3.7
tflint 0.44.1
tfsec 1.28.1
```

## npx git-cz
- 概要
commit時にprefixを強制する
commitが追いやすくなるため、個人的にはprefixをつけたい派
prefix適用漏れなどを防げる
デフォルトからのカスタマイズも可能
- 参考
https://rightcode.co.jp/blog/information-technology/git-cz-commit-message-format-unification-syain
enPiT-ws in Iwateに行って

# 他大学と交流して感じたアジャイルの学び
こんにちは。2/22に岩手県立大学で行われた「enpit-ws in Iwate」に行ってきたので、報告がてら、アジャイル開発について感じたことを記します。
ワークショップについての詳細は↓のリンクから

https://www.enpit-ws.com/

アジャイルワークショップに参加し、実際に他大学の学生たちとenPitについて意見交換を行うことで、アジャイル開発についての知識を深めることができました。特に、筑波大学のenPitの質の高さを知ることができたと感じています。

### 他大学のプロダクト

ワークショップには、岩手県立大学をはじめとして、会津大学やはこだて未来大学等10校近くの大学から約15チームが参加していました。中でも特に目を引いたプロダクトは、埼玉大学の「DISTIME」と室蘭工業大学の「室蘭まもるくん」でした。DISTIMEはプライバシーに配慮したzenlyのようなソリューションで、室蘭まもるくんは防災ハザードマップを利用しやすいアプリケーション形式に落とし込んだソリューションで、両者ともに非常に高い完成度でした。私たちの作成したプロダクトと比べると、圧巻の技術力というような感じでした。

しかし詳しく話を聞いてみると、アジャイル開発というよりも、ウォーターフォールに近い手法で開発を行っており、個人の技術力や、マンパワーに頼っている印象を持ちました。これは他の開発グループにもあてはまり、技術の高さや完成度は目立つものの、アジャイルワークショップに対して機能の説明が過多になっており（まあ、時間がなかったこともありしかたないのですが）、アジャイル開発とソリューションの完成度の両立にはテクニックが必要という印象でした。

更に話を聞いてみると、他大学では、ソリューションが動く形式になったチームが少なかったとのことなので、開発自体がかなり高いハードルなのかなという印象を受けました。

### 筑波大学enpitの特徴

他大学の取り組みを拝見した筑波大学の特徴は以下の2点です。

- 技術力が高い
    
    筑波大学では約10チームが開発を行っていましたが、短い時間にも関わらず、完成（もしくは動くソリューション）させているチームがほとんどだった印象です。他大学では、ログイン画面のみの実装にとどまっているというところもあり、筑波大学生のすばらしさを感じました。
    
- アジャイルに力を入れている
    
    他の大学では「ソリューションの開発」に力を入れているチームがおおく、そのために残業やハードワークをしているところが多かったです。筑波大学enpitでは、カリキュラム上振り返りやAMFを重視しているため、プロダクトの価値を検証するという点で、アジャイル的な価値観を身に着けやすかったと感じます。特に私たちのチームは、「時間は有限」というように考え、機能や実装を絞って最終発表に取り組んだ点が非常に良かったのだなという印象を受けました。アジャイルの定義に沿って、機能については妥協する必要があり、そのためにはソリューション自身の見直しも必要であるということを学びました。
    

上記の2点に共通して言えることは、筑波大学enPitは他の大学と比較してとても良いカリキュラムで作られているということです。文部科学省の取り組みの枠から外れたにも関わらず、これまで手厚いアジャイルの指導が受けられる筑波大学enPitはとても有意義なものだと思います。特に春の事前学習は開発に必要な知識を自ら吸収できるうえに、メンターが様々な取り組みを進んで行ってくれるため、開発未経験の私でも有意義なアジャイルライフを送ることができたと感じています。

また、そのような手厚いカリキュラムと最高のメンバーに恵まれ、チーム開発賞を獲得することができました。皆さんありがとうございました。
Vimの基本的なコマンドリスト

# はじめに
よく利用するvimの基本コマンドをリスト化しました！

# エディタを起動する前の操作
## 起動
* `vim`：vimエディタを起動
* `view`：viewモードを起動
  * vimの機能を使って、ファイルの書き換えミスの保存やアクシデントなどを防ぎたい時に利用

# インサートモード上の操作
## モードの切り替え
* `i`：インサートモードに切り替え
* `esc`：ノーマルモードに切り替え
* `a`：次の文字からインサートモードに切り替え
* `o`：カーソルの下に空白を入れ、インサートモードに切り替え
* `O`：カーソル行に空白を入れ、インサートモードに切り替え
* `:`：コマンドモードに切り替え
* `\`：コマンドモードに切り替え
* `v`：ビジュアルモードに切り替え
  * 複数文字や行を選択できる

# ノーマルモード上の操作
## 移動
* `k`：上に移動
* `j`：下に移動
* `h`：左に移動
* `l`：右に移動
* `0`：先頭に移動
* `^`：インデントの先頭に移動
* `{`：ひとつ上の段落に移動
* `}`：ひとつ下の段落に移動
* `[[`：ひとつ上の空白行に移動
* `]]`：ひとつ下の空白行に移動
* `gg`：ファイルの先頭に移動
* `G`：ファイルの最後に移動
* `Control + o`：移動前に戻る

## 保存
* `w`：上書き保存
* `wq`：保存して終了
* `q`：編集終了
* `q!`：保存をせずに終了

## 削除
* `x`：1文字削除
* `dd`：1行削除
  * `2dd`：2行削除
  * `3dd`：3行削除
* `dw`：単語ごとに削除

## 戻る&進む
* `u`：ひとつ前の状態に戻す（作業と元に戻す）
* `Control + r`：直前の操作に進む

## コピー&ペースト
* `yy`：1行コピー
  * `2yy`：2行コピー
  * `3yy`：3行コピー
* `p`：カーソルの下にペースト
* `P`：カーソルの位置にペースト

## 連結
* `J`：カーソル行と下の行を連結する

# コマンドモード上の操作
## 実行
* `:!${コマンド}`：コマンドを実行
  * :!python3 test.py
  * :!ruby test.rb
  * :!ls
* `:!!`：前のコマンドを実行

## 削除
* `:%d`：一括削除（ファイルの中身を空の状態にする）

## 検索&置換
* `\${ワード}`：検索
* `n`：次の検索結果に移動
* `N`：前の検索結果に移動
* `R`：置換
* `:%s/${ワード}/${ワード}/g`：一括置換
  * `:%s/dev/prod/g`：devのワードをprodへ全て置換する
* `:%s/${ワード}/${ワード}/gc`：確認しながら置換
  * `:%s/dev/prod/gc`：devのワードをprodへ、1ワードずつ確認しながら置換が可能
  * コマンド実行後に、確認オプションが出力される

## 移動
* `:set number`：行数を表示
* `:set nonumber`：行数を非表示
* `:${数字}`：指定した行数に移動
  * `:5`:5行目に移動
  * `:10`:10行目に移動

## コメントアウト
* `:norm I#`：複数行コメントアウト

# ビジュアルモード上の操作

## 移動
* `y`：カーソル指定をコピー
  * コピーした後はノーマルモードの`p`でペースト
* `>`：選択したものを右にインデントで移動
* `<`：選択したものを左にインデントで移動
AWS上に作成したMattermostに502エラーが出た話

# まずは構成図
AWSにmattermostを、terraformで構築した時の話です。
まずは構築した構成図です。
![あああ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227793/211f9641-9c4c-78c2-51d6-84bb3a3842f6.png)
+ ec2インスタンスはauto scaling groupにて最小1の構成で1a, 1cに構築されます
+ ALBを踏み台にしてtarget groupに構築したec2を指定して8065ポートでアクセスします(mattermostはデフォルトで8065をリッスンします)
+ ALBは↑のtarget groupをForwardでHTTPS(443)でルーティングします
+ route53でドメインを取ってCertificate Managerでssl認証させています
+ ec2はamazon linux2のt2.micro です
+ 他はよくある構成と同じです(割愛します)
# 502エラーとの出会い
terraform applyでウッキウキで完了を待ち、ドメインを見に行くと、そこに現れたのは502 bad gatewayでした。
しかし焦る事勿れ。awsのec2を状態を見に行きましょう。
今回、ec2でのmattermostをインストールしデーモン化する所もスクリプトで書いているため、terraformでapply complite!と言われても内部ではまだ処理を受け付けてくれていない可能性があります。
**しばらく待ちましょう。**
![24hours_later.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1227793/3a69ff88-a18c-a294-8b94-63d0a5b2b9fa.jpeg)

!!!**502 bad gateway**!!!

# 探したこと
まずはaws環境を見に行き、何かぱっと見で稼働していない部分などがないかを探しました。
すると**target groupがunhealthy**でした。
しかしec2はactiveですし他におかしな部分は見当たらない。
ググってみたところ、以下がよく解決策として挙げられました。
+ サーバのKeepAliveTimeoutがtarget groupのIdle Timeout 値よりも長くする
+ ALB, target groupのポート設定を正しいものにする(nginxなら80)
+ ヘルスチェックのディレクトリパスが正しくない

などなど。。。
特にnginxで80をリッスンしているのにターゲットグループのポートを443にしているケースが多くみられました。
しかしmattermostのポートは8065...ここのあたりはミスはなさそう。
ALBアクセスログも見に行きましたが、ここでも何かおかしな点はありませんでした。
ALBアクセスログの保存設定の仕方は以下の記事がわかりやすかったです
https://dev.classmethod.jp/articles/alb-log-to-s3/

# 結論: まさかのスクリプト落ち
沼っているところec2にアクセスしてディレクトリを見に行ったところ、、、スクリプトに書いたディレクトリが作成されてなかったりしました。なんじゃこりゃ。
もしやと思いサーバ内を色々探ってみた結果...スクリプトで書いたダウンロード系統が見つからなかったらしく、**処理がスキップされていました**。
お前！「terraform complite!」ゆうたやんけ！！！
**たとえスクリプトファイルでダウンロードが正常にできなくてもterraformは構築は完了したのでcompleteを返します。**
というわけで原因は自分が書いたスクリプトの問題でサーバ内部の問題でした。
**完全に灯台下暗し。**

# まずはありがちな部分から探そう
今回ハンズオン学習を除くとterraformで初めてaws基盤を構築しました。
初めて使ってエラーが出ると、未熟さを理解しているが故にまずはその新技術に対応する部分が問題になっているを思い込んでしまいました。
その結果terraformのコードを何度も読み返したりすることになり大変時間を浪費してしまいました。
**新技術でも、エラーが出た際にはまずありがちな部分から攻めるべき**ということを身をもって実感しました。
今回で言うと
1. ec2インスタンスはactiveか
2. インスタンス内部は問題ないか
3. target groupやALBの設定は適切か
4. その他基盤設定は問題ないか

と言った順序で攻めるべきでした。

target groupのunhealtyが第一発見だった事...見事に沼りました。
INNER JOINのINNERを省略したらどうなるか？

結論を言うと、`INNER JOIN`と`JOIN`は一緒です。
`INNER`は省略できるので、`JOIN`と宣言されているのは`INNER JOIN`と同じと思ってよいと思います。

https://babydaemons.hatenablog.com/entry/20080808/1218180516

## 省略はした方が良いのだろうか？
コード規約に沿って記載すべき、というのが結論ですが
こういうのを明示的に設定してない所もあるので、個人的な見解を記載します。

正直、手間をかけてもINNERは記述したほうが良いと思います。

### メソッドのjoinと合わさると可読性落ちる
言語によっては、joinというメソッドがあると思います。
SQLの文字列結合をする際に、JOIN句とjoinが重なることがあると思います。
区切りとして、結合のJOIN句で改行するというのは結構あるので、以下のようなちょっと面白い現象が起きます。
```
sql.join("join JAGI jagi on ....")
```

上記はネタですが、思ったよりプログラムの標準メソッドと予約語などが混ざると読みにくくなります。
極力標準で存在する名前と被るような記述は、やめておきましょう。

### JOINだけだと記述ミスなのか、想定挙動なのかパッと見分からない
JOINだけの記載があるとパッと見どちらなのか分からないことですね。
1. **本当はLEFT JOINだけど、書き忘れちゃった♡**
1. **INNER JOINを略しただけだよ♡**

少なくとも、レビューや調査の際にいちいち確認する必要が出ます。
記述ミスではなく、INNER JOINを略しただけか？と。

そんなことをするくらいなら、INNERをちゃんと記述するほうが結果的に楽できると思います。

## おまけ：JOIN句とカンマによる記述はどっちの方が見やすいか
### カンマによる記述
カンマによる羅列というのは、こういうやつです。
```
select * from tableA, tableB
where tableA.key1 = tableB.key1
and tableA.key2 = tableB.key2 
and tableA.column = 1
```

上記と下記は一緒の挙動をします。
### JOIN句による記載
```
select * from tableA
inner join tableB 
on tableA.key1 = tableB.key1
and tableA.key2 = tableB.key2 
where tableA.column = 1
```

### どちらの方が見やすいか？

どちらの方が見やすいかというと、圧倒的に後者です。
それはJOIN句をつけることで、下記が圧倒的に見やすくなります。
- テーブルが何を基準にしているか
- 外部結合か内部結合かがすぐわかる
- 結合のキーとなる項目（漏れがあるかもわかりやすい）
- 基準元テーブルを絞り込む抽出条件

今回は例として非常に簡単な文でしたが、これが3つ、4つのテーブル
WHERE句が複雑になってくると可読性が劇的に変わってきます。

同じ挙動をさせるのであれば
余程のことが無い限りは、JOIN句でSQLを記述するのがベストだと思います。
次にTerafformを組むなら

# 概要
業務でTerraformを組む機会があったため、
今回使いやすかったルール、次回terraformを組む際に適用したいルール
を備忘として記載する

### ディレクトリ構成
- 環境差分パラメータはすべてenv配下のvariables.tfで定義する
- 環境固有のリソースはenv配下に定義する（例：ec2_fumidai.tf）
- 各環境共通となるリソースはmodules配下に定義する
- 使い回すリソースはterraform　registry（すでに検証済みのモジュール）をコピペしてmodules配下に定義する
```
terraform/
    ├── docs/
    │   ├── naming.md
    │   └── doc.md
    ├── env/
    │   ├── dev/
    │   │   ├── main.tf
    │   │   ├── providers.tf
    │   │   ├── variables.tf
    │   │   ├── ec2_fumidai.tf //dev環境でのみ使用するリソース
    │   │   └── README.md
    │   └── stg/
    │       ├── main.tf
    │       ├── providers.tf
    │       ├── variables.tf
    │       └── README.md
    ├── modules/
    │   ├── main/
    │   │   ├── network.tf
    │   │   ├── elb.tf
    │   │   ├── acm.tf
    │   │   ├── ssm.tf
    │   │   ├── route53.tf
    │   │   ├── ecs.tf
    │   │   ├── ecr.tf
    │   │   ├── rds.tf
    │   │   ├── s3.tf
    │   │   ├── variables.tf
    │   │   ├── outputs.tf
    │   │   └── README.md
    │   └── moduleA/
    │       ├── main.tf
    │       ├── variables.tf
    │       ├── outputs.tf
    │       └── README.md
    ├── .gitignore
    └── README.md
```

### 命名規則
```
//各パーツの定義
resource "リソースタイプ" "ローカル名" {
  name      = リソース名

  tags = {
    Name    = リソース名
  }
}
```
- 全体ルール
    - 小文字を使用する
    - セパレータにアンダースコア（_）を使用する
    - AWSリソース名（nameやnameTag）はセパレータに（-）を使用する
- ローカル名
    - モジュール内で単一となるリソースは「main」で統一する
    - モジュール内に複数作成されるリソースは、直感的に意味のわかる名称とする
    - リソースタイプを繰り返さない
    - プロジェクト名、サービス名を使用しない
- リソース名
    - prefixを使用する
    - prefix-リソースタイプ形式で定義する
  
```sample.tf
locals {
    prefix = "${var.project}-${var.environment}"
}

resource "aws_route53_zone" "main" {
    name = "${local.prefix}-route53"
}

resource "aws_subnet" "private_1a" {
  tags = {
    Name    = "${local.prefix}-subnet-private-1a"
  }
}
```

### デフォルトタグ
リソースごとに定義するとtag付けが漏れるため、
デフォルトタグを指定する
```
provider "aws" {
  region = "ap-northeast-1"
  default_tags {
    tags = {
      env = "dev"
      project = "sample_project"
    }
  }
}
```

### variablesは型チェックし、使用するリソースごとにまとめる
変数は各所に散らばりやすいため、variables.tfで一元管理し、かつ使用する用途ごとにまとめて管理する
```
variable "ecs" {
    type = list(
        object({
            name = string
            cpu = number
            memory = number
        })
    )
}
```

### 参考ページ
https://dev.classmethod.jp/articles/terraform-bset-practice-jp/

https://registry.terraform.io/providers/hashicorp/aws/latest

https://dev.classmethod.jp/articles/terraform-aws-provider-default-tags/
Linux メール関連のログ

# 【Linux メール関連のログ】

## ログの違い

- maillog(`/var/log/maillog`)
  - メール送受信ログ。Postfixなど。
- messages(`/var/log/messages`)
  - システムメッセージ。OS全般のメッセージ
- secure(`/var/log/secure`)
  - セキュリティ関連。sshのログオン・ログオフやログイン失敗など。
- cron(`/var/log/cron`)
  - ジョブスケジューリング結果、ジョブの起動失敗ログなど。
【個人開発】IT系技術書の検索サイトを作りました

![スクリーンショット 2023-02-27 18.45.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30697/41070f81-5cae-01ba-dcee-d36e87f75d6c.png)


**「[Hotty技術書検索](https://book.hottydb.com/)」** というIT技術書に特化した検索サイトを作りました。

* サイトのURL

https://book.hottydb.com

* サイトの作り方

https://qiita.com/toru1055/items/a8444f128e880d8eaa6e

# はじめに
筆者は[HottyDB](https://www.hottydb.com/)という検索エンジンと推薦エンジンの機能を搭載した次世代型RDBMSを個人開発しています。
この度このHottyDBを紹介するために、HottyDBを利用したIT技術書の検索サイト「[Hotty技術書検索](https://book.hottydb.com/)」をリリースしました！

HottyDBを使えばこのような検索サイトが簡単に構築できるようになります。
近日中に、この「Hotty技術書検索」の作り方を詳しく解説したハンズオン形式の記事も投稿する予定ですので、そちらも是非お楽しみに！

# 主な機能
「Hotty技術書検索」の主な機能を３つ紹介します。

## キーワード検索機能
検索ボックスにキーワードを入力すれば、そのキーワードに関連する技術書の一覧を表示します。 
検索結果は機械学習によって最適なランキングで表示されるようになっています。
機械学習によるランキングを簡単に導入できるのもHottyDBの特徴です！

![スクリーンショット 2023-02-27 18.47.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30697/2fbfb2eb-9a00-0f82-1a66-7a6bf733b315.png)


## 関連書籍の機能
書籍を選択すると、その書籍のタイトルと類似した技術書を一覧で表示します。

![スクリーンショット 2023-02-27 18.48.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30697/aa439731-925a-ffb9-8c0f-fa5b73b24e4e.png)


## 「あなたにおすすめ」の機能
いくつかの書籍を閲覧すると、「あなたにおすすめ」の技術書を一覧で表示することができます。

![スクリーンショット 2023-02-27 18.48.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/30697/3c852c50-48aa-fb5d-79f8-666039ea71e3.png)


# 利用した技術
「Hotty技術書検索」で利用している技術は以下の通りです。

| 項目 | 利用技術 |
| --- | --- |
| フロントエンド |  Vue.js |
| バックエンド（API） | Spring Boot |
| データベース | HottyDB |
| 検索エンジン | HottyDB |
| 機械学習システム | HottyDB |
| ETLシステム | **なし**（データは全てHottyDBに入ってるのでETLが不要！） |

ご覧のとおり、ほとんどがHottyDBです！！
HottyDBを使えば、検索システムを構築するために新たに検索エンジンを構築したり、機械学習によるランキングをするためにETLのシステムを組む必要がなく、RDB内でこれらの処理が完結するのです！

# 動作環境
続いて現状「Hotty技術書検索」が動作している実行環境を紹介します。

| 項目 | 値 |
| --- | --- |
| サービス | [KAGOYA CLOUD VPS](https://www.kagoya.jp/cloud/vps/) |
| インスタンスタイプ | スタンダード | 
| CPU | 2コア |
| メモリ | 2 GB |
| 料金 | 660円 / 月（2023年2月26日時点） |

このスペックのインスタンス1つでSpring BootとHottyDB（データベース・検索エンジン・機械学習環境）の両方を動かしています。
なので、多少速度が遅くなることもあるかもしれませんが、その辺はマシンスペックの問題だと思ってください＞＜；

# 書籍データ
ちなみに書籍データは[楽天ブックス書籍検索API](https://webservice.rakuten.co.jp/documentation/books-book-search)を利用して抽出しています。

# 終わりに
最後まで記事を読んでいただきありがとうございます。

繰り返しになりますが、近日中にこの[「Hotty技術書検索」の作り方を詳しく解説したハンズオン形式の記事](https://qiita.com/toru1055/items/a8444f128e880d8eaa6e)も投稿する予定ですので、そちらも是非お楽しみにしてください。

その記事を読めば、例えば「Hotty小説検索」のような違うカテゴリのものでも簡単に作れるようになると思います！！

:::note info
「Hotty技術書検索」の作り方を詳しく解説したハンズオン形式の記事を公開しました！
- [検索システムの作り方（Spring Boot編）](https://qiita.com/toru1055/items/a8444f128e880d8eaa6e)
:::
WindowsPCを交換するときのメモ書き


ひねった内容でもないですが、備忘録として書いてみます。
PC移行前に忘れてたってことがないように貢献できたらいいなと思いますが、
数日後に忘れてたってことが出てくるんだろうな。。（追記出来たら追記します）
開発環境はそれぞれ異なると思うので参考程度に自分用のを書きました。。
そして、もっと楽な手順をコメントなどで教えていただけたら幸いです。

## 旧PCでやっておくこと

### ユーザ辞書のエクスポート
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256378/d020ef03-0de1-7621-7231-8abb78c7c3bb.png)
ユーザ辞書 > ツール > 一覧の出力 でテキストファイルを保存して、
新しいPCで > ツール > テキストファイルからの登録でインポートできます。

### 環境変数
    - レジストリエディタで以下の2つをregファイルとしてエクスポートしておく
        - HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment
        - HKEY_CURRENT_USER\Environment
        ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/256378/14089a97-eb5e-2307-01f1-453dd98c4006.png)
上記2つのパスでそれぞれ、画像のように右クリック → エクスポートでregファイルを保存し、保存したファイルを新しいPCに共有して、ダブルクリックすると環境変数を移行できます。

### Visual Studio Code
設定の同期を有効にしておけば、移行楽ちんです。
 - 参考記事
    https://qiita.com/Nuits/items/6204a6b0576b7a4e37ea

### gitでソース管理に含めていないファイルの移行
.envとか？

## その他新PCでやること
めちゃくちゃ人によると思いますが。。
要は環境構築

- gitインストール
インストール後、必要であればglobalユーザを設定しておきます
    ```
    git config --global user.name "Mona Lisa"
    ```
- Nodeインストール
- Pythonインストール
    - pyenv 
    - pipenv


こんな感じで、PC交換から1週間ほど経ちますが、とくに問題なく開発できています。
冒頭にも書かせていただきましたが、もっとよい方法などあればコメントいただければ幸いです。
WindowsマシンでインスペクターでiPhoneのデバッグの設定手順＋ログがWarningとCautionしか表示されない問題の対策

## 設定
[WindowsでiOSのSafariで開いたページをデバッグする | Web活](https://webkatu.com/posts/20200509-ios-safari-debug-on-windows/)
を参考に設定する。

一度設定した後は、手順６の
`remotedebug_ios_webkit_adapter --port=9000`
以降のみ実施でOK。

iOS１６以降は以下も必要そう。
[【iOS 16】iPhoneのデベロッパモードを有効にする方法2選](https://www.tenorshare.jp/ios-16/2-ways-to-turn-on-the-iphone-developer-mode.html#:~:text=%E6%89%8B%E9%A0%861%E3%80%81iCareFone%E7%94%BB%E9%9D%A2%E3%81%A7,%E3%81%9D%E3%82%8C%E3%82%92%E3%82%AA%E3%83%B3%E3%81%AB%E3%81%97%E3%81%BE%E3%81%99%E3%80%82)

## ログフィルター問題

ログにフィルターがかかってWarningとCautionしか表示されない問題が発生する。

## ログフィルター問題の対策

remotedebug-ios-webkit-adapterにバグがあるようです。
以下の修正を適用する。
[RemoteDebug/remotedebug-ios-webkit-adapter#192 (comment)](https://github.com/RemoteDebug/remotedebug-ios-webkit-adapter/issues/192#issuecomment-633062692)

自分の場合はファイルの場所は以下でした。
`C:\Users\【ユーザー名】\scoop\apps\nodejs\current\bin\node_modules\remotedebug-ios-webkit-adapter\out\protocols\ios\ios.js`
ファイル名をもとに勝手にフォルダ分けするGAS

<h1>使用方法</h1>

ファイル名を、パスのようにしておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953722/f0471cb2-25d6-900b-6f85-7e7f0d5dbd35.png)
すると、ファイル名で指定したフォルダに勝手に移動される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2953722/669f300b-301d-5f51-79b7-cee1fef1eb53.png)
(又、移動後にrenameする)

<h1>ソースコード</h1>
コピペして、fileManagement関数にトリガーをセットしてください。
トリガーの間隔はなんでもいいです。(私は1時間に一度にしています。)

```js
/**
 * ファイル名をもとに、特定のフォルダへそのファイルを移動する。
 * /test/test1/filename の場合、filenameという名前のファイルを、test>test1フォルダへ移動。
 * 振り分け後、ファイル名はpathではなくfilenameのみになる。
 * 注 : ルートフォルダのファイルにしか反応しない。
 * 注 : 同一フォルダ名で複数ある場合、後ろが優先。
 */

function fileManagement() {

  //最終更新が今日のファイルのみを対象にすることで、処理を軽くする。
  const today = Utilities.formatDate(new Date(),"JST","yyyy-MM-dd");
  const files = rootFolder.searchFiles(`modifiedDate >= "${today}"`);/**@type {DriveApp.FileIterator} */

  while(files.hasNext()){
    try{

      const file = files.next(); /**@type {DriveApp.File} */

      if(!file.getName().startsWith("/")) continue;

      //ファイル名を解析
      const fileInfo = file.getName().split("/"); //["",...path,filename]
      const filename = fileInfo[fileInfo.length-1]; /**@type {string} */
      const path = fileInfo.slice(1,fileInfo.length-1);

      // ファイル名でフォルダ指定がない場合、fileInfoは["",filename]
      if(!path.length) continue;

      //移動先の取得
      const directory = getDirectoryByPath(path);

      //移動
      file.moveTo(directory).setName(filename);

    }catch(e){

      console.log(e);

    }

  }
  
}


/**
 * @param {array} path [foldername1,foldername2,foldername3,...]
 */
function getDirectoryByPath(path){

  let directory;

  //対象フォルダの取得
  for(let i=0,l=path.length;i<l;i++){

    /**
     * @type {FolderMangerClass} directory
     */
    //初回はFolderManger.getFolder(),2回目以降はdirectory.getFolder()
    directory = (directory || FolderManager).getFolder(path[i]);

  }

  //directory: 
  //FolderMangerClass{
  //   currentFolder : DriveApp.Folder
  // } 
  return directory.currentFolder;/**@type {DriveApp.Folder} */

}


/**
 * 一度取得したフォルダを内部的にキャッシュすることで、パフォーマスの向上を期待
 */
class FolderManagerClass{

  /**
   * @param {DriveApp.Folder} 
   */
  constructor(currentFolder){

    this.currentFolder = currentFolder;
    return this;

  }

  /**
   * 指定のフォルダ名と一致するフォルダを取得。
   * @param {string} foldername
   * @return {FolderManagerClass} 同一ディレクトリに同一名のフォルダが複数ある場合、一番最後のフォルダを返す。
   */
  getFolder(foldername){

    //既に取得済みのフォルダはそのまま返す(処理の簡素化)
    if(this[foldername]) return this[foldername];

    //以降、新しく取得する際の処理際の処理
    
    //合致するフォルダの取得
    const folders = this.currentFolder.getFoldersByName(foldername);/**@type {DriveApp.FolderIterator} */
    let folder;
    while(folders.hasNext()) folder = folders.next();/**@type {DriveApp.Folder} */

    //内部的にキャッシュ => 次以降はガード節で引っかかる
    this[foldername] = new FolderManagerClass(folder);

    return this[foldername];

  }

}

const rootFolder = DriveApp.getRootFolder();
const FolderManager = new FolderManagerClass(rootFolder);



```
<h1>仕様</h1>

・ファイル名の先頭をスラッシュ(/)にしないと反応しません。
・同じフォルダの中に、同じ名前のフォルダが複数ある場合、一番後ろのフォルダが優先されます。
・ルートフォルダのファイルにしか反応しません。
・日付をyyyy/MM/ddで書くと、フォルダとして認識されてしまいます。
gRPCでバリデーションエラーを返す方法について

# 前置き
goやgRPCは最近書き始めたばかりなので、間違ったことが記載されている可能性があります。その場合はご指摘いただけると幸いです。

# gRPCのエラーの受け方について
バリデーションエラーはHTTPRequestの４００エラーで返したいですが、その場合はメタ情報にバリデーションエラーの内容を書く必要があります。BFFがJSあるいはBFFなしで直接繋いでいる場合はまだ公式パッケージにメタ情報からバリデーションエラーを引っこ抜く方法がないため、自分で処理を書く必要があります。

# 開発環境
### フロントエンド
- React
- @grpc/grpc-js

### バックエンド
- golang

# バックエンド

```
e := status.New(codes.FailedPrecondition, "メッセージ")
ed, err := e.WithDetails(
    &errdetails.BadRequest{
        FieldViolations: []*errdetails.BadRequest_FieldViolation{
            {
                Field:       "キー値1",
                Description: "バリデーションメッセージ",
            },
            {
                Field:       "キー値2",
                Description: "バリデーションメッセージ",
            },
        },
    },
)
if er != nil {
    return nil, e.Err()
}
return nil, ed.Err()
```

# フロントエンド

```
const detailsBinary = error.metadata['internalRepr'].get(
'grpc-status-details-bin'
)
detailsBinary?.map((err) => {
if (Buffer.isBuffer(err)) {
  const details = Status.deserializeBinary(new Uint8Array(err))
    .getDetailsList()
    .map((element) => {
      return unpackBadRequest(element)
    })
    return details[0]?.fieldViolationsList[0].description,
}})
```
テストコードを書くべき理由を改めてまとめてみる

## はじめに
最近コードを書いていく中でテストコードを書く機会が増えてきた。
テストの重要性は理解しているつもりだが、ときより面倒だなと思ったり、テストの必要性を考えることもあったりするので
改めてテストコードの重要性をまとめていく。

## テストコードが重要な理由
### バグの早期発見
テストコードを書くことにより、アプリケーションの各部分における問題やバグを早期に発見することができます。
これにより、開発者は修正に必要な時間を短縮し、高品質のアプリケーションを提供できるようになります。

### コードの品質向上
テストコードを書くことは、コードの品質を向上させるための良い方法。
テストコードによって、アプリケーションが意図した動作をするかどうかを確認でき、
コードの信頼性や保守性を高めることができる。

### リファクタリングの安全性向上
コードのリファクタリング時に、テストコードがあると安全に作業を進めることができる。
テストコードがない場合、リファクタリングがバグを引き起こす可能性があるが、
テストコードがあるとそのリスクを減らすことができる。

### コードのドキュメンテーション
テストコードは、コードのドキュメンテーションとしても機能する。
テストコードは、アプリケーションの期待される動作を説明することができる。
これにより、新しい開発者がアプリケーションを理解するのに役立つ。

### 開発の効率化
テストコードを書くことにより、開発プロセス全体の効率が向上する。
テストを自動化することで、手動でテストを実行する必要がなくなり、
開発者は時間を節約し、アプリケーションの開発を迅速に進めることができる。


## まとめ
わかってはいるものの改めて確認するとやっぱり必要なんだなと立ち返ることができる。
個人開発でもためてしまうと大変になるのでこまめに書いていくことを意識する。
【Laravel】依存性の注入（DI）とコンストラクタインジェクション

## はじめに
依存性の注入とコンストラクタインジェクションについて調べてみました。Laravelを使っています。

## 依存性の注入によって何が解決されるのか
デモ用にRegisterServiceクラスとUserクラスを用意しました。`RegisterService`クラスの`userInfoRegister`メソッドに登録情報を渡すと、Userクラスの`calcAge`メソッドが呼び出され、誕生日を元に年齢を計算する処理です。（内容は適当です）
=>これは`クラスが別クラスと依存関係にある`処理だと言えます。
```RegisterService.php & User.php
class RegisterService
{
    public function userInfoRegister($info) {
        $user = new User();
        $user->calcAge($info['birthday']);
    }
}

class User {
    public function calcAge($birthday) {
        // 誕生日から年齢を計算する処理
    }
}
```
上記はの`RegisterService`クラスは、`userInfoRegister`メソッドで`User`クラスのインスタンスを生成して利用しています。`User`クラスの動作には`RegisterService`が必ず必要になります。
=>つまり、依存しています。

次に`特定クラスとの依存関係を排除した`処理に書き換えます↓
```RegisterService.php
class RegisterService
{
    public function userInfoRegister(User $user, $info) {
        $user->calcAge($info['birthday']);
    }
}
```
このように記述することで、クラスやメソッド内で利用する機能を外部から渡すことができるようになります。これが`DI（依存性の注入）`と呼ばれるものです。
クラスの差し替えが必要になった場合でも、クラス同士が密接に依存しなくなったため、修正やテストが少なくなるメリットがあります。


## コンストラクタインジェクション
クラスのコンストラクタの引数でインスタンスを注入する方法は、`コンストラクタインジェクション`と呼ばれます。コンストラクタインジェクションでは、機能を渡されるクラスのコンストラクタの仮引数で、必要なクラスを`タイプヒンティング`で指定します。

 *タイプヒンティングとは、関数が引数を受け取る際の型宣言のことですね。
引数が何のオブジェクトやインターフェースなのか、またもや数値なのか配列なのかなどを指定することが出来ます。


```RegisterService.php
class RegisterService
{
    private $userRepository;

    public function __construct(UserRepository $userRepository)
    {
        $this->userRepository = $userRepository;
    }

    public function register($info)
    {
        $this->userRepository->create($info); 
    }
}
```
コンストラクタ仮引数の定義から、タイプヒンティングがクラス名やインターフェースであればその解決を行い、取得したインスタンスをコンストラクタメソッドの引数に渡します。
インターフェース名の場合は、解決方法がbindされている必要があります。

## おわりに
Laravelを使っていると当たり前に出てくるDIやコンストラクタインジェクションですが、何をやっているのかあまり分かっていませんでした。便利ですよね。
RHEL 固定IP 設定 備忘録

## ifcfgファイルを編集する
/etc/sysconfig/network-scripts

```config
TYPE=Ethernet
PROXY_METHOD=none
BROWSER_ONLY=no
BOOTPROTO=none
DEFROUTE=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_FAILURE_FATAL=no
NAME=enp0s3
UUID=9db6xxxx-exxx-xxxx-xxxx-xxxx333bxxxx
DEVICE=enp0s3
ONBOOT=yes
IPADDR=192.168.xx.xx
GATEWAY=192.168.xx.xx

```

BOOTPROTO:none
→デフォルトは[dhcp(Dynamic Host Configuration Protocol)]

IPV6INIT=no
→デフォルトは[yes] IPv6 を無効化

ONBOOT=yes
→システムの起動時にネットワークインタフェースが自動的にオンライン状態になる (動作する) 。

IPADDR=192.168.xx.xx
→IPアドレス

GATEWAY=192.168.xx.xx
→デフォルトゲートウェイ
【SwiftUI】数字の省略表記の仕方

# はじめに
以前も同じような記事を書きました。

https://qiita.com/SNQ-2001/items/297e9c09510e94686f4a

もっと簡単な方法を見つけたので記事にします。

https://twitter.com/frboulais/status/1629534292555583490?s=46&t=EWSUharycZkWyj_46NR0ig

自動でローカライズしてくれるのでかなり良いです。

# 実装
```swift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Text(100, format: .number.notation(.compactName))
            Text(1000, format: .number.notation(.compactName))
            Text(10000, format: .number.notation(.compactName))
            Text(100000, format: .number.notation(.compactName))
            Text(1000000, format: .number.notation(.compactName))
            Text(10000000, format: .number.notation(.compactName))
            Text(100000000, format: .number.notation(.compactName))
        }
    }
}
```

# 完成形
|英語|日本語|
|-|-|
|![simulator_screenshot_BDB0DC15-064E-43BC-9FC9-8F291E34873A.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/af320ced-37ba-958f-9e90-68a72c73a769.png)|![simulator_screenshot_1632DA19-85A2-4D6A-A9A1-E6A8761A36FC.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/5e749d9d-2995-a8a6-401b-73fe18bf97e1.png)|

# おわり
`Text`のフォーマットは全然知らないのでこれから勉強していきたいです
prisma チートシート (CLI)

# 概要

#### 前置き
**( ◜◡◝ )**
**prisma の CLI の汎用コマンドについてまとめるよ**
**prisma client のチートシートに関しては別記事で書くよ**


#### 要約
|  コマンド  |  説明  |
| ---- | ---- |
|  `npx prisma init`  |  prisma の初期設定を行う   |
|  `npx prisma migrate dev`  |  ローカル で schema をDBへ反映  |
|  `npx prisma migrate deploy`  |  商用、ステージングでschema をDBへ反映  |
|  `npx prisma db seed`  |  マスタデータの流し込み  |
|  `npx prisma generate`  |  prisma client の生成  |
|  `npx prisma studio`  |  GUI でデータを見る  |
|  `npx prisma format`  |  schema に format をかける  |
|  `npx prisma validate`  |  schema での error を確認  |
|  `npx prisma introspect`  |  既存DBから schema を生成  |
|  `npx prisma db pull`  |  DBの変更を schema へ反映  |
|  `npx prisma db push`  |  schema の変更を migration を生成せずにDBへ反映  |
|  `npx prisma version`  |  prisma のversion 情報を出力  |





# よく使うコマンド(詳細)

## init
**( ◜◡◝ ) < 必須機能**

:::note info
**init とは**
対象 app で prisma の利用を開始する
:::

- `npx prisma init`
→ プロジェクトに prisma を導入、必要ファイルを自動生成してくれる。



## migrate　 (まいぐれーと) 

**( ◜◡◝ ) < 必須機能**

:::note info
**migrate とは**
schema で定義したデータモデルをDBに反映させること
DDL 的なもの
:::

migration には
- `npx prisma migrate dev`
→ 開発環境で実行する。
→ prisma client の生成, seed の実行 まで一括して行われる。

- `npx prisma migrate deploy`
→ 本番環境, tes環境などで 事前に担保されたデータモデルの変更を適用する際に使用する。
→ 実行後,DB に変更が反映されるが別途 prisma client の生成が必要

の2種類ある。

:::note info
**Schema で表現できないSQLをmigration として管理したい場合**

`prisma migrate dev --name initial-migration --create-only`（`initial-migration` に任意のファイル名） 
→ 空 migration ファイルを作成し、任意のSQL をmigrationとして管理することが可能
:::


## seed (しーど)

**( ◜◡◝ ) < 割と使うよ**

:::note info
**seed とは**
seed.js で定義したマスタをDBへ流し込む
DML 的なもの
:::

- `npx prisma db seed`
→ seed.js での記述を元にマスタへデータを流し込む

## generate (じぇねれーと)
**( ◜◡◝ ) < 忘れがちだよ**

:::note info
**generate とは**
schema で定義したものを元に prisma client を生成する。
:::

- `npx prisma generate`
→ バックエンドサーバで DB へのアクセスするための prisma client の生成を行う。

## studio (すたじお)

**( ◜◡◝ ) < なくてもいいけど便利だよ**

- `npx prisma studio`
→ 実行することによって、GUI でDBの中身を閲覧、編集できる。
→ schema, client, DB 全て同期されていないとエラーが起きる。

# 覚えてたらいいコマンド

## format (ふぉーまっと)
**( ◜◡◝ ) < VS Code の拡張でいいかな**

`npx prisma format`
→ *schema.prisma* を format する

## validate (ばりでーと)
**( ◜◡◝ ) < VS Code の拡張でいいかな**

- `npx prisma validate`
→ *schema.prisma* を確認しエラーをログとして出力する。

## introspect (いんとろすぺくと)
**( ◜◡◝ ) < 途中からprisma を導入するなら便利かも**

- `npx prisma introspect`
→ 既存のDBから *schema.prisma* を**新規生成**する

## pull (ぷる)
**( ◜◡◝ ) < 個人的に使いたくない**

- `npx prisma db pull`
→ 既存のDBから *schema.prisma* を**更新**する

:::note warn
introspect は初回のみ実行でき、*schema.prisma* を新規生成する。
pull は *schema.prisma* を通さず 直接行われた DB の変更を *schema.prisma* に反映させる。
→ できる限り、直接DBを触らない方が管理しやすい。
:::

## push (ぷっしゅ)
**( ◜◡◝ ) < 意外と便利？**

- `npx prisma db push`
→ *schema.prisma* をもとに dbを更新する。（migration ファイルを生成せずに)

:::note warn
***migration ファイルを生成しないことのメリット***

ローカル環境で、データモデルのプロトタイピングをする際、 *schema.prisma* の version を更新せずにデータモデルの変更を試すことができる。
:::

## version (ばーじょん)
**( ◜◡◝ ) < それはそう**

- `npx prisma version --json`
→ prisma の version 情報諸々を json 形式で出力する。
Pythonのオンライン学習をいくつかやってみる（MS Learn、Exercism、openSAP）

なんとなくPythonをさわっていますが、PowerShellについては、無料で実施できるオンライントレーニングがいくつもあります。

今回は `Microsoft Learn` , `Exercism` , `openSAP` で提供されているPythonのコースを実施してみました。

記事執筆時点で、すべて完了までやった訳ではありませんが、Pythonの学習としてまとめてみます。

なお実施にあたっては、各サイトでユーザ登録が必要となります。

## Microsoft Learn

`Microsoft Learn`はマイクロソフトが提供している無料のオンライントレーニグプラットフォームです。

`Python` 以外にも豊富な学習リソースが揃っており、ラーニングパスを眺めているといくつか面白そうな物がみつかるかと思います。

[Microsoft Learn とは何ですか。](https://docs.microsoft.com/ja-jp/learn/support/faq?pivots=general#what-is-microsoft-learn)

[ラーニングパスをpythonで検索](https://docs.microsoft.com/ja-JP/learn/browse/?terms=python&resource_type=learning%20path)

まずは`Python`を学習するにあたって、自分は下記らコースを実施してみました。

- [Python の基礎を使って謎を解き明かし、答えを見つける](https://docs.microsoft.com/ja-jp/learn/paths/python-partnership/)
- [初心者向け Python](https://docs.microsoft.com/ja-jp/learn/paths/beginner-python/)
- [Python を使用して実際のアプリケーションを作成する](https://docs.microsoft.com/ja-jp/learn/paths/python-language/)

基礎編を体系だって学べるのはありがたいです。

### Exercism

[about Exercism](https://exercism.org/about)

Exercismはオープンソースのフリーコーディングプラットフォームで様々な言語の学習リソースが登録されています。

今回はその中のPythonを実施してみました。
ちなみにこの`Exercism`　様々な言語がありますが、そのなかにSAPのABAPコースもあります。

[Exercism - Python](https://exercism.org/tracks/python)

`Exercism`の`Python`コースについては、ブラウザ上のエディタでコーディングを行い、テストを通過させる形式となります。

また`exercism`コマンドを利用して、cliからローカル端末で記述したコードを回答から提出もできるようです。

### openSAP

[About openSAP](https://open.sap.com/pages/about)

openSAPはSAPが提供するオンライン学習リソースになります。

SAPが提供しているだけあって、SAP製品がメインとなりますが、何故かPythonの初級者向けコースがあります。

[Python for Beginners](https://open.sap.com/courses/python1)

この講座、`Course Characteristics`にあるように

コースは元々は期間が2022年4月5日から2022年6月1日までで、この期間に最終試験まで完了すると、`Digital Badge`がもらえたようですが、2022年6月1日以降は`self-pace`として各課題や動画を参照できるようです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1670622/b591d2d6-103e-ec85-654e-a370f2406d3d.png)

`MS Learn`のように日本語されているわけではなく、英語での動画講座だったり、問題だったりだいぶハードルは高いです。

動画字幕がついていますが、その字幕の中に日本語はありません。が、英語字幕を表示してブラウザの機能で日本語翻訳するとなんとなく理解はできる気はします。

## まとめ

`Python`は人気がある言語なだけあり、学習リソースについても有名な物がいくつもありました。

公式のドキュメント読みながら適当にさわっている`Python`ですが。
こういう学習リソースがあるのは、理解が深まる気がします。
HTMLでサイトを作ろう！ #1

# HTMLでサイトを作ろう！
どうも1998です。今回はHTMLを使って簡単な
ウェブサイトを作る方法をご紹介します。
まず、HTMLファイルを作りましょう。(今回は、VScodeを使用します)
```HTML:index.html
```
できましたか？まだ何も表示されてないと思います。
では、今からhtmlの文法をご紹介します。
```html:index.html
<h1>Hello World!!</h1>
```
まず、このように記述してみてください。
まず、h1というのは文字をh1の大きさで
表示するという意味を持っています。
そして矢印括弧で囲います。
このようなものを、タグと言います。
タグの形式には二つの種類があり、開始タグと
終了タグの二つがあります。
終了タグは、そのタグの名前の後ろに/(スラッシュ)を入れる
ことによってできます。
そして、開始タグと終了タグがそのタグの効果の範囲になります。
この場合では、
Hello World!!がh1の大きさで表示されます。
これで完成！と思いきや、HTMLとしては完成していません。
HTMLの骨組みを完成させましょう。
```html:index.html
<html>
<head>
<meta charset="UTF-8">
</head>
<body>
<h1>Hello World!!</h1>
</body>
</html>
```
このようになります。
各タグの意味を紹介していきます。
まずhtmlタグです。このタグの意味は、HTMLをこの中に記述します。
といった意味です。もちろん必須ですので、覚えておきましょう。
次は、headタグとbodyタグです。headの中にあるものは
表示されず、bodyの中にあるものは表示されます。
人間で例えるとheadが内臓などの器官、bodyが髪の毛や目などになります。
(変な例えですみません)
ですので、headタグには設定などを記述します。
```html
<meta charset="utf-8">
```
上記のコードは、htmlを普通に表示すると文字化けする可能性があるので
文字の形式を定義しています。これに関しては覚えなくて構いません。
僕もついこの間までコピペしてました。
次に、bodyタグには先ほども言ったように、表示する部分を記述します。
今回の場合は、
```html:index.html
<h1>Hello World!!</h1>
```
を記述します。
書いたhtmlを表示するには、htmlファイルを開くことによって
できます。また、LinuxやPowerShellのコマンドでする方法もあります。
表示されると、このようになります。![7BB322DE-2D33-4B21-98C2-8294F9E8D3F1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3139531/a2d41578-5abb-4597-fcfb-d0fd1c5151e4.png)


ちなみにVScodeというアプリケーションでは、予測変換機能があるので、
誤字をせずに記述が非常に楽になるのでおすすめです。
一回VScodeにするとやめられないぐらい便利です。
これで、サイトの作り方の説明は終わりです。お疲れ様でした。
PHP：オブジェクト指向：コンストラクタの短縮記法

オブジェクトのclassにおけるコンストラクタの短縮記法。
頻出するから楽になる。

```php
class Artist {
    function __construct(protected string $name) {
    }

    function getName() {
        return $this->name;
    }
}

```
paiza.ioでelixir その195

# 概要
paiza.ioでelixirやってみた。
練習問題やってみた。

# 練習問題
"' '"なら32を"64"なら64を返す関数を書け。

# サンプルコード

```

defmodule Main do
    def val(s) do
        if String.starts_with?(s, "'") do
            String.at(s, 1)
            |> String.to_charlist
            |> List.first
        else
            String.to_integer(s)
        end
    end
    def main do
        "' '"
        |> val
        |> IO.inspect
        "64"
        |> val
        |> IO.inspect
    end
end
Main.main



```

# 実行結果

```
32
64

```

# 成果物

https://paiza.io/projects/nc3HY6G4f9oexumnfspTcA


以上。
LPICレベル1(101)備忘録

## はじめに
今年度末にLPIC101試験を受験予定なので、備忘録として投稿します。
間違い等ありましたら、ご指導よろしくお願いします。

## 正規表現
抽象的な文字列パターン。検索対象の文字列をそのまま指定するのではなく、より抽象度の高い正規表現で検索対象を指定することができる。

- grep：テキストデータ内の文字列検索を行う。（正規表現が利用可能）
- ^a：行の先頭がa
- .*：任意の文字列の繰り返し
- a$：行の末尾がa
- .a[^b].a：2文字目および5文字目がa、3文字目がbではない
- grep -v ~:条件に合致しない文字列を検索する
- wc -l:grepの検索結果をカウントする
- pgrep:現在実行中のプロセスを調べて、プロセスIDを検索する
- pgrep -u root = pgrep -U 0:rootプロセスを検索する
- fgrep：正規表現を使用しない検索コマンド

## viエディタ
CUIのソフトウェアであるviエディタはファイルの編集・保存等のすべての操作をキーボードで行うことができる。

- ctrl + f:末尾に向かって１画面進める
- ctrl + b:末尾に向かって１画面戻る
- wp!,ZZ:編集内容を保存して終了する
- ls -l ~:ファイルのパーミッションを確認する
- !:viエディタにてコマンドラインモードになる
- i:カーソルの前に文字を挿入
- a:カーソルの後に文字を挿入
- o:カーソル行の下に行を追加してその先頭から文字を挿入
- I:カーソル行の先頭に文字を挿入
- A:カーソル業の末尾に文字を挿入
- O:カーソル行の上に行を追加してその先頭から文字を挿入
- x:カーソルの1文字を削除
- dd:カーソル行を削除
- ndd:カーソルからn行削除
- set -o vi:viモードに設定する
- set -o emacs:emacsモードに設定する
Uncaught SyntaxError: Illegal break statementエラーについて

## ソースコード
こちらがサンプルソースコードです。
```: index.html
<!DOCTYPE html>
<html lang="js">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>練習</title>
</head>
<body>
    <button type="button" id="btn" onclick=clickBtn()>練習</button>
    <p id="test"></p>
    <p id="test2"></p>
</body>
<script src="index.js"></script>
</html>
```

```:index.js
const btn = document.getElementById('btn')
const test = document.getElementById('test')
const test2 = document.getElementById('test2')
const clickBtn = () => {
    test.innerHTML = "1";
    break;
    test2.innerHTML = "2";    
}

```
エラー分はこちらです。
```
Uncaught SyntaxError: Illegal break statement
```

## 原因
breakは、for 文や、while 文などでしか使用できないためです。

## 解決策
breakの代わりにreturnを使う。
```:index.js
const btn = document.getElementById('btn')
const test = document.getElementById('test')
const test2 = document.getElementById('test2')
const clickBtn = () => {
    test.innerHTML = "1";
    return;
    test2.innerHTML = "2";    
}
```
こうすることで、画面に「1」が表示されるはずです。
以上になります。
"sudo" git clone? ちょっと待ったぁ！！

これで2時間くらい奪われたのでメモ()

間違いなどございましたら気兼ねなくおっしゃっていただければ幸いです！

## まとめ

`sudo`を付けて`git clone`をしてしまうと、
コマンド実行ユーザーでなくrootのユーザーとしてssh接続が実行されてしまうため注意！
（ssh接続に必要な秘密鍵もrootのユーザーのものが使われてしまいます！）

## 2時間前のぼく

「リポジトリクローンするよ」
```:実行コマンド
git clone [任意のリポジトリのパス(ssh)]
```
```:エラーメッセージ
fatal: could not create work tree dir '[任意のリポジトリの名前]': Permission denied
```
「Permission deniedってあったからsudoつけてcloneしたよ」
```:実行コマンド
sudo git clone [任意のリポジトリのパス(ssh)]
```
```:エラーメッセージ
git@github.com: Permission denied (publickey).
fatal: Could not read from remote repository.

Please make sure you have the correct access rights
and the repository exists.
```
「Permission denied (publickey)ってあったからsshのチェックしたよ」
```:実行コマンド
ssh -T git@github.com 
```
```:返ってきたメッセージ
Hi [ユーザー名]! You've successfully authenticated, but GitHub does not provide shell access. 
```
「あれ...sshは接続できてるな...なんでcloneできないの...」
↑`sudo git clone`でrootユーザーの秘密鍵を使ってssh接続しようとしてたからですね、ばーかばーか

## 解決法

下記のようなコマンドで一時的に権限を与え、
`git clone`(**sudoなし！**)をしてあげることでcloneできました！
（clone後、権限を元に戻すのを忘れないようにしてくださいね！）
```
sudo chown [ユーザー名] [cloneするディレクトリ]
sudo chmod 777 [cloneするディレクトリ]
```
Ubuntuで間違えてGUIを削除してしまった話

# 切っ掛け

pythonをバージョンアップしたらaptがエラーになるようになり、色々試した際に"sudo apt autoremove"したらPC再起動後にGUIが立ち上がらなくなりネットワークに繋がらずaptも出来なくなった。

# 状況確認

* GUIが立ち上がらない
* aptが実行できない
    * ネットワークに繋がっていない
* CUIからログインは出来る
* bootable USBメモリから起動すれば全て動作
    * 各種データは無事
    * インターネットに接続可能

# 復旧方法検討

* aptによる復旧
    * ネットに繋げないと何も出来ない
* Bootable USBメモリからOSを追加インストール
   * データが消える可能性があったので何度も試そうとしたが最後で断念
* NASにデータを全コピーしてバックアップ
    * Bootable USBからの起動ではファイルシステムの関係でコピー出来ないファイルがあり途中で断念

# 復旧手順

同時並行で色んな事を試しつつネットワークトラブルの原因を調査。

### nmcliコマンド
別PCからネットを調べてnmcliコマンド(NetworkManagerCLIentの略?)で情報収集可能と知る。
結果、deviceがunmanagedになっているのが問題らしいということを確認。

### Network Manager設定ファイル
検索結果のサイトに従い、以下のファイルがなかったので追加。
/etc/NetworkManager/conf.d/10-globally-managed-devices.conf
```
[keyfile]
unmanaged-devices=none
```
上記ファイル追加後に以下を実行したらネットワーク復旧。
aptが使えるようになりました。
```
$ sudo systemctl restart NetworkManager
```

以下の2つのサイトを参考にしました。

https://www.nemotos.net/?p=3123

https://tarufu.info/ubuntu_wired_unmanaged/

### apt実行

GUIをインストール
```
$ sudo apt install ubuntu-desktop
```

mozcが設定できない、そもそもTerminalが無い等、色々問題があるようなので色々確認。
以下を実行して解決。
```
$ sudo apt install unity-control-center
```
とりあえずここまで行ったらそこそこ使える状態に戻った。
GTM実装記録

### 概要

GTMの勉強記録。作業内容を箇条書きで記録。

### 詳細

### 導入

- wordpress
    - 「Local」を使用してサイト構築
        - lightning等プラグイン導入
    - Google タグマネージャー設定＞Google タグマネージャーのコンテナIDを設定→guiベースでgtmタグ埋め込み
- GTM
    - アカウント作成・コンテナ作成
        - タグ作成
            - ウェブストリームの測定id設定
        - トリガー作成
    - プレビューボタンからデバッグ
        - 問題ないことを確認しタグを公開
    - Tag Assistant を使用してタグを確認
    
### 実装例の詳細

#### UAで[内部リンククリックをカウントタグ](https://www.youtube.com/watch?v=ilo55QNdm5g&ab_channel=%E3%82%B8%E3%83%A5%E3%83%B3%E3%82%A4%E3%83%81%E3%81%AE%E3%80%90%E3%83%87%E3%82%B8%E3%83%9E%E7%A0%94%E7%A9%B6%E6%89%80%E3%80%91)を実装
- ↑の挙動をGA4の「リアルタイム」メニューでモニタリング
#### UAで外部リンククリックのカウントタグを実装
- プレビューでデバッグ
- Display Variables as  Names →Valuesを選択で値が確認できる
#### ボタンクリックの実装
- デベロッパーツールでボタン要素のClass名を調べる
- Click Classes を条件とするトリガーを実装
#### ページscrollの実装
- Scroll Depth Threshold をトリガーに設定

#### 画像表示の実装(event: "gtm.elementVisibility")
- トリガー：要素の表示
- [セレクタ：デベロッパーモードのCopy selectorで取得](https://anagrams.jp/blog/how-to-use-element-visibility-trigger-in-gtm/)
- 例：#post-212 > div > div.is-layout-flex.wp-container-3.wp-block-columns > div:nth-child(1) > figure > img

### 変数設定
#### パス+クエリを出力する変数の設定
- ルックアップテーブルと変数「クエリ」を使用

#### ウェブページタイトル
- 変数タイプ：javascript変数、グローバル変数名：document.title
- document.titleは、ページのロード中に自動的に設定される場合もあります。HTML文書の<head>要素内の<title>要素がある場合、ブラウザーはページを読み込む際に、この要素のテキストをdocument.titleプロパティに設定します。
- こんな感じでプレビューモードのvariablesに取得されている![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1347377/e99a004f-43ed-43f2-af48-fa37505cbce8.png)

#### リンクのパスをClick Elementから取得
- ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1347377/f176ef49-a97b-5b1d-8683-c3674636c661.png)

#### GA4→biqqueryへのエクスポート
- window.innerWidthの値によってデバイスタイプを判定していることが分かる
    - デバイスタイプ変更はf12→ctrl+shift+Mで左上のページの横幅をいじれば可能
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1347377/74682a54-e277-6bce-7a3f-3fb4fa6bbd7f.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1347377/bf199f6f-a784-1eee-9b74-cf8b409b6d61.png)


#### GA4→biqqueryへのエクスポート
- お金かかって止めるの忘れそうだったのでプロジェクト選択するところまで
#### コンテナ設定のエクスポート
- jsonはIDが漏れるのでプライベートリポジトリで保管
    

### 定義

- リンク
    - `<a>`タグで指定されたもの
- イベントタグ実装時の文脈
    - Page URL　どのURLにいるか
    - Click URL　どのURLがクリックされたか
    - 値　アクション当たりの値。１クリック時のクリック単価等

### 備考

- 変数命名規則の確認
    - 基本的にUpper Camel Case
        - EX.「hoge - fuga」「LinkClick - 内部リンクをクリック」
- 当たり前だが、移行期間に当たってはUA GA双方のタグを埋め込まなければいけない
- トリガーのタイプで「ページビュー」と「リンクをクリック」（系）が地味に間違いやすいので注意
- デバッグモード10、link_domain10とあるが、デバッグモード中でクリックされた外部ドメインが10でこのように表示される。デバッグモード中のカウントが排除されているわけではないので注意
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1347377/20ce9760-df46-4933-e8f3-9bb3749f191a.png)
- 仮説→計測タグの設定→設定方法の調査→プレビューモードでのデバッグ→公開→GA4のレポート＞リアルタイムでモニタリング
Gitコマンド集

ポートフォリオ作成のためにGitHubの使い方を再確認中なのですが、こんがらがってきたので少しまとめました。

* ユーザー名、メールアドレス、デフォルトブランチ名を確認
```
$ cat ~/.gitconfig
[user]
        name = 〇〇
        email = myemail@example.com
[init]
        defaultBranch = main
```

アッドの取り消し(追跡していない状態に戻す)
```
$ git rm --cached ファイル名
```

直前のコミットの取り消し
```
$ git reset --soft HEAD^
```

* リモート追跡ブランチの一覧
```
$ git branch -r
  origin/feature/202303/user
  origin/main
```

* git init の取り消し
git initしたディレクトリに対してそれを取り消す方法です。
このコマンドによりディレクトリがgit管理下から外れ、.gitフォルダも消えます。
```
$ rm -rf .git
```

### 参考サイト
* [【Git入門】ブランチ(branch)とは？メリットや使い方を解説！ | 侍エンジニアブログ](https://www.sejuku.net/blog/71071)
* [第1章 ゼロからデプロイまで - Railsチュートリアル](https://railstutorial.jp/chapters/beginning?version=7.0#sec-the_hello_application)
* [git init取り消し - Qiita](https://qiita.com/majihuwa_z/items/ec0d2e1ac21d68769693)
M5StackをarduinoIDEで使うためのセットアップ

# はじめに
M1ProのMacBookProを購入したことで今まで使っていたM5Stackの環境を再構築が必要になりました。その際つまずく場面があったので記録を残しておきます。

## 私の環境

- **パソコン :** MacBook Pro（14インチ、2021）
- **OS :** MacOS Monterey
- **CPU :** Apple M1 Pro
- **ArduinoIDEのバージョン :** 1.8.19
- **M5stackの種類 :** Basic

## 以下流れ

#### 1.インストール
[Arduinoのサイト](https://www.arduino.cc/en/software)からArduinoIDEをダウンロードしてください。UIが新しくなっているもの（2.0以降）とそれ以前のもの(Legacy IDE)の２つがあると思いますが私はLegacy IDEをインストールしました。
![スクリーンショット 2023-02-27 17.47.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2767749/b99c2218-8b92-40fe-c574-3126fc409e61.png)

#### 2.ボードマネージャーを追加

インストールしたらArduinoIDEを起動して
メニューから **Arduino　→　Preferences**の中にある**追加のボードマネージャーのURL**に
```
https://m5stack.oss-cn-shenzhen.aliyuncs.com/resource/arduino/package_m5stack_index.json
```
を追加します。追加したら「OK」ボタンを押してPreferenceを閉じてください。


#### 3.ボードマネージャーをインストール

メニューにある**ツール → ボードマネージャー**を選択します。右上の検索ボックスに「M5Stack」と入力し、**M5Stack by M5stack official**をインストールします。（画像はインストール済みの画面なので「インストール」ボタンを押してインストールしてください）
ここのインストールは時間がかかるので気長に待ちましょう。
![スクリーンショット 2023-02-27 18.30.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2767749/b4d26184-5c3e-bc47-f168-8487f57892f2.png)

#### 4.ライブラリーをインストール

メニューより**ツール → ライブラリを管理**を選択します。ボードマネージャーと同じく検索ボックスに「M5Stack」と入力し、**M5Stack by M5stack**をインストールします。他にもライブラリ入れてくださいとの表示が出るので「install all」を選択します。
![スクリーンショット 2023-02-27 18.43.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2767749/a44024f8-42a6-3433-65cd-70a74e7dd1ce.png)

#### 5.書き込み

M5StackとPCを繋いで書き込みを行います。

**ツール → ボード**から**M5Stack-Core-ESP32**を選択します。（M5Stackの種類によって変わるみたいです。Basicはこれでいけました）

シリアルポートに接続したポートを選択してください。

![スクリーンショット 2023-02-27 19.16.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2767749/d22e0189-806a-2b84-eea1-fb7daa8294f8.png)

メニューから**ファイル → スケッチ例 → M5Stack　→ Basic　→ Hello World**を選択してスケッチを開いてください。
![スクリーンショット 2023-02-27 19.34.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2767749/1aacc870-0898-c14c-c1d2-d3b768f3534a.png)

上の右矢印のアイコンをクリックして書き込みを行なってください。書き込みが完了するとM5Stackのディスプレイに「Hello World」と表示されていれば書き込み成功となります。

以上がセットアップとなります。お疲れ様でした。
効果検証：マッチング法とIPWについて

忙しい人向けの結論
-
・傾向スコアとは介入グループに割り振られる確率のこと
・マッチング法とは傾向スコアが似たもの同士をペアにして、効果検証を行う。ATTが推定される
・IPWとは平均をとる際に傾向スコアの逆数を重みとして利用しているもの。
・回帰分析、IPW、マッチング法で利用する分析方法で迷った際は全部使ってみる。

傾向スコアとは
-
・ある被験者が介入グループに割り振られる確率。

・介入変数を目的変数としたロジスティック回帰分析などで出力した確率がそのまま傾向スコアとなる。

・発想は介入グループと非介入グループで似た被験者を組み合わせていけば、外的な要因（バイアス）に左右されることなく介入の効果検証ができるというもの。傾向スコアがその似た度合いを示す。

・介入・非介入を決める際に何らかの基準や仕組みがあるとき、介入グループに入れられる確率（＝傾向スコア）が近いもの同士は性質も似ていると考える発想でもある。

傾向スコアが似たもの同士でペアにして分析する=傾向スコアマッチング法
-
・傾向スコアが近いもの同士は似た性質があると考え、その似たもの同士をペアにすることで、バイアスを減らして、効果検証しようとする発想に基づく方法。

・注意点としてマッチングしなかったデータは捨てられる。

・推定される効果はATT（Average Treatment effect on Treated）。ATTとは介入グループに選ばれた人たち(Z=1)が、もし介入が行われなかった場合の効果量と介入が行われた場合の差の平均。ここで、非介入グループに割り振られた人たちは考えてないので、そこは混同しないこと。P(X)は傾向スコア。Yは介入の効果量。

```math
\tau_{ATT} = \mathbb{E}(\mathbb{E}[Y|P(X),Z = 1] - \mathbb{E}[Y|P(X),Z = 0]|Z = 1)
```
ATE（Average Treatment effect）を推定することもできる。ATEは介入グループと非介入グループの差の平均。

IPW（逆確率重みづけ）
-
アイデアは介入に割り振られる個体は、元々効果が出やすい個体が割り振られ、非介入に割り振られる個体は効果が小さいまたは出にくい個体が割り振られているので、傾向スコアの逆数を使って、効果量の重みを調整するという発想。逆数を利用すると介入グループに割り振られる個体は傾向スコアが高いため、介入グループの効果量は低い倍率で補正され、非介入グループはその逆なので、非介入グループの効果量は高い倍率で補正される。これにより、セレクションバイアスを軽減し本来の効果量$Y^{(1)} - Y^{(0)}$を発見する手法。

マッチング法と回帰分析とIPWの比較
-
回帰もマッチング法もIPWも共変量によるバイアスを取り除いて分析するという発想である点は同じ。ただし、それぞれを特徴が違うので、以下は比較してメリット・デメリットとなるものを羅列したもの。

・回帰分析は共変量が必要だが、マッチング法やIPWは共変量がなくても分析できる

・マッチング法やIPWでは傾向スコアが良いものかどうか検討する必要がある。検討する方法は、マッチング後のデータで、共変量のASAM（標準化後平均差）を確認し、傾向が似ているか判断する。

・マッチング法ではマッチングしなかったデータを捨てているため、恣意的になりやすい（マッチングの基準を緩くしたり、キツくしたりすることで結果を操作できる）。

・IPWだと特にデータを捨てる必要もなく、全データで分析できる。

・回帰分析はモデリングが必要。２乗の項などが存在する場合、これを入れずに分析するとOVBが発生する。一方で、マッチング法やIPWはモデリングが必要ないので楽。

とにかく全部やってみるのが正解かも。

参考文献
-
効果検証入門〜正しい比較のための因果推論/計量経済学の基礎

https://www.amazon.co.jp/gp/product/4297111179/ref=ppx_yo_dt_b_asin_title_o01_s00?ie=UTF8&psc=1