OmniAICreator/Qiita-1.07M huggingface dataset:
続：Apple TVから流れてくる変なRAをRaspberry PI + FreeBSDで何とかする話

# その後の状況
以前こんな記事を書きました。

https://qiita.com/yshdsnd/items/ccbf4dcd6c2d67b2c606

```sh
${fwcmd} add 690 deny ipv6-icmp from fe80::18d1:c949:e9b5:98e0 to any icmp6type 134
```
こんな感じで、ルールを記載していましたが、このAppleTVのリンクローカルアドレスは再起動する毎に変わるということが分かったので、ルーター側のリンクローカルアドレス(仮にfe80::aaaa:bbbb:cccc:ddddと表記しています)を使うことにして以下の様なコードに変えてしばらく運用していました。

```sh
${fwcmd} add 610 allow ipv6-icmp from fe80::aaaa:bbbb:cccc:dddd to any icmp6type 134
${fwcmd} add 620 deny ipv6-icmp from fe80::/10 to any icmp6type 134
```
→ ルータからのRAは通すが、それ以外からのRAは通さない。

しかし、最近RasPIのOSを13.2-RELEASEにアップデートして再起動して見たところ、deny ipv6-icmp from fe80::/10 to any icmp6types 134のルールに全くパケットが引っかからなくなっていました。

<pre># ipfw -a list
00100     262      24842 allow ip from any to any via lo0
00200       0          0 deny ip from any to 127.0.0.0/8
00300       0          0 deny ip from 127.0.0.0/8 to any
00400       0          0 deny ip from any to ::1
00500       0          0 deny ip from ::1 to any
00600    6384     465960 allow ipv6-icmp from :: to ff02::/16
00610   20418    2123472 allow ipv6-icmp from fe80::aaaa:bbbb:cccc:dddd to any icmp6types 134
00620       0          0 deny ipv6-icmp from fe80::/10 to any icmp6types 134
00700      89       6168 allow ipv6-icmp from fe80::/10 to fe80::/10
00800  344168   29975368 allow ipv6-icmp from fe80::/10 to ff02::/16
00900       0          0 allow ipv6-icmp from any to any icmp6types 1
01000    6541     470216 allow ipv6-icmp from any to any icmp6types 2,135,136
65000 7383007 1699174752 allow ip from any to any
65535       0          0 deny ip from any to any</pre>

はて？
tvOSも以前この問題を見つけたときには16.1位でしたが、今は16.4になっています。どこかのアップデートで改善されたのかもしれません。
しかし、tvOSのリリースノートには特に記載がありませんでした。
うーむ、直ったんですかねぇ...

半信半疑ですが、このRasPIのパケットフィルターは役割を終えたのかもしれません。
RasPIの新しい使い道考えなきゃ。
オブジェクト指向の考え方（その３：カプセル化）

# カプセル化とは
カプセル化とは、「情報と動作をひとまとめにする」こと。

情報隠蔽と同義で使われることがあるが、厳密には異なり、情報隠蔽は「中身を見ることができない」となるが、カプセル化は「中身を知る必要がない」という考えになる。
![オブジェクト指向-6 2.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/580819/2376d52b-64c2-32cc-0e5d-e61283d93e8a.jpeg)

オブジェクト指向では、機能と実装を分離し、知る必要のない仕組みを無視することで複雑さを排除してソフトウェアの理解度を向上させる。


