OmniAICreator/Qiita-1.07M huggingface dataset:
「プログラマー脳」のchapter3「プログラミング言語の文法を素早く習得する方法」

# 目次
[1.初めに](#1-初めに)
[2.文法を覚えるためのテクニック](#2-文法を覚えるためのテクニック)
[3.長期記憶から情報を取り出す際に、貯蔵強度と検索強度の2つのメカニズムがある](#3-長期記憶から情報を取り出す際に、貯蔵強度と検索強度の2つのメカニズムがある)
[4.ただ情報を見るだけでは不十分](#4-ただ情報を見るだけでは不十分)
[5.能動的に考えることで記憶を強化](#5-能動的に考えることで記憶を強化)
[6.【プログラマー脳】Chapter](#6-プログラマー脳chapter)


# 1. 初めに
「プログラマー脳」という本を読んでいます。
その中で印象に残ったことや大事だなと思う部分をまとめています。
自分の理解の必要に応じて自分が慣れているJavaScriptで処理を書いています。

# 2. 文法を覚えるためのテクニック
- フラッシュカードを使って文法を素早く覚える
- 忘れ物を防ぐ
- 想起練習(積極的に何かを思い出そうとする)
- 推敲(新しい知識を既存の知識と積極的に結びつける)

長期記憶の仕組み
- 脳の中の記憶は階層構造になっておらず、ネットワーク構造で構成されている
- 勉強時間を増やすよりも期間を徐々に開けながら、長い期間で繰り返し行うことで長期記憶に組み込まれる

# 3. 長期記憶から情報を取り出す際に、貯蔵強度と検索強度の2つのメカニズムがある
- **貯蔵強度**
    - 長期記憶にどれだけきちんと保持されているかを示す
    - 勉強すればするほど、その記憶は強くなって忘れることがなくなる
    - 例: 3×4=12(すぐに思い出せるため貯蔵強度が高い)
- **検索強度**
    - 特定の何かを思い出すのがいかに簡単かを示す
    - JavaScriptのfillter関数の文法など、知っているはずなのになかなか思い出せない、思い出したらなぜ思い出せなかったのか不思議に思うような場合は検索強度が低いと言えます

貯蔵強度は増加する一方で、年月が経つにつれて検索強度は低下していく

- ある情報を繰り返し学習することでその情報の貯蔵強度は強化される
- 自分が知っている事実を繰り返し思い出そうとすると、特に勉強しなくても、検索強度は向上する

【個人的な感想】コードを速読する中で検索強度を意識する方がチャンク化してコードを読むことができそう

# 4. ただ情報を見るだけでは不十分
リストの処理を1つ1つ処理をするコードの6つの選択肢がある場合に正しい選択肢を見つけることは困難です。答えを知ると当たり前のように感じます。

例: 下記の選択肢の中で0のみを含む配列が返ってくる選択肢を選びなさい(JavaScriptのfiltterメソッド)

```typescript
1.[0,1,2,3,4,5].filter(item => !item)
2.[0,1,2,3,4,5].filter(item => item > 3)
3.[0,1,2,3,4,5].filter(item => item / 2 === 0)
4.[0,1,2,3,4,5].filter(item => item / 2 !== 0)
5.[0,1,2,3,4,5].filter(item => item < 3)
6.[0,1,2,3,4,5].filter(item => item < 2)
```


答えは1です

知識が長期記憶にしっかり保存されているか(貯蔵強度)ではなく、それを見つけることの容易さ(検索強度)が必要になりました

長期記憶に情報を保存するだけでは不十分であり、その情報も簡単に取り出せるようにする必要があることがわかりました。

【個人的な感想】インプット以上にアウトプットの速度が重要なのかもしれない(積極的にアウトプットすることの重要性)


# 5. 能動的に考えることで記憶を強化
学んだばかりのことを考えるプロセスのことを精緻化と呼ぶ。

精緻化とは、覚えたいことを考え、それを既存の記憶と関連づけ、新しい記憶を長期記憶にすでに保存されているスキーマに適合させることをいう

例:下記の数字を覚える際に、二進数表現に変換すると1のみで構成される数字という分類に当てはめることで容易に覚えられる

「1,3,15,127,63,31」

スキーマ : ネットワーク構造の脳内で、他の記憶や事実との関係性を持った内容が頭の中で整理されたもの

新しい情報をより多く記憶したい場合は、その情報を明示的に精緻化していくことが有効になる

---

文法を調べることで作業の妨げにならないように文法を多く記憶しておくことが大切です。

私たちはプログラミングの文法を頭で記憶しているかを気にしていない
なぜなら、それらの情報をインターネットで調べることができるから

しかし、何を記憶しているかはコードをどれだけ効率的に処理することができるかに影響することをchapter2で知りました。

従って、プログラミング言語の文法や概念、データ構造を記憶することで、コードを処理する速度を上げることができます。→ より多くのコードをチャンク化することができる

# 6. 【プログラマー脳】Chapter

[「プログラマー脳」のchapter1「コーディング中の混乱を紐解く」](https://qiita.com/kosuke-17/items/b64f9450ebbd99b274d5)
[「プログラマー脳」のchapter2「コードを速読する」](https://qiita.com/kosuke-17/items/645babd7445203f4734a)
Now →[「プログラマー脳」のchapter3「プログラミング言語の文法を素早く習得する方法」](https://qiita.com/kosuke-17/items/67220ced21104ddda933)
[「プログラマー脳」のchapter4「複雑なコードの読み方」](https://qiita.com/kosuke-17/items/4b1348afe3ba74d6d4de)
[「プログラマー脳」のchapter5「コードの深い理解に到達する」](https://qiita.com/kosuke-17/items/77794aa78c9b8d51a1aa)
【TODO】「プログラマー脳」のchapter6「プログラミングに関する問題をよりうまく解決するには」
【TODO】「プログラマー脳」のchapter7「思考に潜むバグ」
【TODO】「プログラマー脳」のchapter8「より良い命名を行う方法」
[「プログラマー脳」のchapter9「汚いコードとそれによる認知的負荷を避けるための2つのフレームワーク」](https://qiita.com/kosuke-17/items/e5750ba01fc742a3b142)
【TODO】「プログラマー脳」のchapter10「複雑な問題をより上手に解決するために」
【TODO】「プログラマー脳」のchapter11「コードを書くという行為」
【TODO】「プログラマー脳」のchapter12「より大きなシステムの設計と改善」
【TODO】「プログラマー脳」のchapter13「新しい開発者のオンボーディング」
ポリシーのattach起因でリソース作成できない場合のTips

(覚書的な内容になります)

# 経緯
小さいシステムを構築してまして、IaC部分にTerraformを使用しています。
ある時、ロール作成とポリシーのアタッチ、リソース作成を一気にやろうとすると、以下のようなエラーが発生しました。
```
InvalidInputException: Service is unable to assume provided role. Please verify role's TrustPolicy
(以下エラー箇所のリソース情報が続く)
```

その時に記載していたTerraformが以下のような形です。
(中身は割とボカしてます)
```
# ロール作成
resource "aws_iam_role" "test-role" {
  name               = "test-role"
  assume_role_policy = file("./assume_role_policy.json") # 何らかのassumeロール設定が記載されているjson
}
resource "aws_iam_policy" "test-policy" {
  name        = "test-policy"
  description = "test policy"
  policy      = file("./policy.json") # 何らかのポリシー設定が記載されているjson
}
resource "aws_iam_role_policy_attachment" "attachment-policy" {
  role       = aws_iam_role.test-role.name
  policy_arn = aws_iam_policy.test-policy.arn
}

# 何かしらのリソース作成
resource "aws_lambda_function" "test-lambda" {
  role = aws_iam_role.test-role.arn
  depends_on = [aws_iam_role_policy_attachment.attachment-policy]
}
```

エラーの内容を見るとロールを受け取ることができないっていっているので、何となくロール周り(ポリシーかassumeポリシー)の設定が怪しそうだなぁということが分かります。
が、ロール周りの設定見直してみても特に違和感はなく、試しに再度Terraform applyすると問題なく通ることがありました。

ディレクトリ分けて別々にapplyするのも解決手段としてはありなのですが、出来るだけ1度のapplyで通るようにした方が楽なので何かいい方法はないかなぁと調べてみました。

# 原因
おそらく以下の理由からうまくいかないのかと思われました。
・policyのattachは多少時間がかかること
・aws_iam_role_policy_attachmentを後続リソース作成時のdepends_onに設定しても、policyのattach開始が終了したことをトリガーにしていてattachが完了したことを保証してくれているわけではないこと

ロール作成、リソース作成を別々で時間を置いてapplyをすると問題なく通るので、depends_on設定だけでは待ち時間が不十分なことが分かります。

# 対応
リソースの作成を任意の待ち時間待つことが出来ればいいわけなので、`time_sleep`リソースというものを活用しました。
https://registry.terraform.io/providers/hashicorp/time/latest/docs/resources/sleep

これによって多少待つことにはなりますが一気にapplyできるようになりました。

```
# ロール作成
resource "aws_iam_role" "test-role" {
  name               = "test-role"
  assume_role_policy = file("./assume_role_policy.json")
}
resource "aws_iam_policy" "test-policy" {
  name        = "test-policy"
  description = "test policy"
  policy      = file("./policy.json")
}
resource "aws_iam_role_policy_attachment" "attachment-policy" {
  role       = aws_iam_role.test-role.name
  policy_arn = aws_iam_policy.test-policy.arn
}

# ここ追加
resource "time_sleep" "wait-policy-attachment" {
  create_duration = "10s"
  depends_on = [aws_iam_role_policy_attachment.attachment-policy]
}

# 何かしらのリソース作成
resource "aws_lambda_function" "test-lambda" {
  role = aws_iam_role.test-role.arn
  depends_on = [time_sleep.wait-policy-attachment] # ここ変更
}
```

# 終わりに
ロール作成とリソース作成を同時にやろうとしてコケてしまう時はこのような対応方法も検討していただければと。
Chatgpt Rebornのエラー429トラブルシュート（＋ChatGPT Plusと、Open AI APIへの課金が実は別だった件）

※2023/4/5 ChatGPT PlusのFAQに情報記載されている旨、追記しました。
※2023/4/5 エラーの原因について、追記しました。

# Chatgpt Rebornのエラー429

VSCode のプラグインChatgpt Rebornを利用していたら、特段設定変更などはしていないのですが、突然以下の`429 Too Many Requests Request failed with status code 429`エラーで利用できなくなってしまいました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/01a9ff86-bc21-9664-3829-9afc7aa88ddd.png)

vscode-chatgptからChatGPT Rebornへの影響を疑って、プラグインの再インストール・各種設定を見直したり、APIキーを再発行したりしたのですが、解決せず。

# ChatGPT Plusと、Open AI APIへの課金が実は別だった

ChatGPT Plusに課金しているのにこの扱いは酷いでは？と思ってOpen AIアカウントのAPIキーの並びにある課金情報を確認したところ、`Free trial`となってました…

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/a9c131e6-aa44-6277-d638-64b51d804cc1.png)


ChatGPT Plusにはちゃんと課金できてることを確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/05740901-d2de-c173-656a-7af7b16627ee.png)

Open AIのアカウントページから各種参考資料を確認したところ、[Pricing](https://openai.com/pricing)のページに行きつくわけですが、DALL·Eも含まれていたりで、ChatGPTとは別のサービス・支払い体系というオチでした…

# Open AI APIへの課金設定

`Set up paid　account`から課金情報を登録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/3a20de79-5b80-0ee9-7d88-ff8659af2be8.png)

Open AI APIは従量課金なので、`Usage limits`から上限を設定します。
`Hard limit`で月ごとの上限値ですので、ChatGPT Plusと同じ値段にしました。
`Soft limit`はメール通知の閾値なので、上記の半分に。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/9f40a266-a90c-67c4-e2bf-0186531470f3.png)

# 動作確認など

設定後、Chatgpt Rebornからプロンプロトを投げるも再度429エラー。
一度、`ChatGPT:Clear conversation`を実行することで、再度利用できるようになりました。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2459468/c9386ce3-38b1-57cb-2331-2f029204e752.png)





# 【2023/4/5追記】 ChatGPT PlusのFAQ
ChatGPT PlusのFAQにChatGPT PlusとAPIは別サブスクリプションである旨、記載されていることを確認しました。

```
13．Is the ChatGPT API included in the ChatGPT Plus subscription?

No, the ChatGPT API and ChatGPT Plus subscription are billed separately.
The API has its own pricing, which can be found at https://openai.com/pricing.
The ChatGPT Plus subscription covers usage on chat.openai.com only and costs $20/month.
```

# 【2023/4/5追記】 429 Too Many Requests Requestの原因
~~根本原因までは追えてませんが、取り急ぎ復旧出来てよかった＋同様事象で困っている人向けに。~~

同様の事象で困っている質問を見つけました。
APIの支払い設定をしないまま、無料分を使い切ってしまうと発生するエラーのようです。

https://qiita.com/HANAMU/questions/9c58f20e61a6a11fff37



# 参考
https://openai.com/pricing


https://help.openai.com/en/articles/6950777-chatgpt-plus

https://qiita.com/HANAMU/questions/9c58f20e61a6a11fff37
youtubeサイトでお気に入り動画リストを作成・再生するプラグインを作成しました。


# 概要
このプラグインは、youtube動画の再生リストを作りますが、youtube公式の再生リストとは形式が異なるオリジナルの再生リストです。簡単に作れて、連続自動再生することができます。
また、不要になった動画も簡単にリストから削除することができますので、メンテナンスも楽にできます。リストは利用者毎に複数作成できます。また、ジャンルも複数作成できます。まだ、現在は作成したリストは本人のみに公開していますので、他の利用者には表示されません。

# 再生リスト画面(右端のマイリスト)
![screen1280.png](https://blog-tool.tecoyan.net/images/screen1280.png)
このような画面が表示されます。このページはyoutubeの公式再生ページです。その画面の右側にこのプラグインが再生リスト(マイリスト)を表示しています。このリストはオリジナルの形式で、youtubeの公式形式とは異なります。
リストのサムネイルをクリックすると再生がスタートします。
再生が終了するとリストの次の動画の再生が始まります。リストの最後の再生が終了すると先頭に戻り、連続して再生が始まります。

#　不要動画の削除
不要になった動画を削除するには、サムネイル上でAltキーを押し、マウスのクリックを押すだけです。
# デモサイト
事前に、youtubeプラグイン v4.0をインストールしておいてください。
[再生リスト画面](https://www.youtube.com/watch?v=eQwj0oPQQvg)

# 使い方
まず、先にchromeウェブストアからyoutubeプラグイン v4.0をChromeブラウザにインストールしておきます。次に、youtubeサイト(https://www.youtube.com/watch?v=...)
でお好みの動画を再生します。再生中に、Ctrlキー+マウスをクリックしてポップアップ画面を表示します。保存ボタンと再生ボタンがありますので、保存ボタンをクリックすると専用のサーバへリストを保存します。再生ボタンをクリックすると再生リストを表示します。リストの中のサムネイルをクリックすると再生がスタートします。詳細については、以降に示します。

# プラグインの特長
「youtubeプラグイン v4.0」は公式のyoutube再生ページ(URLは、例: https://www.youtube.com/watch?v=eQwj0oPQQvg です。)で動作します。
リストの作成と再生が同じページで出来ますので操作が簡単です。それが唯一の特長です。
また、保存ボタンをクリックすれば、再生中の動画をご自分のリストへ追加保存しますので、簡単に再生リストを作れます。
主な機能は以下になります。
・youtube再生ページで再生中の動画を保存ボタンでリストに追加できます。
・同じ動画は追加保存しません。
・リストの不要動画はAltキー+マウスClickで削除できます。
・リストは専用サーバに保存されます。
・リストはユーザー毎にひとつになります。
・リストは本人のみに表示され、他の人には公開されません。
・広告はスキップボタンが表示されたときにクリックして指定の動画を再生します。
・再生中のリストのインデックスを表示します。
・再生中の動画のリスト内タイトルは赤色表示し、リストの先頭へスクロールします。
・youtube再生サイトの公式ページですが、このプラグインにより、あたかも自分用のページのような見え方をします。マイ・リストが公式サイトの関連リストの上に表示されます。関連リストを見る場合は、マイ・リストを脇にドラッグすれば見ることができます。
・動画の登録は関連動画(公式リスト)の動画の中から選択して再生し、保存すると簡単に登録できます。
・一秒で登録し、一秒で再生できることがメリットです。


# あとがき
このプラグインはyoutube再生ページ単独で再生リストを作成し、再生もしますので、ワンストップで解決します。
他のタブと連携はしません。ただし、このプラグインには、すでに公開済みの「yyプラグインプラス」の機能も包含していますので、その機能も動作します。
簡単に再生リストがつくれ、再生もできますので、お試しください。
(追記)
近いうちに、シリーズ対応をしたバージョンを出したいと思っています。このシリーズとは、「....」シリーズというように好きなジャンルに登録できるものです。どんなジャンルでもいいようにする予定です。お待ちください。
初めて社外のフロントエンド勉強会に参加してみた

# 概要

先日、社外での勉強会に初めて参加した際に出てきた技術・用語で知らなかったものを調査し、まとめてみます。

参加したのは、株式会社Another worksさん、株式会社HRBrainさんが共催する[Front-end Meetup 2023](https://anotherworks.connpass.com/event/276673/)に参加しました。
オンラインで参加したため、私は発表してないですが、色々と身になることがありました。

# 参加して良かった点

- 知らなかったorあやふやだった技術・用語が見つかる
- 他社の開発への取り組みや考え方を知れる
- モチベアップ


## Vertical Saas

Verticalは「垂直」という意味を持っており、Vertical Saasは特定業界に対して垂直方向に深い価値を持つSaaSを指します。
その業界特有の問題を解決することを目的としており、それに向けた機能が開発・提供されます。



業界の例としては、「教育」「医療」「EC」などが挙げられます。
[バーティカルSaaS カオスマップ2022](https://onecapital.jp/perspectives/vertical-landscape-2022)

一方で、さまざまな業界で水平方向に広く利用できるSaasという意味のHorizontal SaaSも存在しており
例として「メール」「Web会議」「会計」などが挙げられ、業界ではなく特定の「業務」に特化しています。


## DnD
Drag And Dropのこと。
実装することで、要素をDrag And Dropで移動させることができるようになります。

![画面収録-2023-04-01-14.31.13.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/55122d9d-a6ea-c10f-041c-35d674d8108f.gif)


DnDの実装に利用できる代表的なライブラリとして、以下のものがあります。

### react-beautiful-dnd

https://github.com/atlassian/react-beautiful-dnd

atlassian社製のDnDライブラリ。現在は、他の優先事項に集中しており、さらなる機能開発や改良の予定はないようです。

この記事によると、React18では`--legacy-peer-deps`しないとインストールできないようです。

https://zenn.dev/takuty/articles/2e375cb349bfc4


### react-dnd

https://github.com/react-dnd/react-dnd

> React DnDは、コンポーネントの結合を解除したまま複雑なドラッグ＆ドロップインターフェースを構築するためのReactユーティリティのセットです。TrelloやStorifyのように、ドラッグ操作によってアプリケーションの異なる部分間でデータを転送し、コンポーネントがドラッグ＆ドロップのイベントに応じて外観やアプリケーションの状態を変化させるようなアプリケーションに最適なものです。


### dnd-kit

https://dndkit.com/

初回のリリースが2021/1/2であり、３つの中で最も歴史の新しいライブラリです。
直近では2023/2に更新されており、メンテナンスの不安もなさそうです。

> フックを使って、数行のコードでコンポーネントをドラッグ可能な要素やドロップ可能な領域にすることができる。ドラッグ＆ドロップ可能なコンポーネントの動作を、あらゆる角度からコントロールできます。


npm trendsにで調べてみると、react-beautiful-dndとreact-dndが優勢のようですね。
react-beautiful-dndのメンテナンスが停止していることを考慮すると、今後はreact-dndを使用するのがよさそうです。
<img width=600 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2475547/f6235e63-1dd5-3b20-7f5f-6281912e7958.png">


## Tokenize

文章を何らかののルールに従ってtoken単位に分割すること。

簡単な例を挙げると、

1+1=2
を
["1", "+", "1", "=", "2"]
に分割したり

I am a student.
を
["I", "am", "a", "student", "."]
に分割することです。

以下の記事ではBERTというGoogleが2018年末に発表した自然言語処理モデルによるtokenizeについて書かれています。

https://zenn.dev/robes/articles/b6708032855a9c


## Chromatic

https://www.chromatic.com/

> Chromaticは、Storybookのクラウドベースのツールチェーンで、チームがUIコンポーネントをより速く出荷できるようにするものです。Storybookの開発チームによって作られました。

Chromaticを使用することにより以下のような利点があります。

- 共有ワークスペースの提供
- コンポーネントの視覚的なリグレッションをテストする
- プルリクエストにより影響を受けるコンポーネントのUI上の変更を比較できる
- CIとバージョン管理でコンポーネントライブラリを自動化できる

詳しくは[こちら](https://www.chromatic.com/docs/)。


# まとめ
一度の参加（しかも見るだけ）でこれだけ知らなかった技術・用語を発見できました。
参加→調査を繰り返すことで、「業務でこういう機能を実現したいが、前に聞いたあの技術がつかえるかも」といった足がかりになります。
また、勉強会の雰囲気も知れるので、「勉強会って自分が参加していいんだろうか・・・なんか怖そう・・・」
と思う方はまずはオンライン参加してみるといいかもしれません！
paiza.ioでpython その6

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

# 練習問題
dbpediaをsparqlで叩け。

# サンプルコード

```
# coding: utf-8

import json
import urllib.request

url = 'https://ja.dbpedia.org/sparql'
data = {
    "query": "SELECT DISTINCT * WHERE {<http://ja.dbpedia.org/resource/東京都> ?p ?o . } LIMIT 10"
}
headers = {
    'Accept': 'application/sparql-results+json',
    'Content-Type': 'application/x-www-form-urlencoded'
}
req = urllib.request.Request(url=url, data=urllib.parse.urlencode(data).encode('ascii'), headers=headers, method='POST')
with urllib.request.urlopen(req) as res:
    body = res.read()
print (body.decode('UTF-8'))




```

# 実行結果

```
{ "head": { "link": [], "vars": ["p", "o"] }, "results": { "distinct": false, "ordered": true, "bindings": [ { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://www.w3.org/2002/07/owl#Thing" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://www.w3.org/2003/01/geo/wgs84_pos#SpatialThing" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://dbpedia.org/ontology/AdministrativeRegion" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://dbpedia.org/ontology/Region" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://schema.org/AdministrativeArea" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://www.wikidata.org/entity/Q3455524" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://schema.org/Place" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://dbpedia.org/ontology/Location" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://dbpedia.org/ontology/Place" }}, { "p": { "type": "uri", "value": "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" } , "o": { "type": "uri", "value": "http://dbpedia.org/ontology/PopulatedPlace" }} ] } }
```

# 成果物

https://paiza.io/projects/bA1GaQho99tgxWPpxsnawA


以上。
Arduino UnoのVS1053シールドで、MP3再生し遊んでみた

　劣化(w)WAVファイルプレーヤーが作れたのに気を良くしていたところ見つけました。その安さについアマゾンで
「Arduino用 VS1053(B) TFCard Stereo Audio MP3デコード開発ボード」
![vs1053.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3189926/f8d2c4fe-55c1-856f-61e7-d61085e81a0d.jpeg)
なるものを購入してしまいました。しかし活用しようにもいかんせん古い物なので、もうあまり情報も少なくちょっと苦労しました。

https://blog.goo.ne.jp/sirius506/e/8ec0d08b6774ee3eaf7bab0d868e0cec

とか

https://nuneno.cocolog-nifty.com/blog/2019/01/vs1053-mp3-78f3.html

は見つけましたが、実際にArduinoで使えるソースコードがなく、やっと見つけたのが

https://github.com/mpflaga/Arduino_Library-vs1053_for_SdFat/tree/master/examples

でした。ArduinoIDEでも"Adafruite VS1053 Library"と"VS1053 for use with SdFat"をインストールしました。後者が上記のgithubのもののようです。前者のexampleも使えましたが、結局、機能が多い後者のexample中の"demo.ino"に落ち着きました。(fileplayer.inoはコンパイルが通りませんでした)
　そのままでは面白くないので、自分なりのアレンジをしようと考えましたが、既になかなか機能豊富で私などに付け加えられるものも無い完成度。そのうち、0～9までのトラックしか再生できないことにふと気が付きました。要するにシリアル通信で一文字しか送信できないというか、一文字しか受け取らないからですね。そこで、"Serial.readString()"を使い10番以降のトラックも再生できるように改造しました。ソースを示しますが、長くなるので"loop"のところだけにします。改造は最小限にしたかったので、少し工夫し"loop"内の変更に留めてます。
```
void loop() {

// Below is only needed if not interrupt driven. Safe to remove if not using.---
#if defined(USE_MP3_REFILL_MEANS) \
  && ((USE_MP3_REFILL_MEANS == USE_MP3_SimpleTimer) \
      || (USE_MP3_REFILL_MEANS == USE_MP3_Polled))

  MP3player.available();
#endif
  // -----------------------------------------------------------------------------

  if (Serial.available()) {
    String inStr = Serial.readString();　 // 文字列を受け取る
    Serial.println(inStr.length());       // 文字列の長さを調べる
    
    if (inStr.length() == 2) {　　　　　// 実質１文字
      char command[2];
      inStr.toCharArray(command, 2);
      parse_menu(command[0]);        　// 1文字目だけcommandとして取り出す 
    } else {
      int i = inStr.toInt();           // ３文字以上なら
      MP3player.playTrack(i);          // 10番以降のトラックを再生
      Serial.print(F("Playing track : "));
      Serial.println(i);
    }
  }
  delay(200);
}
```
   2桁の数字を入力するとtrack010.mp3、track011.mp3、…が再生できました。
　今では"DFPlayer Mini"などがもっとお安く販売されていて消えていく運命の物ですかね。でも私にとっては少し前に覚えたシリアル通信での文字列受信が役立ち良かったです。:smile:
コードレビューの観点メモ

※自分用メモです。随時、変更・追記してきます。

基本的に以下の書籍を参考にしています。

- リーダブルコード
- CleanCode

# 大前提

- 理解しやすいコードであること
- 一度に一つのことを行うこと

# 名前

- 気取った名前より、意味の伝わる名前であること

# コメント

- コメントすべきではないこと
  - コードからすぐに推測できるようなこと
  - 変更内容の履歴のような日誌コメント
- コメントすべきこと
  - 情報を与えるコメント
  - なぜそうしたのか、意図を伝えるコメント
  - 結果に対する警告コメント
  - TODOコメント

# 制御フロー

- ネストは浅くすること
- 説明変数を利用すること
- 要約変数を利用すること

# 変数

- スコープは小さいこと

# 関数

- 小さいこと
- 一つのことを行なっていること
- 引数は少ないこと
- フラグ引数は極力使わないこと
- 副作用を避けること
- DRY原則

# クラス

- 小さいこと
- 単一責任の原則
- 凝集性が高いこと
- オープン/クロースドの原則
- 依存性逆転の原則
WSL2環境にasdfでPHPとNode.jsをインストールする

- 前回「[WSL2 + VSCodeでRuboCopが動くようにしたかった](https://qiita.com/matntntn/items/883503b22f51d2d0d47b)」でasdf入れたのでPHPも入れておきました
- 備忘録として残します
- インストールしたバージョン
    - PHP: 8.2.1
    - Node.js: 最新版

## PHPのインストール

1. PHPインストール時にとにかくエラーが出るので先にパッケージをインストールしておく

    ~~~sh
    sudo apt install autoconf bison libcurl4-openssl-dev libgd-dev libonig-dev libpq-dev libreadline-dev  libsqlite3-dev libxml2-dev libzip-dev mlocate pkg-config re2c
    # mlocateはファイルにインデックス付けるプロセスがあり、/mntを対象外にしないと非常に時間がかかる(Windows側のファイル全てにインデックスつけようとするため)
    # 以下の手順で/mntを対象外にできる
    sudo vi /etc/updatedb.conf
    # PRUNEPATHS= に /mnt を追加
    # :wqで上書き
    ~~~
    
    :::note warn
    **mlocateについて**
    私の場合、`sudo apt install mlocate`を実行すると、いつまでたってもインストールが終わりませんでした（１０分以上）
    色々調べたところ、ファイルにインデックス付けるプロセスがあるようでした
    /mntを対象外にしないとWindows側のファイルにまでインデックスつけようとするようです
    一度インストールを止めて、以下の作業を実施して再度インストールしたところ割と早めに終わりましたので参考まで・・・
    ~~~sh
    sudo vi /etc/updatedb.conf
    # PRUNEPATHS= に /mnt を追加
    # :wqで上書き
    ~~~


1. プラグインインストール

    ~~~sh
    asdf plugin-add php
    ~~~

1. phpをインストール

    ~~~sh
    asdf install php 8.2.1
    # もしパッケージ不足等でエラーが出た場合は調べてインストールして再チャレンジする
    ~~~

1. グローバルに設定

    ~~~sh
    asdf global php 8.2.1
    ~~~

1. インストールできたか確認

    ~~~sh
    php -v
    ~~~

## Node.jsのインストール

1. プラグインインストール

    ~~~sh
    asdf plugin-add nodejs
    ~~~

1. phpをインストール

    ~~~sh
    asdf install nodejs latest
    ~~~

1. グローバルに設定

    ~~~sh
    asdf global nodejs latest
    ~~~

1. インストールできたか確認

    ~~~sh
    node -v
    ~~~

## 最後に

- PHPのインストールがやっぱり時間がかかりました
    - PHPインストール→ライブラリ不足でエラー→エラーをもとに調べてapt install→PHPインストール→エラー...の繰り返し
    - さらには`mlocate`のインストールで時間かかり、、、
- 以前asdfで色々インストールしてましたが、久々にやると「どうするんだったっけ？」とまた調べることになりました
- もう忘れないよう個人的な備忘録として書かせていただきました
- 以上です

### 参考

- [Getting Started - asdf](https://asdf-vm.com/guide/getting-started.html)
- [Ubuntu 20.04 に locate コマンドをインストールする](https://obel.hatenablog.jp/entry/20210313/1615579200)
- [Initializing mlocate database; this may take some time... - WSL](https://github.com/microsoft/WSL/discussions/5967)
- [Ubuntu20.04にphpインストールするときのメモ](https://y-ni-shi.hatenablog.com/?page=1641185400)
Androidのhttp requestで詰まったところ

公式 (https://developer.android.com/training/volley/simple?hl=ja#kotlin) のサンプルを使用したときに、"That didn't work!"になってしまった。

調べたところ、api level 28 からhttp通信がデフォルトで無効になっているとのこと。
サンプルは http://www.google.com を指定していたので、通信できなかった。

解決法
- http:// -> https:// に変更
- AndroidManifest の application に android:usesCleartextTraffic="true" を追記
- res/xml/network_security_config.xml を作成する
paiza.ioでpython その5

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

# 練習問題
qiitaapiを叩け。

# サンプルコード

```
# coding: utf-8

import requests
import json

page = 1
per_page = 5

print("作成日,タイトル,URL,いいねカウント")
url = 'https://qiita.com/api/v2/users/ohisama@github/items'
headers = {
    "content-type" : "application/json", 
    #"Authorization" : "Bearer xxxxxxxxxxxxxx" 
}
params = { 
    "page": str(page), 
    "per_page": str(per_page)
}
res = requests.get(url, headers=headers, params=params)
list = res.json()
#print(list)
for item in list:
    item_id = item['id']
    title = item['title']
    likes_cnt = item['likes_count']
    create_date = item['created_at']
    item_url = item['url']
    print(create_date + ", " + title + ", " + item_url + ", " + str(likes_cnt))




```

# 実行結果

```
作成日,タイトル,URL,いいねカウント
2023-04-04T21:19:51+09:00, paiza.ioでpython その4, https://qiita.com/ohisama@github/items/a589a615d2012636ea3c, 0
2023-04-04T15:53:15+09:00, paiza.ioでpython その3, https://qiita.com/ohisama@github/items/25e36c06979be784a327, 0
2023-04-04T15:39:57+09:00, paiza.ioでpython その2, https://qiita.com/ohisama@github/items/2bda3bab5a049e72fff9, 0
2023-04-04T05:58:35+09:00, cscの作法 その300, https://qiita.com/ohisama@github/items/aebdd9b6dc2be2d92901, 0
2023-04-03T08:10:21+09:00, cscの作法 その299, https://qiita.com/ohisama@github/items/0c53d06d5745804d866b, 0
```

# 成果物

https://paiza.io/projects/arJL-NE3BqzmPRP_yeMVRw?language=python3

以上。
次世代プロジェクト管理ツールの構想を練る（３）

https://qiita.com/EasyCording/items/4ee4329965f26eaac5d1


# GUIの構想について
　何せWEBアプリ寄りのスタートだったので、ここまで来るのに２～３日かかってしまった。昨日はCHATGPTにも質問をぶつけまくり、最初はWEBのグラフィックスで、canvas要素だとか、img要素でSVGを使うのか？など、色々調べてきたが、遂に下記のサイトと出会い、Three.Jsが自分の求めている世界観に一致した。

https://devsnap.me/three-js-games

# 経緯
　自分は少し最近のAIGの動向を見ていて、これからはSONYと任天堂などのゲーム企業が、ＡＩ関連で成長するというStability社CEOの[YouTube動画](https://youtu.be/2-LCP6fbJcg)を見て、まさにそんな気がしたので、いろいろゲーム開発について調べていた。本屋に行き調べたのであるが、GAME開発と言うとUNITYなどの本が多いので、web技術ではあまり目新しいものに出会わなかった。そういう点では、この領域については、まだまだこれからの領域なんだろうと確信した。
　昨年まではREACT.JSを使えるように、かなり勉強してきたが、今回のREDMINEのGUI開発において、REACTとThree.Jsを組み合わせる構想が、一番モダンな技術になると確信してきた。

# Three.js
　ひとまず下記のサイトを見てほしい。先日まではmidjourneyなどの生成系グラフィックスにはまっていたが、これからは二次元デザイン領域は確実にＡＩに代替されることが自明である。残ってくるのはロボット開発などの機械領域で、真っ先に考えられるのは、AIを使った物理現象のシミュレーションである。

https://threejs.org/

# 教材
　とりあえずCHATGPTに出会ったので、これからはバリバリ質問しまくっていこうと思うが、やはり開発環境の構築や、基本的な部分は、ある程度の学習が必要だ。そんな訳で、今週は下記の動画を中心にTHREE.JSに入門することにした。

https://youtube.com/playlist?list=PLT5klp7W4r8TprwP0xZvVC64WSfRUQFY-

# GPT関連
　ひきつづきCHATGPTのウォッチングも進めている。今回のPJT管理ツールでは、タスクとチケットの生成で、とくに階層決定などで、CHATGPTを利用しようと考えている。もちろんビジネスアプリを思考しようとすると、勝手な利用はできないので、まずはOPENソースでオンプレミスが前提である（これからの企業は、いかに情報機密を確保しつつ、ＡＩ利用を考えるのか、ここが最大の課題になることが自明であるので）
　一応、GPT4ALLと言うのが、有望みたいなので、こちらのリンクも貼っておく。

https://www.youtube.com/watch?v=GhRNIuTA2Z0

# 3Dサイト
　調べていて下記の動画に行きついた。REACT+3Dはこれから必須の時代になるだろう。一歩上を目指す方はこちらをどうぞ

https://www.youtube.com/watch?v=ZqEa8fTxypQ
ChatGPTおすすめChrome拡張機能7選



## 1. Superpower ChatGPT

https://chrome.google.com/webstore/detail/superpower-chatgpt/amhmeenmapldpjdedekalnfifgnpfnkc

:::note info
**【拡張機能の恩恵】**
- ChatGPTとの会話の出力をMarkdownやHTML、Jsonで保存できる。
- ChatGPTとの会話履歴が消えない。
- コミュニティのプロンプト履歴を見ることができる
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/d6c4f04a-1686-7914-426b-9cd25bd3bcb6.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/ef3ba2f4-6cce-0e11-45b6-29e33e62b53a.png)


## 2. ChatGPT for Google

https://chrome.google.com/webstore/detail/chatgpt-for-google/jgjaeacdkonaoafenlfkkkmbaopkbilf/related?hl=ja

:::note info
**【拡張機能の恩恵】**
- googleで検索時にChatGPTからの回答も表示されるようになる
:::

:::note warn
OpenAIのAPI Keyが必要
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/376633c6-7042-6ac6-ed2d-7601a435194c.png)


## 3. ChatGenie

https://chrome.google.com/webstore/detail/chatgenie-for-chatgpt/lgfokdfepidpjodalhpbjindjackhidg?hl=en-GB

:::note info
**【拡張機能の恩恵】**
- 拡張機能のアイコンをクリックしてChatGPTに質問ができる
- ブラウザで選択した文字をChatGPTに質問できる
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/ee99a822-a545-0384-246f-352f1b946ced.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/96a6affa-18c9-a99c-9c9f-e6730a9703b5.png)



## 4. ShareGPT: Share your ChatGPT conversations

https://chrome.google.com/webstore/detail/sharegpt-share-your-chatg/daiacboceoaocpibfodeljbdfacokfjb?hl=en-GB

:::note info
**【拡張機能の恩恵】**
- ChatGPTとの会話をリンクで共有できる
- 会話にコメントを付けることができる
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/60e62d53-953d-fb46-f707-47dceebf907e.png)


## 5. WebChatGPT: インターネットにアクセスできる ChatGPT

https://chrome.google.com/webstore/detail/webchatgpt-chatgpt-with-i/lpfemeioodjbpieminkklglpmhlngfcn

:::note info
**【拡張機能の恩恵】**
- ChatGPTが検索して回答するようになる
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/42e3e625-e8e1-5d07-a2d7-0db6f91365c1.png)


## 6. YouTube Summary with ChatGPT

https://chrome.google.com/webstore/detail/youtube-summary-with-chat/nmmicjeknamkfloonkhhcjmomieiodli

:::note info
**【拡張機能の恩恵】**
- Youtube動画の要約をしてくれる
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/8c2cb14c-ed9a-d0f6-2e43-565628a77826.png)

## 7. ChatGPT Writer - Write mail, messages with AI

https://chrome.google.com/webstore/detail/chatgpt-writer-write-mail/pdnenlnelpdomajfejgapbdpmjkfpjkp

:::note info
**【拡張機能の恩恵】**
- メールの文章を考えてくれる
- メールテンプレートを作ったり、メールの誤字脱字チェックしたり
:::

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/449867/14af58c5-beb8-43bf-0e0f-0740e822d27a.png)
jdkのインストール(fedora 37)

# openJDK 17

## インストール

```
sudo dnf install java-17-openjdk
```


eclipseをインストールしてからプロジェクト作成し、実行したときに下のようなエラーがでたので、上記コマンドを実行した。

Exception in thread  java.lang.UnsatisfiedLinkError: Can't load library: lib/libawt_xawt.so
githubの複数アカウントの使い分け

# 始めに
githubのアカウント(プライベート用や会社用などの使い分け）の使い分けについていくつか方法があるようだが、自分なりのファイナルアンサーをまとめておく。


# 複数アカウント使い分けはこうする

<b>Step 1.</b> clone時にユーザとtokenを指定してクローンする. 

```
git clone https://{ユーザ名}:{トークン}@github.com/{ユーザ名}/hogehoge.git
```
これで当該フォルダにcloneしてきたgit repositoryおよびpushする時には指定したアカウントが使われる。この情報はcloneしたフォルダの.git/configに保存されている。トークンは期限があるため、期限が切れたら下記ファイルのトークンを直接書き換えしまえばいい。
※ ユーザ名トークン名を指定しないでcloneした後に、下記ファイルを直接書き換えても問題なさそう。

```
% cat .git/config
...例...
[remote "origin"]
	url = https://hbjpn:ghp_XXXXXXXXXXXXXXXXXXXXXX@github.com/{ユーザ名}/hogehoge.git
	fetch = +refs/heads/*:refs/remotes/origin/*
...
```

トークンの取得方法詳細は別途ググって欲しいが、簡単に紹介すると github.comにログインして「Settings」-> 「Developer Settings」-> 「Personal Access Tokens」 からGenerate New Tokenする。パーミッションの設定は普通のリポジトリ操作だけなら「repo」にチェックしておけば良さそう。ちなみに、「Developer Settings」が一番下のわかりにくい所にあるのが個人的には解せない。github使っている人はほぼDeveloperなんだからメインの設定扱いくらいでよいと思うのだが・・・。


<b>Step 2.</b> コミット記録用 名前・メールアドレスの設定
グローバル設定とローカル設定がある。アカウント使い分けしたい場合は、フォルダごとに使い分けたいというのが典型的ユースケースだろう。ローカル設定を一回だけ実施すればOKだ。

```
% git config user.name "{名前}"
% git config user.email "{メールアドレス}"
```
ここで設定した情報も .git/configに記録される。

何も設定しないとglobal設定 (~/.gitconfigに記録されているもの)が使われてしまうので必ず設定すること。

以上のstep1, step 2 だけやっとけばOKだ。

上で設定方法は終わり。下記は参考情報。


# github認証 : HTTPS + Token or SSH
githubのリモートリポジトリへのpushには認証が必要である。 githubでは HTTPS or SSHで認証を行う。 

HTTPSは httpsアドレスを指定してcloneするアレである。cloneするとpasswordをきかれるので、githubページで生成したtoken文字列を指定する。 tokenは昔のパスワードに変わるものである.

SSHでのアクセスにはローカルでssh鍵を生成しそれをgithub.comページで登録することで、ローカルとgithubアカウント紐づけて認証を行う方法である. 

個人的には鍵生成とか面倒なのでより直感的でステートレス（に近い気がする)なHTTPSベースの認証の方が好き。

# user.name ?
gitではuser.name, user.emailでcommit時の「アカウント」を指定できる。という説明をしている記事も結構見たのだけど、これはアカウントを指定しているわけではなく、単にコミットログに残す名前とメールをしているに過ぎない(名前/email は任意のものが指定できる)と理解している。そのため、「アカウント」を切り替えたつもりが、想定しない「名前」でコミットしちゃったよという事故が起きる。
mapbox-gl-jsで地図を日本語化する方法【2023】


## mapbox-gl-jsで地図を日本語化する方法

ちょっとハマったので共有。

[公式ドキュメント](https://docs.mapbox.com/jp/mapbox-gl-js/example/language-switch/)には`setLayoutProperty`で地図の言語を変えられると書いてあるが、こちらは現在日本語は未対応だそう。

日本語にするには`mapbox-gl-language`で実装する必要がある。
https://github.com/mapbox/mapbox-gl-language

①パッケージインストール
`npm install --save mapbox-gl @mapbox/mapbox-gl-language`

②サンプルコード
```
import mapboxgl from 'mapbox-gl';
import MapboxLanguage from '@mapbox/mapbox-gl-language';

mapboxgl.accessToken = 'YOUR_ACCESS_TOKEN';
const map = new mapboxgl.Map({
    container: 'map',
    style: 'mapbox://styles/mapbox/streets-v10',
    center: [-77.0259, 38.9010],
    zoom: 9
});

// 言語変更設定
const language = new MapboxLanguage();
map.addControl(language);
```

この設定をしたら地図が日本語になりました。


対応している地図スタイルはこちら
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/358277/d1006a6d-052a-65e2-3c4a-49c88cd36ff0.png)

インスタンス化したものを変数に入れ直している場合はエラーになるかも
https://github.com/mapbox/mapbox-gl-language/issues/37
Unixコマンドライン操作【基礎編④】

コマンドラインの基礎知識について1から復習中なので、
主に自分の備忘のために学んだことを記録しておこうと思います。のその④
おそらく最後です！

教材はRuby on Railsチュートリアルのコマンドライン編です。
第5章の「ディレクトリ」の内容について書こうと思います。
3章以降は有料コンテンツのため、覚えたコマンドだけ簡単に紹介します

macOSを使っています。

# 1. スーパーユーザの権限で実行

「sudo」・・一般ユーザーにスーパーユーザーの強大な権限を与えるもの

※スーパーユーザー（何でも実行できるユーザ。またの名をrootユーザ)の強大な権限を与えるコマンド

```Bash:ターミナル
$ sudo touch /opt/foo
 Password:***
```
上の例の場合、権限がなくtouchコマンドが使用できなくても、頭にsudoをつけてパスワードを入力すれば実行可能

# 2.ディレクトリの作成

### mkdir
指定した名前でディレクトリを作成するコマンド

```Bash:ターミナル
$ mkdir <name>  
```


### pwd

現在作業しているディレクトリを表示

```Bash:ターミナル
$ pwd
```
# 3.ディレクトリの移動

以下のような移動が可能

```Bash:ターミナル
$ cd <dir>    ← 作業ディレクトリを<dir>へ
$ cd ~/<dir>  ← ホームからの相対位置へ
$ cd ..       ← 一つ上のディレクトリへ
$ cd          ← ホームディレクトリへ
$ cd -        ← 直前のディレクトリへ
```

### カレントディレクトリ　「.」
「.」の一文字でカレントディレクトリ(現在作業中のディレクトリ）を表せ

【使用例】
```Bash:ターミナル
$ cp ~/text_files/foo.txt . ← 現在のディレクトリにファイルをコピー
$ find . -name '*.txt'      ← カレントディレクトリ以下の階層のテキストファイルを検索
$ open .                    ← Finderを開く（Macのみ)
```
#### ※find
ファイルやディレクトリを検索できるコマンド
#### ※open(Macしか使えないらしい）
指定したファイルを、プログラムを使って自動的に開いてくれるコマンド
ディレクトリを指定した場合にはFinderを開く

# 4.ディレクトリのリネーム/コピー/削除

## リネーム
ファイルのリネームと同じくmvコマンドを使用する
```Bash:ターミナル
$ mv foo/ bar/
```
※後ろの/はあってもなくてもいい

## コピー
###### ディレクトリの中身ごと（そのディレクトリも含め）コピーしたい場合
```Bash:ターミナル
$ cp -r ../text_files . 
※再帰的にコピーのオプション(-r)を付ける必要がある。/はつけない
$ ls
text_files
```
※/を末尾につけた場合、中身のファイルはコピーされるが肝心のディレクトリはコピーされない

###### 個別のファイルだけをコピーする場合
```Bash:ターミナル
$ cp -r ../text_files/* . 
```
/だけ書かずに明示的に*を置くようにする（実行結果は同じでも）

## 削除
```Bash:ターミナル
$ rmdir <dir>　 ← （中身が空の）ディレクトリを削除する
$ rm -rf <dir> ← ディレクトリと中身を削除する(中身があっても削除できる)
```
※「-rf」・・再帰的かつ強制。使用には注意する

# おまけ
###### ディレクトリの任意の最深部にある文字列を探す方法

```Bash:ターミナル
$ grep -ri <string> <dir>
```

「-r」・・再帰検索
「-i」・・大文字小文字区別なし

※grepについては基礎編③で紹介

今回はこんなところで！

ありがとうございました。
[Unity URP] カラーノイズとα抜きテクスチャからラメ仕様のSSRカードを作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/85324e38-9505-ded4-8c42-f71ff2b3f1fb.png)
キモはNormalUnpackで、カラーノイズのRGBを法線方向に変えてしまえば、ラメの出来上がりです。
<iframe width="560" height="315" src="https://www.youtube.com/embed/9b7iwqvyz-U" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>
以上です。
素数判定アルゴリズムについて

# Pythonによる素数判定アルゴリズム

### 用語定義
- 自然数：1以上の整数
- 素数：約数が1とその数自身である自然数
    - ただし、1は素数でない。
- 合成数：素数でない数

## 素数判定アルゴリズム
素数であることの定義は、約数が1とその数自身である自然数である。

アルゴリズムの1つは、ある自然数Zを２からZまで割っていき、Zで割ったとき以外、一度も余りが0にならなければ素数と判定するものである。

以下の2点を踏まえてアルゴリズムを実装した。
- ZをZで割った余りは0であることは明らかなので、２からZ-1でよい。
- 加えて、隣り合う自然数は互いに素であるから、Z-1では余りが0にならない。したがって、Z-2でよい。
```python:isPrime.py
def isPrime(Z):
    if Z < 2:
        return False
    else:
        for i in range(2, Z-1):
            if Z % i == 0:
                return False
        return True  
```

しかし、この方法は総当たりで、Zが大きくなるにつれて、計算量が膨大になる。したがって、より良いやり方を2つ目に提示する。

## 2つ目のアルゴリズム

2つ目のアルゴリズムには、「合成数aは、b<=√a を満たす素因数bをもつ」という性質を利用する。

### 証明：
合成数は、少なくとも二つ以上の素数の積で構成されている。合成数をN、素数をp,qとおくと、
N>=p＊q　-①
である。ここで、√N<pかつ√N<qと仮定すると、
N<pq
となり、①に反する。したがって、N>√pまたはN>√qである。

以上のことから、Nは√N以下に少なくとも１つ素数が存在していることが分かる。よって2からz-1まで調べず、√Nまで調べれば十分である。

また、計算量を下げるための工夫を２つ施す。
- Nが2の倍数か判定
Nが2の倍数か判定することで、計算量を半分にできる。

- iの初期値を3にする
iの初期値を3にすることで、i+=1ではなくi+=2とできる。なぜなら、4以上の偶数は素数でないことが確定しているからである。そのため、初めにNが2であるかどうかを判定している。

以上を踏まえ、より良いアルゴリズムは以下のとおりである。
```python:isPrime1.py
def isPrime1(N):
    if N == 2:
      return True
    if N < 2 or N % 2 == 0:
      return False
    i = 3
    while i**2 <= N:
        if N % i == 0:
          return False
        i += 2
    return True
```
【GAS】Googleドライブを経由せず、Gmailに添付されたCSVファイルの中身をGASで取得したい

コーポレートルールの制約でDriveAppクラスのメソッドが使用できない環境だけど、Gmailに添付されたCSVファイルの中身をスプレッドシートに取り込みたかった。

# 目次
[1. 概要](#1-概要)
[2. スクリプト](#2-スクリプト)
[3. 実践](#3-実践)

# 1. 概要
① GmailAppクラスのメソッドでメールを取得
② 添付ファイルをBlobで取得
③ getDataAsStringメソッドでテキストに変換

の要領でできました。

# 2. スクリプト
```getCsvContent.js
function getCsvContent() {
  var threads = GmailApp.search('<メール検索クエリ>', 0, 1); 
  threads.forEach(thread => {
    var messages = thread.getMessages();
    messages.forEach(message => {
      let attachmentBlobs = message.getAttachments();
      let attachmentBlob = attachmentBlobs[0];

      let data = attachmentBlob.getDataAsString("UTF-8");
      let csv = Utilities.parseCsv(data);
      Logger.log(csv);
      })
  })
}
```

# 3. 実践
CSVの中身はこんな感じ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643466/337d5dce-b730-3017-e85f-4efa33d61450.png)

出力結果はこんな感じ（二次配列で取得できる）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1643466/15a5315d-6f0f-adaa-6c8c-b2cb7c677880.png)
RedHatパートナーサブスクリプション申請してみた

# パートナーサブスクリプションとは
https://www.redhat.com/ja/about/press-releases/red-hat-introduces-new-partner-subscriptions-enable-ecosystem-innovation-and-customer-success
- RedHatのパートナー企業はRedHat製品をPoCや社内でのスキル習得の目的に限定して1年の利用権限が付与されるライセンスのようです。

- 従来はパートナー企業に対しては、NFR(Not for Resell)というサブスクリプション提供がされていたようですが、2023年2月からこちらに切り替わったとのこと。

# 申請条件
上記の発表レターから抜粋です。
>Red Hat Partner Subscriptionsは、Red Hat Ready、Advanced、Premierのすべてのビジネス・パートナーに提供されるようになりました。さらに、Red Hatの製品認定を完了した、または完了手続き中のRed Hatテクノロジー・パートナーも、Red Hat Partner Subscriptionsを利用することができます。

ということでRedHatのパートナー企業であれば大体いけそうです。

# 申請手順
## RedHatパートナーコネクトから申請
- 前提としてRedHatのパートナーアカウントは取得している前提とします。
- パートナーポータルにログインします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/584d2a67-f70f-891d-3be0-2548e4fe2aea.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/99beeb66-da7e-7768-9d38-77dc96289037.png)
- パートナーコネクトにログインしたら、上段の[セールス]-[RedHat パートナーサブスクリプション]を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/d5a98195-2ec9-98a7-e30c-7cd068ce7eeb.png)
- [Accept Terms and COnditions]をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/95a20ee9-0413-fc8f-2b20-750fe97049b5.png)
- 利用条件を読み、同意しますにチェックを入れて[提出]をクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/5f7a9609-f01c-728d-03c5-1ac593de46ed.png)
- パートナーサブスクリプションの利用用途を選択し(最大3つでした)[Review Terms and Conditions]をクリックします
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/7e48fd84-0cce-4a82-a3ef-b22698d15623.png)
- また、利用条件に戻った？と思いますが、よく見ると前の利用条件と内容が違うものでしたの。確認して、同意し[提出]しましょう(前の：RedHat Partner Code of Conduct、今の：Partner Subscription Terms)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/797ca39d-a317-12a1-77d8-c2341c0f230f.png)
- なんか今度こそ同じこと聞かれている気がするのですが、気にせず[Request Partner Subscription]をクリックします。これで申請は完了です。![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/f1b232e5-325f-e0dd-e90c-1736eee07b46.png)
## メール受信～カスタマーポータルでサブスクリプションの確認

- 以下の差出人件名でメールが届きます。
  - 差出人：Red Hat Workflow \<noreply@redhat.com>
  - 件名：Your Red Hat subscription is now active
- メールが届いたら、メールに記載の`Get started with your subscription now:`の後ろにあるカスタマーポータルのリンクをクリックします。
- カスタマーポータルの[サブスクリプションの使用状況を表示]をクリック
![rhsub1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/9d09ed79-3aff-01ea-127b-73ae5079d365.png)
- こんな感じでパートナーサブスクリプションが有効化されているのが見えます![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/93933/3bb0d92b-ac9a-be86-1f22-cf74d65ddd94.png)


# 最後に
- OpenShiftやAnsible Automation Platformを検証するために1年ライセンスが取得出来たのであとはやるだけ。
新天地キャリアチェンジ

これから備忘録のような使い方で投稿していこうと思います。
有識者の先輩方々必死にしがみついていくので何卒宜しくお願い致します。
(もし宜しければそれ違うよってとこがあればコメントに残していただけましたら幸いです💦)

-profile-
20代前半の若手未経験インフラエンジニア
PHP,Javaをプロゲートでかじった程度
直近の目標はITパスポートに合格してある程度の知識をつけること

どこまで行けるか分からないがやれるものはとことんやっていく精神で精進していきます。
GitHub Flow について

# GitHub Flow　とは
- チーム開発にて活用する
    - バックアップを取りながら開発を進めることができる
    - コピー上でコードを追記していく
    - コピーを複数人でレビュー
    - レビューが完了すればgithub上に反映する
### 言葉のイメージ
- mainブランチ
    - 木の幹
- ブランチを作る（= コピーを作ること）
    - ブランチ=枝

# 手順
1. ”リモート”mainブランチから”ローカル”mainブランチへpull
1. ブランチを作成
1. 開発 -> commit
1. ローカルブランチからリモートブランチへpush
1. Pull Request
1. マージ or 修正依頼(※再push)　
1. githubdesktop（ローカル）でmainブランチでfetchオリジンし、リモートブランチとの差分をプルオリジンすることで修正が反映される。

### 画像にて
1. ”リモート”mainブランチから”ローカル”mainブランチへpull
1. ブランチを作成
    1. new branchを押し、名前をつけ、クリエイトブランチで作成する。
![スクリーンショット 2023-04-04 23.23.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/644f9b8c-acb3-9316-1833-a631e70c112d.png)
![スクリーンショット 2023-04-04 23.23.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/63c9dd7a-ff2b-0c40-03ee-f710ff31cbec.png)
1. 開発 -> commit
![スクリーンショット 2023-04-04 23.26.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/4f0d3490-74c8-8c45-6899-25e691eed97a.png)
1. ローカルブランチからリモートブランチへpush
![スクリーンショット 2023-04-04 23.26.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/36bd5630-817e-fa4a-be09-3061837d08ac.png)
![スクリーンショット 2023-04-04 23.26.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/4745893e-473d-dcc4-dcfd-9a85c7549613.png)
1. Pull Request
内容を記述してプルリクエスト
![スクリーンショット 2023-04-04 23.27.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/a630259d-1c8c-7f6c-b9e4-b05822ef2431.png)
1. マージ or 修正依頼(※再push)　
![スクリーンショット 2023-04-04 23.27.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/5df84e4c-c4d6-e93e-77fe-d63f8d522c56.png)
![スクリーンショット 2023-04-04 23.28.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/e558be12-2d26-d151-a1fa-1bb10aacecc0.png)
1. githubdesktop（ローカル）でmainブランチでfetchオリジンし、リモートブランチとの差分をプルオリジンすることで修正が反映される。
![スクリーンショット 2023-04-04 23.28.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/41a0a093-7f43-c8bb-2aab-3aa5025b2f0f.png)
![スクリーンショット 2023-04-04 23.28.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/22b12d32-f53a-90db-74cd-b7bbe90ffe9d.png)
![スクリーンショット 2023-04-04 23.28.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3193952/f28ce2bf-ff99-4805-ad42-74a329985d48.png)
【Git】fatal: You have not concluded your merge. (MERGE_HEAD exists) 解消法

## 状況

`git merge develop`を実行した際に次のようなエラーが発生する。

```terminal
$ git merge develop
fatal: You have not concluded your merge. (MERGE_HEAD exists)
```

## 解消法

`git merge develop`を実行する前に`git reset --merge`を実行することで解消する。

```terminal
git reset --merge
```
[AWS Q&A 365][WAF]AWSのよくある問題の毎日5選 #23

# 1. AWS WAFとは何ですか？ 
AWS WAF（Web Application Firewall）は、アプリケーションの可用性に影響を与える可能性がある一般的なWeb攻撃からWebアプリケーションを保護するWebアプリケーションファイアウォールです。

# 2. AWS WAFはどのように動作しますか？ 
AWS WAFは、カスタマイズして特定のニーズに合わせることができる事前定義されたルールセットに対してWebリクエストを検査します。 Webリクエストがルールに一致する場合、AWS WAFは構成に基づいてブロックするか、通過を許可します。

# 3. AWS Firewall Managerとは何ですか？ 
AWS Firewall Managerは、AWSアカウントとアプリケーション全体でファイアウォールルールを中央的に構成および管理できるセキュリティ管理サービスです。

# 4. AWS Shield Advancedとは何ですか？ 
AWS Shield Advancedは、AWSで実行されているアプリケーションのDDoS（分散型サービス妨害）攻撃の高度な検出と軽減を提供するDDoS防御サービスです。

# 5. AWS WAFを設定するにはどうすればよいですか？ 
AWS WAFを設定するには、AWSアカウントに登録し、管理ユーザーを作成し、必要なツールをダウンロードし、AWS WAF開発者ガイドに記載されているステップバイステップの手順に従う必要があります。
[AWS Q&A 365][WAF]Daily Five Common Questions #23

# 1. What is AWS WAF? 
AWS WAF (Web Application Firewall) is a web application firewall that helps protect web applications from common web exploits that could affect application availability, compromise security, or consume excessive resources. 

# 2. How does AWS WAF work? 
AWS WAF inspects web requests against a set of predefined rules that you can customize to meet your specific needs. If a web request matches a rule, AWS WAF can block it or allow it to pass through based on your configuration. 

# 3. What is AWS Firewall Manager? 
AWS Firewall Manager is a security management service that allows you to centrally configure and manage firewall rules across your AWS accounts and applications. 

# 4. What is AWS Shield Advanced? 
AWS Shield Advanced is a DDoS (Distributed Denial of Service) protection service that provides advanced detection and mitigation of DDoS attacks for applications running on AWS. 

# 5. How do I set up AWS WAF? 
To set up AWS WAF, you need to sign up for an AWS account, create an administrative user, download the necessary tools, and then follow the step-by-step instructions provided in the AWS WAF Developer Guide.
Turborepo内のRemixアプリから、内部パッケージをインポートするときに発生するエラーを解決する

# はじめに

Turborepoの`apps`ディレクトリに、Remixプロジェクトを作成した際にエラーが発生しました。

# 実行できないエラーが発生

Remixの`package.json`に、`packages/ui`ワークスペースの依存関係として追加しました。

```package.json
{
  "dependencies": {
    "ui": "*"
  }
}
```

この状態でもビルドは通りました。
しかし、実行した時にエラーが発生しました。

```bash
npx turbo build
cd apps/my-remix-app
npm run start

> start
> remix-serve build

/Users/takagimeow/**/my-turborepo/packages/ui/index.tsx:1
import * as React from "react";
^^^^^^

SyntaxError: Cannot use import statement outside a module
```

# `serverDependenciesToBundle`を設定してエラーを解決

このエラーを解決するには、`remix.config.js`の`serverDependenciesToBundle`フィールドを使います。
このフィールドに、`["ui"]`を設定します。

```remix.config.js
/** @type {import('@remix-run/dev').AppConfig} */
module.exports = {
  ignoredRouteFiles: ["**/.*"],
  // appDirectory: "app",
  // assetsBuildDirectory: "public/build",
  // serverBuildPath: "build/index.js",
  // publicPath: "/build/",
  future: {
    v2_errorBoundary: true,
    v2_meta: true,
    v2_normalizeFormMethod: true,
    v2_routeConvention: true,
  },
  serverDependenciesToBundle: ["ui"],
};
```

もう一度ビルドと実行を行った結果、エラーは解決しました。

```bash
npx turbo build
cd apps/my-remix-app
npm run start
```

# 参考にした記事

https://github.com/remix-run/remix/issues/4234
linux シェルスクリプト実行法について検証してみた

# はじめに
シェルスクリプト実行法が4通りあるため、実際に検証してみた

以下の本で学びました。
https://www.amazon.co.jp/dp/4798166154

※カレントのシェルは現在使用しているシェルのことです。

## スクリプトを実行
以下はTEST用に作成したシェルスクリプトの中身です。
```
#!/bin/bash

export TEST=123
echo ${TEST}
```

### 1 ./スクリプト名.sh
実行権限が必須です。環境変数はスクリプト実行後にシェルに残らないです。
※おそらくシバン(#!/bin/bash)で子シェルを起動して、子シェルの中で環境変数が設定されていると思います。

```
 ./test.sh
ls -l
-rw-r--rwx. 1 root root 44 Apr  4 21:01 test.sh

[test_user@localhost tmp]$ ./test.sh
123

TESTがシェルの環境変数に残っていないことを確認した
[test_user@localhost tmp]$ env | grep TEST
[test_user@localhost tmp]$
```

### 2 bash ./スクリプト名.sh
basコマンドから子シェルが起動して、子シェルの中で環境変数が設定されていると思います。
実行権限は不要です。
```
[test_user@localhost tmp]$ bash ./test.sh
123
[test_user@localhost tmp]$
[test_user@localhost tmp]$ env | grep TEST
```

### 3 . ./スクリプト名.sh
カレントのシェルでスクリプトが実行されています。そのため、環境変数がカレントのシェルに設定されています。
実行権限は不要です。
```
[test_user@localhost tmp]$ . ./test.sh
123
[test_user@localhost tmp]$ env | grep TEST
TEST=123
```

### 4. source ./スクリプト名.sh
カレントシェルでスクリプトが実行されています。そのため、環境変数がカレントのシェルに設定されています。
実行権限は不要です。
```
[test_user@localhost tmp]$ source ./test.sh
123
[test_user@localhost tmp]$
[test_user@localhost tmp]$ env | grep TEST
```
# まとめ

上記のシェルスクリプトのパターンがありましたが、先ずはカレントのシェルでスクリプトと子シェルどちらでシェルスクリプトを実行したいのか考える必要があります。
過去にシェルスクリプトに実行権限を付ける手間を減らすために１の./スクリプト名.sh以外の実行法を使用しているケースがありましたが、個人的にはあまりお勧めしません。
１の./スクリプト名.shは実行権限がないユーザーはスクリプトを実行できないのと環境変数がカレントのシェルに残らないため、本番環境ではお勧めです。
Laravel url へルパ関数の意外な落とし穴

# 環境
Laravel Version 8.68.1

# 概要
Laravelでよく使うurlへルパ関数ですが意外な落とし穴を見つけました。

```php
url('/hoge/hoge');
```

それは「データベースにURLを登録する際にurlへルパ関数を使うと最悪の場合サイトの信頼性を損ねる可能性がある」ということです。

# どういうことか

下記の例を見てみましょう

```HogeController.php
        App\Models\HogeTable::create([
                'title' => 'タイトル',
                'text' => 'テキスト',
                'link' => url('/hoge/1'),
        ]);   
```
このサービスが仮に http://example.com というドメインでこのサービスを運営していたとします。
この場合linkカラムには http://example.com/hoge/1 という値が入ります。

しかし、逆引きされたIP http://93.184.216.34 でアクセスして、この処理が実行された場合、linkカラムには http://93.184.216.34/hoge/1 という値が登録されてしまいます。

つまり、悪意のあるユーザーがこのIPを任意のドメインのDNSレコードに紐づけてサービスにアクセスして、この処理を実行した場合、任意のURLを登録されてしまいます。

登録された悪意のあるURLに他のユーザーがアクセスしてしまった場合にサイトの信頼性を大きく損ねてしまうというわけです。

# 対策
- .envのAPP_URLからURLを取得するようにする
- Webサーバーを正しく設定する
ASP.NET MVCで共通処理をまとめる

### はじめに
どの画面のControllerでも行うチェックがあり、複数箇所で同じ記載をしていたためまとめたいと思っていました。
現場での画面開発が初めてで、しかも新規作成だったため手探り状態でしたが、今回学んだことを備忘録にまとめます。

### Filter
JavaのServletでFilterを使ったことがあるので、ASP.NETにもあるんだという感じでした。
ASP.NET Core7.0の説明ですが、詳しくは[公式ドキュメント](https://learn.microsoft.com/ja-jp/aspnet/core/mvc/controllers/filters?view=aspnetcore-7.0)をご覧ください。
ネットで調べても使用例はあまり見つけられなかったため、公式ドキュメントを読み込んで試行錯誤しました。

今回はControllerアクションの最初で処理を行いたかったので、「アクションフィルター（IActionFilter）」を使いました。
```SampleActionFilter.cs
public class SampleActionFilter : IActionFilter
{
    public void OnActionExecuting(ActionExecutingContext context)
    {
        // アクション実行前処理
    }

    public void OnActionExecuted(ActionExecutedContext context)
    {
        // アクション実行後処理
    }
}
```
例外処理も同じ記載があるのでまとめたいと思い、「例外フィルター（IExceptionFilter）」を使えたらいいなと思ったのですが、DbExceptionとExceprionとあるので分け方が分からず、こちらは次に紹介する親Controllerに記載しました。
はじめはFilterクラスを作成していたのですが、Controllerでも使えるようでまとめて親Controllerに記載することにしました。

### 親Controller
共通処理を親Controllerに書いておき、継承してそのメソッドを使うようにしました。
親ControllerをBaseControllerとします。

OnActionExecutingはアクションメソッドの前に一律で処理されます。
コントローラ名、アクション名が取得できるので特定のコントローラ、アクションを除外できます。
```BaseController.cs
public class BaseController : Controller
{
    protected override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        RouteValueDictionary routeValue = filterContext.RouteData.Value;
        // ログイン画面の場合は除外
        if (routeValue["controller"].ToString() == "Login")
        {
            return;
        }
        
        // 初期処理の場合
        if (routeValue["action"].ToString() == "Index")
        {
            // 処理
        }
            
        // 共通で行いたい処理

        base.OnActionExecuting(filterContext);
    }
    
    // メソッドが続く
}
```
セッションチェックなどの共通チェックはメソッドにしました。
```BaseController.cs
protected bool SessionCheck()
{
    　// セッションの値があればtrue。なければfalse。
}
```
複数のチェックもまとめたりもしました。
```BaseController.cs
protected bool CommonCheck()
{
    // セッションチェック
    if (!SessionCheck())
    {
        return false;
    }

    // トークンチェック
    if (!TokenCheck())
    {
        return false;
    }

    // 権限チェック
    if (!RoleCheck())
    {
        return false;
    }

    return true;
}
```

各コントローラで使用する場合は下記のようになります。
通常の場合とAjaxの場合でreturnの記載が違うためこのようにしました。
```TopController.cs
public class TopController : BaseController
{
    public ActionResult Index()
    {
        if (!CommonCheck())
        {
            // エラー画面に遷移
            return RedirectToAction("Error", "Error");
        }  
    }
}
```

Exceptionは重複部分だけBaseControllerに書いて、そのメソッドを使うようにしました。

### 最後に
各コントローラにメソッド使用とreturnの記載が必要なため、まとめる意味があまりなさそうな気がしましたが、コードの重複がなくなりスッキリしました。メッセージIDの修正があった時もBaseControllerだけ修正すればよかったのでやった甲斐はあったと思います。
フレームワークの知識と経験がまだまだ足りないのでまだ知らないことや良い方法あるかもしれませんが、随時更新していきたいです。
hmmlearnでtransmat_ rows must sum to 1が出る原因

hmmlearnエラーの原因がわかったのでメモ
# 環境
```
Python 3.10.4
hmmlearn 0.2.8
```
# エラー再現
```py
import numpy as np
from hmmlearn import hmm

X = np.array([[100], [100], [100], [1]])

model = hmm.GaussianHMM(n_components=2)
model.fit(X)
# Warning: Some rows of transmat_ have zero sum because no transition from the state was ever observed.

model.sample(20) # ここでエラーになる
# ValueError: transmat_ rows must sum to 1 (got [1. 0.])
```
# 原因
あるステートから別（または同じ）ステートに一度も移行しない場合に起こる。

これはエラーにならない
```py
X = np.array([[100], [100], [100], [1], [100]])
X = np.array([[100], [100], [100], [1], [1]])
```
また、根本的な解決にはならないが遷移確率の合計が1にならなかった時に`model.transmat_`に仮の値を代入しても一応エラーは防げる。
例えば
```py
num_states = 2
if model.transmat_.sum() != num_states:
    model.transmat_ = np.array([[0.5, 0.5], [0.5, 0.5]])
```
とか。