***
前の回はこちら → [オブジェクト指向の考え方（その２：抽象化と階層化）](https://qiita.com/TkyI/items/cb27bd2db95204499bc4)

続きはこちら → [オブジェクト指向の考え方（その４：クラスとインスタンス）](https://qiita.com/TkyI/items/8a9ec240483c9397c1f2)
[SEO観点] wwwサブドメインとAPEXドメインは統一したほうがいいか

### wwwなしのメリット

1. URLの統一性が確保できる
   1. wwwサブドメインを使う場合、URLが"www.example.com"となるため、APEXドメインと合わせて統一感のあるURLを作ることができます。このため、ユーザーにとってはURLを覚えやすくなり、ブランドイメージの向上につながります。

### wwwなしのデメリット

- 特になし

### wwwありのメリット

1. トラフィックをまとめることができる
   1. wwwサブドメインを別のサイトとして運用することで、トラフィックを分散することができます。また、アクセス数の多いページをwwwサブドメインに移行することで、負荷分散ができます。

### wwwありのデメリット

1. リンクジュースの分散
   1. wwwサブドメインとAPEXドメインを別のサイトとして運用する場合、リンクジュースが分散されることがあります。これによって、SEOの効果が減少する可能性があります。
2. コンテンツの重複
   1. wwwサブドメインとAPEXドメインを共存する場合、コンテンツが重複してしまうことがあります。これによって、Googleがサイトをスパムとみなす可能性があります。
3. セキュリティの問題
   1. wwwサブドメインを別のサイトとして運用する場合、セキュリティに問題が生じる可能性があります。例えば、wwwサブドメインに適切なSSL証明書を設定しない場合、情報漏洩のリスクが生じます。

以上が、wwwサブドメインとAPEXドメインを共存する場合、しない場合の主なメリットとデメリットです。SEOにおいては、リンクジュースの分散やコンテンツの重複といったデメリットを踏まえつつ、運用方法を検討する必要があります。
【1週目】ウェブについて基礎知識【スパルタコーディングクラブ】

・ブラウザの原理
→Web上の文言を検証メニューから変更する（検証：Commnad + Option + i）

・Visual Studio Codeを使ったHTML、CSSの仕組み
→HTMLは骨組み、CSSは見た目
→Open with live serverでタイプしたコードをブラウザに表示する

・ログインページの作成
→HTMLで骨組みを作成
→CSSで配置や大きさなどを変更

・Bootstrapについて
→BootstrapとはHTML/CSSフレームワークがまとめられたサイト

・Githubに作成した映画レビューページを公開する
→Webページを配布する
【Python】同一カラムの複数CSVファイルを1つにまとめるスクリプト

同一カラムの複数CSVファイルを1つにまとめる際、Google Colaboratoryでつかっているスクリプトを共有します。

まとめたいCSVファイルをルートディレクトリに配置後、以下を実行すれば、同じディレクトリに出力ファイルが生成されます。

```python
import pandas as pd
import csv
import glob
 
sample_files = glob.glob('./*.csv')
list = []
for file in sample_files:
    list.append(pd.read_csv(file))
 
df = pd.concat(list)
df.to_csv('<出力ファイル名>.csv',index=False)
```
LaravelでAjaxを使おうとすると、エラーコード419が出た。【1回目】

2023年4月にjQueryでJavaScriptを使ってAjax（非同期）の実装を試みる。機能は検索機能。


・開発環境
PHP 8.1.17
Laravel：ver6台(課題の指定がバージョン６)
Composer version 2.5.5
macOS ver13.31


まずは、

【参照】：【jQuery入門】jQueryの基本的な書き方・文法
https://uxmilk.jp/11074
を参照して

```php:blade.php
<head>
 <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>
</head>
```
を入れる。


これを参照：https://enginiya.com/entry/laravel-how-to-use-ajaxすると以下のようにしてAjaxをかける。
＊正直、上記のブログを参照すると非同期処理を実装できる。書いた俺以外の人はそっちを参考にしてください。

```php:blade.php
 // 検索ボタンを押したら、検索欄とメーカー一覧の欄の情報
 $(function() {
  $(".goods_select_btn").on("click", function() {
     $('.goods-list tbody').empty(); //もともとある要素を空にする
     $('.search-null').remove(); //検索結果が0のときのテキストを消す
     var searchSale = $('.search').val(); //検索ワードを取得
     var selectSale = $('.select').val(); //選択メーカーの情報を取得

  $.ajax({
             type: 'POST',
             url: "{{ route('select') }}",
             data: 'search': searchSale,},
             dataType: 'json', //json形式で受け取る
          }).done(function($search) { //ajaxが成功したときの処理
               $('.sale-list tr').append('<td>$search.value</td>');//sale-listというクラスのテーブルにappend();でtrを追加する。
          }).fail(function() {
                        //ajax通信がエラーのときの処理
                        console.log('どんまい！');
          })
   })
});
```
コントローラーやルーティングは置いておいて、このbladeを出力しようとするとエラーコード 
POST http://localhost:8888/＊＊＊/public/＊＊＊ 419 (unknown status)
のようなものが出た。
これをChatGptで検索にかけると
「このエラーは、CSRFトークンが期限切れまたは不一致のために、リクエストが拒否されたことを示しています。
Laravelでは、CSRF攻撃を防止するために、デフォルトで全てのPOSTリクエストに対してCSRFトークンを要求します。このトークンがない場合、リクエストは拒否されます。」
と出る。

つまり、トークン処理を入れろということだ。
今まで、フォームリクエストの時に```@csrf```を入れたように、jQueryでも入れるということ。

```
<head>
<meta name="csrf-token" content="{{ csrf_token() }}">
</head>

<body>
 $.ajaxSetup({ headers: { 'X-CSRF-TOKEN': $("[name='csrf-token']").attr("content") }, })
</body>
```
を入れると解決する。

今後Laravelで非同期処理を実装する際にはこれを見直そうと思う。

ちなみにこのbladeだと、
＄searchでjsonデータを持ってきているはずだが、出力部分である
```<td>$search.value</td>```は間違っているため
検索結果は、
［$search.value］としか表示されない笑

正直、カリキュラムの課題を早く終わらせたいから笑えない。
Git チートシート(になるといいな)

# はじめに
git操作を覚えたい
導入したてですがとりあえずこれさえあれば当面困らんやろ、、、と思ってメモしています

# 基本的な扱い方
::: note info
「編集」→「add」→「commit」の繰り返し

場合によっては
「branch作成」→「編集」→「add」→「commit」→「merge」

いい感じになったら
「add」→「commit」→「push」
:::
（ぐらいの認識しかない）

# コマンド
コマンドプロンプト上で操作する
## 管理開始
最初の設定

### 初期化
管理対象ディレクトリに`cd 管理対象ディレクトリ`で移動
初期化すると.gitフォルダが作成される
```
git init
```

### untracked fileの設定
`.gitignore`という名前のファイルを作成、追跡しなくて良いディレクトリやファイルを指定する
`.gitignore`をaddしてcommitしておく
``` .gitignore
/フォルダ名/
/ファイル名
...
```

## 基本操作

### 状態の確認
今いるブランチとかがわかる
```
git status
```

### add（コミット準備）
コミット予約、ステージングに追加と呼ぶらしい
```
git add 対象ファイル
```
すべてを予約するには
```
git add .
```

### commit
```
git commit -m "コメント"
```

### 履歴を見る
コミット履歴とかコミットIDとかがわかる
```
git log --graph --all
```
`--graph`オプションはなくてもOKだが、個人的にはこっちのほうが見た目が好き
`--all`オプションをつけなければ今いるコミットまでのログを出力する
`q`でログの表示を終了できる

GUIでログを表示
```
gitk --all
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/4c64bacf-f5c0-e74b-2a66-6d6bd453e4f1.png)


## ブランチの操作
### ブランチの作成
ブランチを階層的に定義する。
今いるブランチから分岐し、featureの中に機能名という名前のブランチを作成する
```
git checkout -b feature/機能名
```

### ブランチの移動
ブランチ名を指定すればそのブランチの最新のコミットに移動できる
```
git checkout ブランチ名
```
コミットIDを指定すればコミット当時の状態に移動できる
```
git checkout コミットID
```

### ブランチの削除
```
git branch -d ブランチ名
```

### ブランチのマージ
今いるブランチに別のブランチをマージする
```
git merge ブランチ名
```

### どんなブランチがあるか
```
git branch -a
```


## Push
### GitHubでリポジトリを作成
Newを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/15f3632a-7808-5c04-a05d-1d942d34828f.png)

リポジトリ名を入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/4f5dea5e-e401-8cd2-902d-ba016af6c864.png)

リポジトリの作成
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2716347/0070deb9-12eb-101c-cef3-87496de9a511.png)

リポジトリを作成すると、コマンド例がつらつら出てくる

### コマンドプロンプトでコードを実行
まずはメアドとユーザー名を指定する。ユーザー名はGitHubに登録したものと同じにする。
```
git config --global user.email "メアド"
git config --global user.name "ユーザー名"
```
確認方法はこれ
```
git config --global --list
```

"…or push an existing repository from the command line"という部分に実行すべきコマンドが記載されている
これを実行するようにGitHubから指示される
```
git remote add origin 指定されたURL
git branch -M main
git push -u リモート名 ブランチ名
```

### 作業の定型化
addしてcommitしてpushする
```
git add 対象ファイル
git commit -m "コメント"
git push -u リモート名 ブランチ名
```
【Git】機密情報を含んだディレクトリを誤ってリモートリポジトリにプッシュしてしまった場合の対処方法

似たような記事が100本以上ありそうですが、駆け出しエンジニア(死語？)向けにあらためてまとめました。

# 状況設定
説明のため、以下のような状況を考えます。
- Serverless Frameworkデプロイ時に生成される`.serverless`というサブディレクトリ内のファイルに、APIキーの情報が含まれてしまった。
- `.serverless`サブディレクトリは本来Git管理すべきではないのに、誤ってリモートリポジトリにプッシュしてしまった。
- git-flowによるブランチ管理を行っており、複数のfeatureブランチも存在している。

# 手順1: 該当ディレクトリをGit管理から外す
git-flowのため、最新のdevelopブランチからfeatureブランチをきります。
このfeatureブランチで、`.serverless`ディレクトリを削除します。

```bash
git rm -r --cached .serverless
```

`.gitignore`ファイルに`.serverless`を追加して、将来のコミットでこのディレクトリが無視されるようにします。

```bash
echo ".serverless" >> .gitignore
```

変更をコミット後、リモートプッシュしてdevelopにマージします。
最新developを作業中のfeatureブランチにマージして、同様に`.serverless`をGit管理から外します。
※この操作を忘れてしまうと、featureを最新developにマージした際、`.serverless`と`.gitignore`が元に戻ってしまいます。

あとはgit-flowにのっとって、develop -> staging -> mainの順にマージすれば、アクティブなブランチから`.serverless`がなくなります。

# 手順2: git-secretsの導入
すべての開発メンバーに`git-secrets`を導入してもらいます。
`git-secrets`によって、機密情報が含まれたコミットがプッシュされる前に、検出とブロックが行われます。
※本来は、開発者がリポジトリをクローンしたときに導入するものです。

まずは、すべての開発メンバーに`git-secrets`をインストールするように指示します。
インストール方法はプラットフォームによって異なります。

```bash
# macOS
brew install git-secrets

# Linux
git clone https://github.com/awslabs/git-secrets.git
cd git-secrets
make install
```

メンバー各自で、ローカルリポジトリで次のコマンドを実行し、`git-secrets`を有効化します。

```bash
cd <your_repository>
git secrets --install
git secrets --register-aws
```

通常、`git-secrets`はインストール時にグローバル設定として有効化されます。
そのため、新しいfeatureブランチを作成する際に`git-secrets --install`と`git secrets --register-aws`を再実行する必要はありません。

# 手順3: リモートリポジトリにある非アクティブなブランチの削除
リモートブランチに無駄に残ってしまっているブランチを忘れずに削除しましょう。

# 手順4: 過去のコミット履歴から機密情報を削除する
`git filter-branch`を使用して、機密情報が含まれる過去のコミットを書き換えます。

```bash
git filter-branch --force --index-filter 'git rm -r --cached --ignore-unmatch .serverless' --prune-empty --tag-name-filter cat -- --all
```

`.serverless`ディレクトリが含まれるすべての過去のコミットから、そのディレクトリを削除します。
他の開発者のリポジトリには影響しないため、リモートリポジトリに強制プッシュする必要があります。

```bash
git push origin --force --all
git push origin --force --tags
```

※BFG Repo-Cleanerのようなツールでも同様の操作ができるみたいです。
Software Testing and Quality Assurance: The Key to Successful Software Development

Software testing and quality assurance are essential in identifying and fixing bugs, errors, and other issues before they affect end-users. By conducting comprehensive testing, businesses can ensure that their software is reliable, secure, and user-friendly. Additionally, quality assurance ensures that software meets regulatory requirements and industry standards, reducing the risk of legal and financial liabilities.

Software testing and quality assurance also contribute to cost savings in the long run. By catching and fixing issues early in the development process, businesses can avoid costly rework and reduce the overall cost of software development.
https://shiftasia.com/column/software-quality-assurance-101-the-basics/
Windows10でIPアドレスを固定する方法

IPアドレス（IPv4）を固定する方法について解説します。

## 手順
1. タスクバーのWindowsボタンを右クリック　→　**[ネットワーク接続]** をクリック
2. 画面の下部で **[アダプターのオプションを変更する]** をクリック
3. Wi-Fi、イーサネット等、変更したい項目を右クリック　→　**[プロパティ]** をクリック
![ip1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1905379/17487ebb-f534-2337-ba53-e8054b3c3384.png)

4. 上記画面が表示されたら **[インターネットプロトコル バージョン4(TCP/IPv4)]** を選択し、 **[プロパティ]** をクリック
5. ラジオボタン **[次のIPアドレスを使う]** を選択
6. IPアドレス、サブネットマスク、デフォルトゲートウェイを入力
※空いているIPアドレスが分からない時は、DOS窓で ```arp -a ``` というコマンドを打つと、現在使用中のIPアドレスが確認できる
※サブネットマスク、デフォルトゲートウェイは ```ipconfig /all``` で確認
7. ラジオボタン **[次のDNSサーバーのアドレスを使う]** を選択
8. DNSサーバーのアドレスを入力
※DNSサーバーのアドレスが分からない時は、**[設定]→[ネットワークとインターネット]→[状態]** 画面へ移動。 **[プロパティ]** をクリックすると、DNSサーバーのアドレスが確認できる。
 
 
![ip2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1905379/cbd2fc5e-045f-744d-282e-fbd7ece5c965.png)

**[OK]** をクリックしてプロパティ画面を閉じる。

![ip3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1905379/628aa4ef-ba2e-09fa-7517-13f1250d1b5f.png)

ipconfigで確認すると、設定したアドレスが表示されました。

接続確認もしてください。何か設定に間違いや不足があると接続できなくなります。
flowをラップして良い感じにレスポンスをハンドリングする

昔参考にさせていただいたflowのラッパーメソッド(apiFlow)で、エラーコードとエラー時のbodyを取得できるようにした。
ちなみに、このラッパーを採用した理由は元記事に書かれている通りで、UIレイヤに例外をそのまま伝搬させたくなかったから。

```apiFlow.kt
inline fun <reified T : Any> apiFlow(crossinline call: suspend () -> Response<T>): Flow<Result<T>> =
    flow<Result<T>> {
        try {
            val response = call()
            if (response.isSuccessful) {
                emit(Result.Success(value = response.body()!!))
            } else {
                val errorResponse = response.errorBody()?.let { errorBody ->
                    Gson().fromJson(errorBody.string(), ErrorResponse::class.java)
                }
                emit(Result.Error(errorCode = response.code(), errorResponse = errorResponse))
            }
        } catch (e: Exception) {
            // 例外発生時は強制的に400エラーとする
            emit(Result.Error(errorCode = 400, errorResponse = null))
        }
    }.onStart {
        emit(Result.Proceeding)
    }.flowOn(Dispatchers.IO)

```

```Result.kt
sealed class Result<out T> {
    // APIコールが実行中である
    object Proceeding : Result<Nothing>()
    // APIコールが成功した
    data class Success<out T>(val value: T) : Result<T>()
    // APIコールが失敗した
    data class Error(val errorCode: Int?, val errorResponse: ErrorResponse?, val throwable: Throwable? = null) : Result<Nothing>()
}
```

ErrorResponseクラスは以下。
今回ErrorBodyの中身がjsonなのでパースしてる。

```ErrorResponse.kt
data class ErrorResponse(
    @SerializedName("messageId") val messageId: String?,
    @SerializedName("errorMessage") val errorMessage: String?
) 
```

レスポンスを取得する側、ViewModelの処理はこんな感じ

```SomeViewModel.kt
someRepository.getSomething().collectLatest { result ->
    when (result) {
        is Result.Success -> {
        }
        is Result.Error -> {
            logd("エラーコード：" + result.errorCode)
            logd("エラーレスポンス：" + result.errorResponse)

            // エラーハンドリング
            when (result.errorCode) {
                400 -> {
                }
                404 -> {
                } //などなど
            }
        }
        else -> {} //読込中状態が入る、何もしない
    }
}

```

もうちょっと改良の余地がありそう。
GsonもMoshiに載せ替えたい。

参照： https://zenn.dev/chmod644/articles/fc304b7e2508de
jq コマンドの基本的な使い方

jqは、JSONデータを処理するためのコマンドラインツールです。以下に、jqの基本的な使い方をいくつか紹介します。

‌

### JSONデータの表示

jqを使用して、JSONデータを表示することができます。以下は、JSONデータが記述されたファイルをjqで表示する例です。

```sh
$ cat example.json | jq
```

‌

### 特定の要素の取得

jqを使用して、JSONデータの中から特定の要素を取得することができます。たとえば、以下のJSONデータがあった場合、"name"の値を取得するには、次のようにコマンドを実行します。

```json
{
  "name": "John",
  "age": 30,
  "city": "New York"
}
```

```sh
$ cat example.json | jq '.name'
```

‌

### 複数の要素の取得

jqを使用して、JSONデータの中から複数の要素を取得することもできます。たとえば、以下のJSONデータがあった場合、"name"と"age"の値を取得するには、次のようにコマンドを実行します。

```json
{
  "name": "John",
  "age": 30,
  "city": "New York"
}
```

```sh
$ cat example.json | jq '{ name, age }'
```

### 要素のフィルタリング

jqを使用して、JSONデータの中から特定の条件を満たす要素をフィルタリングすることもできます。たとえば、以下のJSONデータがあった場合、"age"が30以上の要素を取得するには、次のようにコマンドを実行します。

```json
[  {    "name": "John",    "age": 30,    "city": "New York"  },  {    "name": "Mary",    "age": 25,    "city": "Los Angeles"  },  {    "name": "Peter",    "age": 35,    "city": "Chicago"  }]
```

```sh
$ cat example.json | jq '.[] | select(.age >= 30)'
```

これらは、jqの基本的な使い方の一部です。jqには、様々なフィルタリングや変換の方法が用意されており、JSONデータの処理を効率的に行うことができます。
コードレビューの観点：ConcurrentModificationException

ConcurrentModificationException は、あるスレッドが Map　などの Collectionで反復処理を行っている間に、別のスレッドがそのCollectionを変更した場合に発生する Java　の例外です。

実装時やレビューの注意点としては、基本的な物だと思います。
対策として SynchronizedMap を使う人もいると思います。
その際、Kotlin では注意が必要です。

下記は、少し無理矢理ではありますが、SynchronizedMap を使って ConcurrentModificationException が発生する例です。

```kotlin
    @Test
    fun synchronizedMapTest() = runTest {
        val map = synchronizedMap(mutableMapOf<Int, String>())
        for(i in 1..1000) { map[i] = i.toString() }
        val builder = StringBuilder()

        val def1 = async {
            // Collectionの反復処理
            map.forEach {
                delay(1)
                if (it.key % 2 == 0) builder.append("${it.value},")
            }
        }

        val def2 = async {
            // Collectionの変更
            delay(100)
            map.remove(1)
            map.remove(100)
        }

        def1.await()
        def2.await()
    }
```

原因は、反復処理で呼んでいる forEach メソッドが SynchronizedMap のメソッドではないためです。
実際に呼ばれているのは、kotlin.collections に定義されている Map　の拡張関数です。

個人的には SynchronizedMap を使うよりも、Map　を使って自前で synchronized 等で制御した方が良いと思っています。

実装時に見落としやすいポイントなので、レビュー時の観点といして頂ければ幸いです。
【Xcode】シュミレーターの画面録画をGIFに変換する

# はじめに
私が記事を書き始めるようになってめっちゃ使うようになった技です。

# シュミレーターを画面録画する
`⌘` + `R`
録画に成功すると四角マークに変わります。

# 画面録画を終了する
四角マークを押します。
![スクリーンショット 2023-04-21 21.58.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/7fe61d2b-ffb6-cf83-def4-612651997e33.png)

# 画面録画をGIFに変換する
画面録画終了時右側に出てくるものを右クリックします。
![スクリーンショット 2023-04-21 22.02.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/200dbe71-5187-c878-c67d-c344754298f0.png)

「Save as Animated GIF」を選択します。
![スクリーンショット 2023-04-21 22.04.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/c11c0a9d-8e9a-d4fb-3f94-d382a841ba0c.png)

# おわり
Qiitaも動画を投稿できるようになるとありがたいです。。。
シュミレーターの画面録画であれば、簡単にGIFに変換できますが、
Macの画面録画だと別アプリでGIFに変換する作業が発生するのでちょっと面倒です。
データサイエンスのための線形代数 第16回 行列関数の性質

:::note info
本記事は数学講座[4.4 行列関数の性質](https://www.matongxue.com/lessons/525/parts/3138)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

# 行列関数の性質

[行列の乗法の演算規則](https://qiita.com/Junlee/items/1a1655f7de15d509e258#%E8%A1%8C%E5%88%97%E3%81%AE%E4%B9%97%E6%B3%95%E3%81%AE%E6%BC%94%E7%AE%97%E8%A6%8F%E5%89%87)のと同じで、行列関数も以下の性質があります。

```math  
\begin{array}{c|c}
    \hline
    \\
    \quad 交換律\quad&\quad 必ずしも成立しない\quad\\
    \quad スカラー倍交換律\quad&\quad \lambda(AB)=(\lambda A)B=A(\lambda B)（\lambdaが定数）\quad\\
    \quad 結合律\quad&\quad (AB)C=A(BC)\quad\\
    \quad 配分律\quad&\quad A(B+C)=AB+AC\quad\\
    \\
    \hline
\end{array}
```

# 交換律

行列関数$A,B$の乗法は、関数の複合を考えたらよいです。
```math  
AB=A\circ B
```
$A\circ B$が関数の複合の記号です。例えば、$y=f(x), y=g(x)$の複合が：
```math
f\Big(g(x)\Big)=(f\circ g)(x)
```

関数の複合は交換できないので、行列関数の交換もできないです。
```math
f(x)=x^2, g(x)=x-2
\\
複合をすると：
\\
f\Big(g(x)\Big)=(f\circ g)(x)=(x-2)^2
\\
≠
\\
g\Big(f(x)\Big)=(g\circ f)(x)=(x^2)-2
```

## 行列関数の複合

例えば、$A$のShear行列、$B$の回転行列：

```math  
A=\begin{pmatrix}1&k\\0&1\end{pmatrix},\quad B=\begin{pmatrix}\cos\theta&-\sin\theta\\\sin\theta&\cos\theta\end{pmatrix}
```
回転とShearの順番が違うと、結果も異なります$AB\ne BA$。

![2-_1_-1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/164a7e72-bf8f-a48c-790a-07ca705d92e5.gif)
と
![3-2 (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/eb1cfb71-6954-7ece-f618-0c5d32ffc40a.gif)

# 結合律

例えば、$A$のShear行列、$B$の回転行列、$C$が拡大縮小行列です：

```math  
\boldsymbol{A}=\begin{pmatrix}1&k\\0&1\end{pmatrix},\quad\boldsymbol{B}=\begin{pmatrix}\cos\theta&-\sin\theta\\\sin\theta&\cos\theta\end{pmatrix},\quad\boldsymbol{C}=\begin{pmatrix}1&0\\0&2\end{pmatrix}
```

$A(BC)$: 先に拡大縮小と回転をして、Shear：

![2-_1_.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/daa37338-9713-8a4b-e7ee-3376f2b8f1dc.gif)

$(AB)C$: 先に拡大縮小をして、回転とShear：
![3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/8d678b2b-d127-3e54-a953-b72e1ab7dc1a.gif)

$\boldsymbol{A}(\boldsymbol{B}\boldsymbol{C})=(\boldsymbol{A}\boldsymbol{B})\boldsymbol{C}$が分かります。


# 補足

$A,B$が$n$次元の行列で、$(A-B)(A+B)$の計算は：

```math
\begin{aligned}
    (A-B)(A+B)
        &=A(A+B)-B(A+B)&&配分律\\
        &=A^2+AB-BA-B^2&&配分律\\
\end{aligned}
```

$AB$と$BA$が必ずしも等しいではないです。
make(旧integromat)の５つの魅力

Integromatは、ビジネスプロセスの自動化を行うためのiPaaSサービスです。以下にIntegromatの魅力をいくつか紹介します。

### 1. 豊富なアプリケーションの連携

Integromatは、約500以上のアプリケーションとの連携が可能です。これにより、異なるアプリケーション間でのデータのやりとりを簡単に行えます。たとえば、Google SheetsとSlackを連携することで、Google Sheetsの内容を自動的にSlackに通知することができます。

‌

### 2. オートメーションの作成が容易

Integromatは、ビジネスプロセスの自動化を行うために必要なツールを提供しています。これにより、オートメーションの作成が容易になります。たとえば、Google Sheetsにデータが追加された場合に、Slackに通知を送信するオートメーションを簡単に作成することができます。

‌

### 3. データの変換が可能

Integromatは、データの変換を行うためのツールを提供しています。たとえば、CSVファイルをGoogle Sheetsにインポートする場合、Integromatを使用して、CSVファイルをGoogle Sheetsの形式に変換することができます。

‌

### 4. 高度なロジックが作成可能

Integromatは、高度なロジックを作成するためのツールを提供しています。たとえば、条件分岐やループ処理を使用して、ビジネスプロセスを自動化することができます。

‌

### 5. フレキシブルな料金体系

Integromatは、フレキシブルな料金体系を採用しています。月間の実行回数に応じて課金されるため、必要な分だけ使用することができます。また、無料プランも提供しているため、初めてIntegromatを使用する場合でも気軽に利用できます。

これらの魅力的な機能により、Integromatは、ビジネスプロセスの自動化を簡単に行えるようにし、生産性や効率性を向上させます。
悲報：ChatGPT英語できない（？）（改善案付き）＃１

**はじめに**
中学一年生のikkun084です。
さっきChatGPTで遊んでいたら驚きの事実が発覚したため、皆さんに伝えようと思い記事を書いています。
**本題**
なんとChatGPTはアルファベットをあまり理解していないようです。
言葉で説明するよりも、実際に見てもらった方が早いと思うので画像を見せます。
![スクリーンショット 2023-04-21 21.09.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/09b97a7a-da9b-2a2b-593c-bfaf21cbd4c7.png)
"W,G,Kのうち、アルファベット順で一番最初に来るのはどれでしょう？"という質問に対し、なんと"K"と答えたのです。
皆さんが知っているように、アルファベットは Aから順に、A,B,C,D,E,F,G、、、となり、この中で一番最初に来るのは"G"なのです。なんと完全に僕たちより馬鹿です。
しかし、
![スクリーンショット 2023-04-21 21.22.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/4827d659-c620-667e-372c-d1b26d656fc4.png)
このように、アルファベットを順番に言うことはできるようです。
そこで、もう一度最初の質問をしてみると、
![スクリーンショット 2023-04-21 21.24.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/7736dc20-7462-4904-8377-3502cd6478be.png)
なんと、正しい答えを出しました。
そこで、ChatGPTを質問の前の状態に戻して、このような質問をしてみます。
![スクリーンショット 2023-04-21 21.29.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/2e7c256e-87d2-f5ea-8b51-a219c3ba23c2.png)
今度は最初から正しい答えを出しました。
そして、この状態だと、
![スクリーンショット 2023-04-21 21.33.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/d43bffdf-75d1-ae8f-fa0e-8eb93bfd0087.png)
こうなります。
さらに、
![スクリーンショット 2023-04-21 21.39.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/9ab37a32-204c-ddf6-c3dc-c174a1c92b7d.png)
これらの結果から、２文字でもいいので、"アルファベットを並べる"ということをしてからなら、アルファベットの順番がわかるようになるようです。
そこで、問題文を少し変えてみます。
"アルファベット順で"ではなく、"アルファベット順に並べて"に変更します。
![スクリーンショット 2023-04-21 21.49.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/30b14965-d33c-f105-aa17-ad05ba027416.png)
ダメでした。
![スクリーンショット 2023-04-21 21.51.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3335275/0eee57cc-8eb6-7cd9-12d0-44ff64390a16.png)
**終わりに**
今回はChatGPTの弱点と、その改善案を紹介してみました。
これからももっといろんなChatGPTの弱点を見つけていきたいので、今後ともよろしくお願いします。
転職の記録

#  書いてあること，対象

- ITエンジニアの転職活動をした記録
- 主に前職の同僚の参考になれば

# 転職活動の大体の流れ

活動開始から終了（内定承諾）まで2ヶ月と少々だった。

1. [求人を探すサービスに登録](#求人を探すサービスに登録)
2. [応募に必要な書類の準備（2つで十分）](#応募に必要な書類の準備) 
3. [気になった求人に応募](#選考の流れ)

以下各項目の反省とか参考になりそうなこと

# 求人を探すサービスに登録

- いくつか登録したが最終的には転職エージェントと口コミ系のサービスをひとつずつ使うようになった。

## ある転職エージェントに登録した時の流れ

- ITエンジニアあたりに特化しているタイプのエージェント。
- オフィスに伺って担当コンサルタントと面談した。
    - 聞かれたことで覚えているのは転職の動機，技術的な興味，希望年収。
    - 転職の動機は本音（お賃金を上げたい）と建て前（高い技術を求められる業務をやりたい）を担当と考えた。

- ためになったアドバイス（うろ覚え）
    - `エンジニアとしての転職なので，技術的な興味というかこれからのキャリアプランはここではっきりさせた方が企業様も採用しやすい`
        - 今の自分の技術的な強みと，それからいえる一番良い感じのキャリアプランというのは担当と考えることができた。
    - `選考段階の足並みは揃えるべき`
        - 大抵は内定を承諾できる期限があるので，内定が出る時期がズレると超困る困った。
        - 期限を延ばしてもらうこともできなくはないが限度がある。
    - `面接時，絶対に希望する給与は聞かれる`
        - 自分の希望が身の丈に合っているかというのは担当コンサルタントと話さないとわからなかったと思う。

# 応募に必要な書類の準備

- 履歴書と職務経歴書の2つあれば選考に支障はなかった。GitHubアカウントとか提出できたらきっとベター。

-  履歴書
    - [yagishを利用した](https://rirekisho.yagish.jp/)
    - 面接当日に客先でスマホで作ったりした
- 職務経歴書
    - [dudaのものを使った](https://doda.jp/guide/syokureki/download.html)

# 選考の流れ

- 一番多かった流れが「カジュアル面談」 → 「選考に応募」。
    - 求人票にある選考フローと違うときもあった。
- どんな時も初めは自己紹介する。
    - 職務経歴書の内容を滞りなく話せるようになった方が良い。
    - 始め方
        - 名前，所属会社，年次を伝える
        - 「〇〇〇と申します。株式会社〇〇に〇〇年〇月に入社し，現在〇年目です。」
    - 職務経歴書にも書いたような内容
        - 滅茶苦茶に盛った。
    - 終わり方
        - 志望先で活かせそうなこと。志望先でやりたいこととか。
        - 私の場合は経験は浅いのと資格取得の面で勉強熱心な2点を考えて後者を多用した。

### カジュアル面談

- 企業側も事業内容とかを説明してくれる感じ。
- 採用担当 1人 ＋ 技術者 1-2人
- 技術とか人柄とかがマッチするか互いに確認する場だと思っている。
- カジュアル面談だと思ったらそうじゃなくてつらい思いをした。
    - 「当社の事業内容知ってるしテックブログも熟読されてきましたよね？」みたいな時がある。
    - 求人票や面接の日程調整の文言で大体わかるようになる。
DatabricksのWebターミナル

[Web terminal \| Databricks on AWS](https://docs.databricks.com/clusters/web-terminal.html) [2023/3/16時点]の翻訳です。

:::note warn
本書は抄訳であり内容の正確性を保証するものではありません。正確な内容に関しては原文を参照ください。
:::

DatabricksのWebターミナルは、Sparkドライバーノードでシェルコマンドを実行したり、VimやEmacsのようなエディタを使用できる便利で高度にインタラクティブな手段を提供します。[SSH](https://qiita.com/taka_yayoi/items/8d951b660cd87c6c5f18#%E3%82%AF%E3%83%A9%E3%82%B9%E3%82%BF%E3%83%BC%E3%81%B8%E3%81%AEssh%E6%8E%A5%E7%B6%9A)の使用とは異なり、Webターミナルは、一つのクラスターで多数のユーザーによって使用でき、キーのセットアップは不要です。Webターミナルの使用例には、リソース使用量の監視やLinuxパッケージのインストールが含まれます。

Webターミナルはデフォルトではすべてのユーザーに対して無効化されています。

[Dockerコンテナサービス](https://qiita.com/taka_yayoi/items/506fa9b15fd07fcac141)を有効化すると、Webターミナルを無効化します。

:::note warn
**警告！**
DatabricksはクラスターSparkドライバーのポート7681からWebターミナルサービスをプロキシーします。このWebプロキシーは、Webターミナルのみに使用されることを意図しています。クラスター起動時に占有されている、あるいは他の競合がある際には、Webターミナルは期待通りに動作しません。他のWebサービスがポート7681で起動されると、クラスターのユーザーは潜在的なセキュリティの悪用の影響を受ける可能性があります。Databricksでは、クラスターでサポートされていないソフトウェアのインストールによって生じるいかなる問題にも責任は持ちません。
:::

# 要件

- クラスターに対する[Can Attach To](https://docs.databricks.com/security/auth-authz/access-control/cluster-acl.html#cluster-level-permissions)権限。
- DatabricksワークスペースでWebターミナルが[有効化](https://docs.databricks.com/administration-guide/clusters/web-terminal.html)されている必要があります。

# Webターミナルの起動

Webターミナルを起動するには、以下のいずれかを行います:

- クラスター詳細ページで、**Apps**タブをクリックして**Launch Web Terminal**をクリックします。
- ノートブックで、ドロップダウンからアタッチされているクラスターを栗串、アタッチされているクラスターをクリックし、**Terminal**をクリックします。

新規タブでWebターミナルUIとBashプロンプトが開きます。ここで、クラスタードライバーノードのコンテナ内のrootとしてコマンドを実行することができます。
![](https://docs.databricks.com/_images/web-terminal-ui.png)

それぞれのユーザーは最大100のアクティブなWebターミナルのセッション(タブ)を開くことができます。アイドル状態のWebターミナルセッションはタイムアウトすることがあり、WebターミナルのWebアプリケーションは再接続して新たなシェルプロセスを起動します。Bashセッションを維持したい場合には[tmux](https://www.man7.org/linux/man-pages/man1/tmux.1.html)を使うことをお勧めします。

# 制限

- DatabricksではWebターミナルからのSparkジョブの実行をサポートしていません。さらに、DatabricksのWebターミナルは以下のクラスタータイプでは利用できません:
    - ジョブクラスター
    - 環境変数で`DISABLE_WEB_TERMINAL=true`が設定されて起動されたクラスター
    - [アクセスモード](https://docs.databricks.com/data-governance/unity-catalog/compute.html#access-mode)が**Shared**に設定されて起動されたクラスター
    - Spark設定`spark.databricks.pyspark.enableProcessIsolation`が`true`に設定されて起動されたクラスター
- 最初のページがロードされて、いかなる接続があり、アクティブだったとしても12時間後には停止されるハードリミットがあります。再接続するためにWebターミナルをリフレッシュすることができます。シェルのセッションを維持するためには[tmux](https://www.man7.org/linux/man-pages/man1/tmux.1.html)を使うことをお勧めします。
- [Dockerコンテナサービス](https://qiita.com/taka_yayoi/items/506fa9b15fd07fcac141)を有効化すると、Webターミナルを無効化します。

### Databricksクイックスタートガイド

[Databricksクイックスタートガイド](https://www.amazon.co.jp/dp/B09V1YXFVQ/)


### Databricks無料トライアル

[Databricks無料トライアル](https://databricks.com/jp/try-databricks)
SockJS-clientを使ってシンプルなリアルタイム通信を実現する方法

この記事では、SockJS-clientを使用してシンプルなリアルタイム通信を実現する方法について説明します。SockJS-clientは、WebSocketのようなオブジェクトをブラウザで使用できるようにし、さまざまなブラウザと通信プロトコルに対応するフォールバックオプションを提供するJavaScriptライブラリです。

# ステップ1: SockJS-clientをプロジェクトに追加する

npmを使用して、プロジェクトにSockJS-clientをインストールします。

```
npm install sockjs-client
```

# ステップ2: SockJS-clientをインポートする

プロジェクトのJavaScriptファイルで、SockJS-clientをインポートします。

```javascript
import SockJS from 'sockjs-client';
```

# ステップ3: SockJSオブジェクトを作成する

エンドポイントURLを指定して、SockJSオブジェクトを作成します。

```javascript
const sock = new SockJS('http://localhost:8080/your-endpoint');
```

# ステップ4: イベントリスナを追加する

以下のイベントリスナを設定して、接続、メッセージ受信、切断、およびエラーに対応できるようにします。

```javascript
sock.onopen = function() {
  console.log('SockJS connection opened');
};

sock.onmessage = function(e) {
  console.log('Received message:', e.data);
};

sock.onclose = function() {
  console.log('SockJS connection closed');
};

sock.onerror = function(error) {
  console.error('SockJS error:', error);
};
```

# ステップ5: メッセージを送信する

以下のように`send`メソッドを使用して、サーバーにメッセージを送信できます。

```javascript
sock.send('Hello, Server!');
```

# ステップ6: 接続を閉じる

必要に応じて、以下のように`close`メソッドを使用して、接続を閉じることができます。

```javascript
sock.close();
```

これが、SockJS-clientのシンプルな実装方法です。必要に応じて、さらに詳細なオプションや機能を追加できます。これで、簡単なリアルタイム通信が可能になります。SockJS-clientを試してみて、あなたのプロジェクトに活用してください。
データサイエンスのための線形代数 第15回 一般的な行列関数

:::note info
本記事は数学講座[4.3 一般的な行列関数](https://www.matongxue.com/lessons/523/parts/615)を勉強して投稿したメモです。詳細は元の素晴らしい講座のページをチェックしてください。
:::

回転関数以外に、一般的な行列関数がまだあります。こちらで他のよく利用されている行列関数を紹介します。

# 単位行列

単位行列は、単位$1$と同じです、単位行列をかけても、何も変わらないです。
$2\times 2$の単位行列が

```math  
\boldsymbol{A}=\begin{pmatrix}1&0\\0&1\end{pmatrix}
```
単位行列の列ベクトルも自然基底です。

```math  
\boldsymbol{c_1}=\begin{pmatrix}1\\0\end{pmatrix}=\boldsymbol{e_1},\quad\boldsymbol{c_2}=\begin{pmatrix}0\\1\end{pmatrix}=\boldsymbol{e_2}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/44f12840-0438-7cc3-79b6-c1f13686b86b.png)

その幾何的意味が、単位行列関数$Ax=y$で、どんなインプットのベクトルでも、アウトプットが変わらないです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/e021eea9-7321-f572-dd42-a761e95f1c7e.png)

# 鏡映変換行列

数学における鏡映（きょうえい、英: reflection）あるいは鏡映変換とはユークリッド空間の超平面を固定点集合にもつ等長変換である。

```math  
\boldsymbol{A}=\begin{pmatrix}0&1\\1&0\end{pmatrix}
```
その列ベクトルは単位行列と同じで、自然基底ですが、順番が違います。

```math  
\boldsymbol{c_1}=\begin{pmatrix}0\\1\end{pmatrix}=\boldsymbol{e_2},\quad\boldsymbol{c_2}=\begin{pmatrix}1\\0\end{pmatrix}=\boldsymbol{e_1}
```
そうすると、$Ax=y$関数を通して、インプットベクトル内の要素の順番が逆転になります。

```math  
入力ベクトル：\begin{pmatrix}x_1\\x_2\end{pmatrix}
\quad → 出力ベクトル：
\begin{pmatrix}x_2\\x_1\end{pmatrix}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/09ea5709-de02-7d36-f675-1b0a5f4a4980.png)

幾何的意味であれば、以下のように回転して：
![2-reflection.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/8669a01d-15b7-d4fc-44a0-ccddc39002fb.gif)

# 拡大縮小行列

```math  
\boldsymbol{A}=\begin{pmatrix}1&0\\0&k\end{pmatrix}
```
その列ベクトルが：

```math  
\boldsymbol{c_1}=\begin{pmatrix}1\\0\end{pmatrix}=\boldsymbol{e_1},\quad\boldsymbol{c_2}=\begin{pmatrix}0\\k\end{pmatrix}=\boldsymbol{ke_2}
```
そうすると、$Ax=y$関数を通して、インプットベクトル内の要素は、$y$が$e_2$の方向で$k$倍まで拡大になります。。

```math  
入力ベクトル：\begin{pmatrix}x_1\\x_2\end{pmatrix}
\quad → 出力ベクトル：
\begin{pmatrix}x_1\\kx_2\end{pmatrix}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/c909a9ee-60fb-97bc-914e-27718e34d7c5.png)
幾何的意味は以下の通りです。
![2-scale_.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/1e083dba-844b-a06b-6431-caad00a73149.gif)


# Shear 行列
```math  
\boldsymbol{A}=\begin{pmatrix}1&k\\0&1\end{pmatrix}
```
その列ベクトルが：

```math  
\boldsymbol{c_1}=\begin{pmatrix}1\\0\end{pmatrix}=\boldsymbol{e_1},\quad\boldsymbol{c_2}=\begin{pmatrix}k\\1\end{pmatrix}=\boldsymbol{e_2}+\begin{pmatrix}k\\0\end{pmatrix}=k\boldsymbol{e_1}+\boldsymbol{e_2}
```
そうすると、$Ax=y$関数を通して、インプットベクトル内の要素は、$y$が$e_1$の方向でへ移行移動しました。

```math  
入力ベクトル：\begin{pmatrix}x_1\\x_2\end{pmatrix}
\quad →出力ベクトル：
\begin{pmatrix}x_1 + kx_2\\x_2\end{pmatrix}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/ec1f06ca-1f96-2357-cbe3-cefd5fb5d80c.png)
幾何的意味は以下の通りです(以下の例では$k$が1ですので、右へ$1$の単位で移動しました)。
![2-shear.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3327130/873c23e6-8547-1507-c165-ae218516cc62.gif)
【phpmyadmin】「#1153 - 'max_allowed_packet'よりも大きなパケットを受信しました。」エラーが出た場合の対処法

# 概要
* phpmyadminでDUMPファイルをインポートしたら、パケットサイズの超過エラーが表示されました。今回はそのエラー解決方法を記します。

# エラー内容
* Dockerでphpmyadminを使ってデータベースにDUMPファイル（`.sql.zip`となっているもの）をインポートしたら、以下のエラーが表示されました。
    * phpmyadminの公式サイト：[インポートとエクスポート](https://docs.phpmyadmin.net/ja/latest/import_export.html)

```
#1153 - 'max_allowed_packet'よりも大きなパケットを受信しました。
```

* このエラーは、MySQLサーバーが受信したパケットのサイズが、許可されている最大パケットサイズ（`max_allowed_packet`）を超えていることを示しています。
* 解決するためには、パケットの最大容量の変える必要があるので、`max_allowed_packet`設定値を変更します。
* 変更は`my.cnf`ファイルで行います。

### 補足： 最大パケットサイズとは
* ネットワークを介して転送されるデータパケット（データ通信を行う際に分割されたデータの塊）の最大サイズのこと。
    * パケット：データを転送する際に分割される「荷物」のようなもの
* MySQLの場合、クライアントがサーバーに送信するSQL文や、サーバーがクライアントに送信する結果セットなどがデータパケットとして転送されます。
* MySQLは、デフォルトで`max_allowed_packet`を`16MB`に設定しています。

> この変数のデフォルト値が小さいのは、クライアントとサーバーの間の不正なパケットを捕捉するための予防措置であり、誤って大きなパケットが使用されてメモリー不足にならないようにするためでもあります。
引用元： [B.3.2.8 パケットが大きすぎます](https://dev.mysql.com/doc/refman/8.0/ja/packet-too-large.html)

* ただし、`max_allowed_packet`をあまりに大きな値に設定すると、MySQLのパフォーマンスに悪影響を与える可能性があるので、ネットワークの帯域幅などを踏まえて適切に設定してください。

# 解決方法は、設定ファイルのマウントorボリュームの永続化
* Dockerコンテナを使って起動している場合、コンテナの中に入って`my.cnf`ファイルを編集したところで、コンテナを一度閉じてしまうと、ファイルシステムが保存されず消えてしまいます。そうしないためには二つの方法があります。
    * データボリュームを永続化したり、バインドマウントを使用したりして、消えないようにする
    * コンテナ起動時に任意の`my.cnf`ファイルを適用するようにする
* 今回は、2番目の方法をとることにしました。

# 実施手順
①`my.cnf`ファイルで最大パケットサイズを変更する
②`docker-compose.yml`の設定を変更する

## ①`my.cnf`ファイルで最大パケットサイズを変更する
* `my.cnf`ファイルに以下のように追記します。この場合だと、MAXが512MBになります。

```my.cnf
[mysqld]
max_allowed_packet=512M
```

* 設定ファイルは、通常`/etc/mysql`にある`my.cnf`ファイルだと思いますが、以下のようにMySQLサーバーの設定ファイルを複数のファイルに分割して管理することができます。

```terminal
$ cd /etc/mysql
$ cat my.cnf

!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
```

* `!includedir`ディレクティブは、MySQLサーバーが起動する際に読み込む追加の設定ファイルを指定するためのものです。
* それぞれ以下のように使われる場合があります。
    * `/etc/mysql/conf.d/`ディレクトリに格納されたファイル: データベースの設定に関するオプション
    * `/etc/mysql/mysql.conf.d/`ディレクトリに格納されたファイル: MySQLサーバー自体の設定に関するオプション
* `mysqld.cnf `に`[mysqld]`のことがまとめて記載されていたので、今回はそちらに追記しました。

```mysqld.cnf 
[mysqld]
pid-file        = /var/run/mysqld/mysqld.pid
socket          = /var/run/mysqld/mysqld.sock
datadir         = /var/lib/mysql
max_allowed_packet=512M
```

## ②`docker-compose.yml`の設定を変更する
* `docker-compose.yml`ファイルに以下を追記します。

```yaml
version: "3"
services:
  mysql:
    image: mysql:latest
    volumes:
      - ./mysqld.cnf:/etc/mysql/mysql.conf.d/mysqld.cnf
```

* これにより、ローカルマシン上の`mysqld.cnf`ファイルを、MySQLコンテナ内の`/etc/mysql/mysql.conf.d/mysqld.cnf`にマウントしています。つまり、コンテナ起動時にMySQLサーバーが`mysqld.cnf`ファイルを読み込む際に、ローカルマシン上の`mysqld.cnf`ファイルの内容が適用されるようになりました。
* コンテナを再起動後、phpmyadminへインポートするとエラーが消えました。無事に最大パケットサイズが変更されたことが確認できました。
CentOS7 + Nextcloud環境下にphpMyAdminを追加する

# はじめに
基本的にこの記事で構築した環境で作業しています。

https://qiita.com/m4549071758/items/227c06fc2a4b79095864


## インストール
### phpMyAdmin
```
 # yum install --enablerepo=remi-php81 phpMyAdmin
```

### PHPのセッション保存ディレクトリ変更
``` /etc/php-fpm.d/www.conf
#session.save_path = "~~~"
↓コメント解除して変更
session.save_path = "/var/lib/php/session"
```
:::note info
PHPセッションディレクトリの権限変更は上記記事内ですでに済んでいるので飛ばします。
:::

### nginxの設定変更

httpsサーバーディレクティブの末尾に以下を追加します。
``` /etc/nginx/conf.d/nextcloud.conf
server {
    listen 443;

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

↓ディレクティブが閉じる前、末尾に追記

   location /phpMyAdmin {
      root /usr/share/;
      index index.php index.html index.htm;

      # IP制限 ---
      allow 192.168.1.0/24;
      deny  all;
      # ----------

      location ~ ^/phpMyAdmin/(.+\.php)$ {
          #nginx.confや上位ディレクティブでの設定にかかわらず,ここにもTCPかソケット通信かを明記しないと繋がりませんでした。
          fastcgi_pass   unix:/var/run/php-fpm/php-fpm.sock; 
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
      }
      location ~* ^/phpMyAdmin/(.+\.(jpg|jpeg|gif|css|png|js|ico|html|xml|txt))$ {
          root /usr/share/;
      }
    }
}
```

:::note alert
IPアドレス制限を行わない場合は、"phpMyAdmin"を意味不明でランダムな文字列に置き換えてください。
セキュリティ上、IPアドレス制限の設定を強く推奨します。
:::

### サービス再起動
```
# systemctl restart nginx php-fpm
```


## インストール後
インストール後は、https://example.com/phpMyAdmin でアクセスできます。
CoreDataをiCloudと連携させてアプリをリリースしたら、本番環境で連携できてなかった話

開発中はiCloudと連携していることは確認できていたので、アプリを再インストールした時にデータが復活していた。アプリの審査が通って手元でリリースアプリを動かしたところ、再インストール時にデータが復元できなくてめちゃくちゃ焦りました・・・

調べたところCloudKit Databaseのサイトにログインして、
Deploy Schema Changesというのをクリックして本番環境でもiCloud連携ができるように設定が必要でした。

しかし、クリックしたところエラーメッセージが表示。

![スクリーンショット 2023-04-21 20.21.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2706870/15d68476-4302-a88a-0f7e-28790b9256d2.png)


`Schema uuid stale, please fetch latest schema.`という謎のエラーが。
ググったところ色々情報が出てきて
`initializeCloudKitSchema`
の処理をすると直ると出てきたので試したところ

```kotlin
        container = NSPersistentCloudKitContainer(name: "hogehoge")
        container.loadPersistentStores(completionHandler: { (storeDescription, error) in
            if let error = error as NSError? {
                fatalError("Unresolved error \(error), \(error.userInfo)")
            }
        })
        container.viewContext.automaticallyMergesChangesFromParent = true
        // この2行を追加してエミュレーターで動かす。
        let options =NSPersistentCloudKitContainerSchemaInitializationOptions()
        try? container.initializeCloudKitSchema(options: options)
```

無事「Deploy Schema Changes」でエラーメッセージがなくなり本番環境でもiCloud連携が動くようになりました。
Docker+poetry 環境で python スクリプトを cronで定期実行する

# この記事は何？
Docker内にpoetryでpython環境を構築し、cron でpythonスクリプトを定期実行する処理を作成したときのメモです。

# フォルダ構成例
プロジェクト直下に Dockerfileやcrontabを配置し、app フォルダ内に実行スクリプトやpoetry関連ファイルを配置しています。

```
.
├── app/
│   ├── app.py
│   ├── poetry.lock
│   ├── pyproject.toml
│   └── ...
├── crontab
├── Dockerfile
└── docker-compose.yml
```

# Dockerfile
```dockerfile
FROM python:3.9.5-slim-buster


RUN apt update && apt install -y \
    curl \
    busybox-static

# poetryインストール
ENV PYTHONDONTWRITEBYTECODE=1 \
    POETRY_VERSION=1.3.2 \
    PYTHONUNBUFFERED=1
ENV POETRY_HOME=/opt/poetry \
    POETRY_VIRTUALENVS_CREATE=true
ENV PATH=$POETRY_HOME/bin:$PATH
RUN curl -sSL https://install.python-poetry.org/ | python -

# タイムゾーン設定
ENV TZ=Asia/Tokyo

WORKDIR /app
COPY ./app/ .
RUN poetry install

# cron関連
COPY --chown=root:root ./crontab /var/spool/cron/crontabs/root
CMD ["busybox", "crond", "-f", "-L", "/dev/stderr"]
```

## ポイント
* **busybox-static** をインストールし、crond を使用可能にしている。
* cronをそのまま使うとコンテナに設定した環境変数が反映されないが、busybox crond を使用することで特に設定を行わずに環境変数反映が可能。
* `ENV TZ=Asia/Tokyo` で日本時間でcronを実行できるように設定。
* `COPY --chown=root:root ./app/crontab /var/spool/cron/crontabs/root` で作成した crontab ファイルを実行可能権限をつけて crontabフォルダにコピーしている.
* `CMD ["busybox", "crond", "-f", "-L", "/dev/stderr"]` でコンテナを起動するときにcronを実行。フォアグラウンドで実行するための-fフラグと、標準エラーにログを記録するための-L /dev/stderrフラグを指定している。


# docker-compose
```yaml
version: '3.8'

services:
  batch:
    container_name: batch
    build:
      context: .
      dockerfile: ./Dockerfile
```
# crontab 指定例
* 時刻指定は適当です.
```
1-59 * * * * cd /app && poetry run python app.py
```

# 実行
```
docker-compose up -d
```

# cronログ確認
```
docker-compose logs -f
```

# 参考
以下を参考にさせていただきました。
* https://www.server-memo.net/tips/crontab.html
* https://shimoju.org/2017/10/09/busybox-crond/
* https://keep-memory.com/docker-busybox-crond
特許情報取得APIを使用して審判請求書の手続きの経緯を自動作成(easy_patents応用例4)

# 概要
特許等の権利化において、特許庁の審査官の判断に対して不服がある場合には、拒絶査定不服審判を請求できる。その拒絶査定不服審判を請求する場合、審判請求書に、一定のフォーマットで手続きの経緯や本願発明が特許されるべき理由などを記載する必要がある。
本稿では、審判請求書の手続きの経緯を、特許情報取得APIを用いて自動作成する方法を解説する。

# アウトプットイメージ
以下の記載例の部分を自動生成する。
![手続きの経緯.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2513217/2e518fcd-327e-010f-d585-7b7f79d72c78.png)

# サンプルコード
```py
from easy_patents.get_info import app_progress
from datetime import datetime as dt
import mojimoji


def make_progress_message(app_number):
    # 特許情報の取得
    progress_info = app_progress(app_number)

    # 手続の経緯に記載する書類の定義
    target_docs = {
            "拒絶理由通知書",
            "拒絶査定",
            "補正の却下の決定",
            "手続補正書",
            "意見書",
            "出願審査請求書",
            "特許願"
    }

    # progress_infoから対象の書類の情報を抽出し、legalDateでソートする
    biblio_info = progress_info['result']['data']['bibliographyInformation']
    doc_info_list = [doc_info for biblio in biblio_info
            for doc_info in biblio["documentList"]]
    target_doc_info_list = [doc_info for doc_info in doc_info_list
            if doc_info['documentDescription'] in target_docs]
    target_doc_info_list.sort(key=lambda x:x['legalDate'])

    # 対象の書類についての発送日・提出日などを文字列として作成する
    ret = []
    message_length = 25
    for target_doc_info in target_doc_info_list:
        legal_date = dt.strptime(target_doc_info['legalDate'], "%Y%m%d")
        document_desc = target_doc_info['documentDescription']
        legal_date_str = legal_date.strftime('%Y年%m月%d日')
        legal_date_str = mojimoji.han_to_zen(legal_date_str)
        space_length = message_length - len(document_desc) - len(legal_date_str)
        message = document_desc + "　" * space_length + legal_date_str
        ret.append(message)
    return '\n'.join(ret)


if __name__ == "__main__":
    print(make_progress_message("2007-035937"))
```

# 出力結果
```
出願審査請求書　　　　　　　２００７年０２月１６日
特許願　　　　　　　　　　　２００７年０２月１６日
拒絶理由通知書　　　　　　　２００８年０２月０５日
意見書　　　　　　　　　　　２００８年０４月０１日
手続補正書　　　　　　　　　２００８年０４月０１日
拒絶理由通知書　　　　　　　２００８年１０月２８日
意見書　　　　　　　　　　　２００８年１２月２６日
手続補正書　　　　　　　　　２００８年１２月２６日
拒絶査定　　　　　　　　　　２００９年０９月２９日
手続補正書　　　　　　　　　２００９年１２月１７日
```

# 備考
　記載例は和暦であるが、西暦でも実質的に問題はない（むしろわかりやすい）ので西暦とした。
　記載例では「起案日」があるが、法的な意味を持つ日付ではないので、発送日・提出日のみに限定した。もし、特許庁が起案日の記載を求めるのであれば、app_progressに「drafting_date」を追加してほしい。（拒絶理由通知書等からは取れるがめんどくさいので）
how to count the number of 1 in an integer variable

Given a signed integer variable,how can we count the number of 1 in this variable?

recently I was reading some computer text books where I met Parity Codes.To achieve this ,we have to count the number of 1 to determine whether the data was modified.

I guess the first thing to do is how we get each bit from a integer.
I have some possible ways here.the first one is shift operation,the second one is bitwise operation.

shift operaion

in c c++ and java we have shift operations like >> and << .
a>>1, it means we do a right shift operation once.but when it is done,we only get a modified variable. this operation is no use for gettting each bit.But its useful to get the next bit data in a variable.

how about bitwise operation?
we have AND OR NOT operation,which  way do you think can get bit from a varaible?
I guess,it's and bitwise operation.let's take some examples.

0101
   &
0001
   =
0001

0100
   &
0001
   =
0000

yes,we do get the first bit data from  a variable through this AND operation.


here is a c sample code.

int main(int argc, char* argv[])
{
	
	
	//

	int sum=0;	
	int testint=0;
	int bit=0;
	
	for(int i=0;i<32;i++)
	{
		
		bit=testint&1;
		if(1==bit)
		{
			sum++;
		}
		testint=testint>>1;
	}

	printf("%d",sum);

	return 0;
}
Flutterでデバイスから画像を選択し、画像を切り抜き縮小圧縮して、Firebase Strageにアップロードする

個人開発でFlutterを利用したアプリ開発を行っています。
ユーザーがアプリ内で画像を選択し、切り抜き・縮小・圧縮をかけた後に、Firebase Storageにアップロードする機能について解説します。

## 今回利用するパッケージ

デバイスから画像の選択

https://pub.dev/packages/image_picker

画像を切り抜き・縮小・圧縮

https://pub.dev/packages/image_cropper


## コード
```dart
Future<void> _selectAndUploadImage(context) async {
    //デバイスから画像を選択
    final XFile? image = await picker.pickImage(source: ImageSource.gallery);

    //画像を切り抜き縮小圧縮
    CroppedFile? croppedFile = await ImageCropper().cropImage(
      sourcePath: image!.path,
      aspectRatioPresets: [
        CropAspectRatioPreset.square,
      ],
      compressQuality: 70,
      maxHeight: 512,
      maxWidth: 512,
      uiSettings: [
        AndroidUiSettings(
            toolbarTitle: 'Cropper',
            toolbarColor: Colors.blue,
            toolbarWidgetColor: Colors.white,
            initAspectRatio: CropAspectRatioPreset.original,
            lockAspectRatio: false),
        IOSUiSettings(
          title: 'Cropper',
        ),
        WebUiSettings(
          context: context,
        ),
      ],
    );

    //Firebase Storageへアップロード
    uploadImage(croppedFile);

    //アップロード後の処理
}

// Firebase Strorageへアップロード
Future<String> uploadImage(CroppedFile f) async {
    final storageRef = FirebaseStorage.instance.ref();
    final gcsPath = "hoge/fuga";
    final uploadRef = storageRef.child(gcsPath);
    final uploadTask = uploadRef.child("image.jpg").putFile(File(f.path));
    final snapshot = await uploadTask.whenComplete(() {
      //
    });
    return gcsPath;
}
```

上記のコードを利用することで、アプリ内での画像選択から、画像の切り抜き圧縮をかけてFirebase Storageへのアップロードまでを実装できます。

Flutterが提供する豊富なパッケージは個人開発には便利です。
AWS認定クラウドプラクティショナー認定試験についてChatGPTに聞いてみた

## はじめに
業務の一環とスキルアップを兼ねて、[AWS認定クラウドプラクティショナー認定試験](https://aws.amazon.com/jp/certification/certified-cloud-practitioner/)を受けることにしました。
そこで、まずは概要から確認をしようと思い、ChatGPTに試験内容を整理してもらったので、参考までに投稿したいと思います。

## 注意事項
ChatGPTの回答ベースなので、間違っている箇所がある可能性が高いです。
勉強過程で間違いに気が付いたら適宜修正しようと思います。
ここ間違っているよ、というのがあればご指摘いただければと思います。

## プロンプト
ChatGPTに投げたプロンプトは下記になります。
```markdown
AWS認定クラウドプラクティショナー認定試験について、下記書式に従って概要と出題範囲を教えてください。

書式:
## 認定の試験概要

## 出題範囲と出題割合

## この試験で特に重要なサービス
### 1.{サービス名}
{サービスの概要}

なお、下記条件を満たす形で回答してください。
条件:
- サービスの概要は100～150文字程度でまとめる
- この試験で特に重要なサービス は10個程度挙げる
- この試験で特に重要なサービス は重要度の高い順に挙げる
```

以降は、ChatGPTからの回答をベースにした試験概要です。

---
## 認定の試験概要
AWS認定クラウドプラクティショナー認定試験は、AWSのクラウドに関する基本的な知識やベストプラクティスを持ったクラウドプラクティショナーとしてのスキルを評価する試験です。AWSのクラウドサービスやアーキテクチャ、セキュリティ、コスト最適化、AWSの運用など、幅広い領域の知識が必要とされます。

## 出題範囲と出題割合
- AWSのグローバルインフラストラクチャ（10%）
- AWSのセキュリティとコンプライアンス（20%）
- AWSのサービスとその利用方法（30%）
- AWSのアーキテクチャとベストプラクティス（30%）
- AWSの課金と料金最適化（10%）

## この試験で特に重要なサービス
### 1. Amazon S3
AWSのオブジェクトストレージサービス。無制限のスケーラビリティ、高い耐久性、低遅延のデータアクセスを提供し、データの保存、バックアップ、データレイクの構築など幅広い用途に利用される。

### 2. Amazon EC2
AWSの仮想サーバー。スケーラブルで柔軟な計算リソースを提供し、異なるインスタンスタイプやオペレーティングシステムの選択肢を持ち、様々なアプリケーションの実行に使用される。

### 3. AWS Lambda
AWSのサーバーレスコンピューティングサービス。コードを実行するためにサーバーの管理を不要にし、イベント駆動型のアプリケーションを構築できる。

### 4. Amazon RDS
AWSのリレーショナルデータベースサービス。MySQL、PostgreSQL、Oracle、Microsoft SQL Serverなどのデータベースエンジンをサポートし、管理、バックアップ、スケーリングなどの機能を提供する。

### 5. Amazon SNS
AWSのシンプル通知サービス。メッセージや通知を効率的に送信、受信、処理するためのトピックベースのメッセージングサービスであり、異なるエンドポイントに対して通知を送信するために使用される。

### 6. Amazon SQS
AWSのシンプルキューイングサービス。メッセージのキューイングおよびメッセージの受信・送信を行うことができる、分散型のキューサービスであり、異なるアプリケーション間での非同期メッセージングに使用される。

### 7. Amazon VPC
AWSの仮想プライベートクラウドサービス。仮想ネットワークを構築し、AWSリソースをセグメント化および隔離し、ネットワークのセキュリティを強化するために使用される。

### 8. AWS CloudFormation
AWSのインフラストラクチャのコード化を可能にするサービス。テンプレートを使用して、AWSリソースの作成、更新、削除を自動化し、インフラストラクチャの管理を効率化する。

### 9. AWS Identity and Access Management (IAM)
AWSのアクセス管理サービス。AWSリソースへのアクセス権限を制御し、ユーザー、グループ、ロールなどのアクセス許可を管理するために使用される。

### 10. AWS CloudWatch
AWSのモニタリングおよびログ管理サービス。AWSリソースの監視、ログの収集、アラームの設定などを行い、運用監視およびトラブルシューティングに使用される。

以上のサービスは、AWS認定クラウドプラクティショナー認定試験において特に重要であり、試験の出題範囲に含まれる可能性が高いです。試験に備えてこれらのサービスの概要や特徴を理解し、関連するベストプラクティスを学習することが推奨されます。

## 終わりに
サービス10個じゃ足りないかな。。。
とりあえず、ここで挙げたサービスの整理から進めていきたいと思います。
GPTエージェント化 : Auto-GPT を試行

# 概要
- autoGTP を動作させてみる
- open api key のみを用いる
    - optional で色々なサービスを使用できる模様




# autoGPT とは
- babyagi では、自動で目的達成まで動作する形式であった
- autoGTP では、エージェントとの対話形式がベース
    - 目的達成のためのプランを立て, 許可を求めてくる



# 環境
M1 mac



# openai api key 取得
https://qiita.com/Satoshi_Numasawa/items/8ab455ef0f97e61ae0e5



# setup
## install
```
git clone https://github.com/Significant-Gravitas/Auto-GPT.git
cd Auto-GPT
pip install -r requirements.txt
```

## write api key
```
cp .env.template .env
vi .env
```

```
OPENAI_API_KEY='sk-DUMMY_KEY
```



## run
```
./run.sh
```




# 使い方
## 以下を設定する
実行後, 以下を入力するよう求められる

- AI の名前
- 目的
- 目的達成のためのタスクリスト
    - 5個設定するが, 不要な項は空欄


## 例
- AI名
    - kura
- 目的
    - 科学者のリチャード・ファインマンについて調べて貰う
- タスクリスト
    - 指定の wikipedia page でリチャード・ファインマンの情報を取得する
    - 取得した text から、ファインマンの性格を考察し要約する
    - 結果を 'feynman.txt' へ出力する
    - 終了する


- 命名
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118627/317078a6-5b4a-5d88-bb9a-323a86e7c0ee.png)

- 目的設定
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118627/fe1fc6c7-0652-c173-c730-30e827a42a90.png)


- Task list
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118627/64350ad6-1373-0607-e8fb-d3028c251825.png)


- 動作中のサンプル. 許可を求められるので `y` を入力しプラン実行を許可する
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/118627/520ae579-a42d-f6a6-e5ac-9b7f1211f62d.png)




## 結果
以下へ書き出される
`auto_gpt_workspace/feynman.txt`

<details>  <summary>要約内容</summary>
Richard Feynman was an American theoretical physicist known for his work in quantum mechanics, quantum electrodynamics, and particle physics. He made significant contributions to the development of quantum electrodynamics and was awarded the Nobel Prize in Physics in 1965. Feynman also worked on the Manhattan Project during World War II and later became a professor at the California Institute of Technology. He was known for his engaging teaching style and popular science books, including "Surely You're Joking, Mr. Feynman!" and "The Feynman Lectures on Physics." Feynman died in 1988 at the age of 69.Richard Feynman was an American theoretical physicist known for his work in quantum mechanics, quantum electrodynamics, and particle physics. He made significant contributions to the development of quantum electrodynamics and was awarded the Nobel Prize in Physics in 1965. Feynman also worked on the Manhattan Project during World War II and later became a professor at the California Institute of Technology. He was known for his engaging teaching style and popular science books, including "Surely You're Joking, Mr. Feynman!" and "The Feynman Lectures on Physics." Feynman died in 1988 at the age of 69.


</details>








# 所管
- net 上から情報取得できるのが素晴らしい
    - 外に出れるので色々幅広く使えそう
- 日本語化したいところ