OmniAICreator/Qiita-1.07M huggingface dataset:
[Vuetify]Veutifyでv-imgタグをクリックしたときに内部リンクに遷移させる

# はじめに
Veutifyのv-imgコンポーネントをクリックしたときに内部リンクに遷移させたい場面があったので、実装方法をご紹介します。

公式ドキュメントを参考に進めていきます。

# 環境
- Vuetify：2.6.1

# 1. 実装方法

https://vuetifyjs.com/ja/api/v-img/#props

v-imgコンポーネントは、`props`で`to`を指定することができないため、
```vuejs
        <v-img
          to="/"
          :src="require('@/assets/logo.png')"
        >
        </v-img>
```
のように記述しても、遷移しません。

https://vuetifyjs.com/ja/api/v-img/#events

また、v-imgコンポーネントは`clickイベント`を設定できないため、メソッド内で遷移させることもできません。
```vuejs
        <v-img
          @click="goHome"
          :src="require('@/assets/logo.png')"
        >
        </v-img>
```

今回は、`router-link`で囲うことで遷移させることができました。
```vue
       <router-link to="/">
        <v-img
          :src="require('@/assets/logo.png')"
        >
        </v-img>
      </router-link>
```
以上で実装完了です。

公式ドキュメントを参考に、できないことを確認することも大事だなと思いました。

# 2. 参考文献

https://stackoverflow.com/questions/45962539/enclosing-a-router-link-tag-in-an-image-in-vuejs
【PHP】三項演算子、Null合体演算子、エルビス演算子

## 三項演算子
演算子の1つで、3つの項目を使用する唯一の演算子

`条件式 ? 式1 : 式2`

```php
<?php
$a = 100;
$b = 100;
echo $a === $b ? '$aと$bは同じ値' : '$aと$bは違う値';
```

※if文の省略形
if文だと3行以上のプログラムが1行で書くことができる。

## Null合体演算子
Nullかどうかを判断する。
Nullだった場合とそうでない場合で返す値を分岐する。

```php
<?php
$fruits = 'apple';
echo $fruits ?? 'nullでした';
```

$fruits にnull値が入ってる場合のみ??の右にある`nullでした`が出力される。
今回の場合は、$fruitsには`apple`が代入されているため、`nullでした`は出力されず、代入されている`apple`が出力される。

## エルビス演算子

```php
<?php
$a = 'apple';
echo $a ?: 'false';

=> apple
```

$a の値に`null`, `0`, `空文字`などが入っていた場合にfalseが出力される。
microk8sハマること(Kube内のDNSが参照できない,証明書)

## デフォでサービス名を参照しない
必須コマンド 
```microk8s enable dns```

microk8sでserviceのDNSが通ってなくて内側からアクセスできない
microk8sベットに設定必要(こんなん気づかんやんfuck)
https://microk8s.io/docs/addon-dns
PodないのDNSみて発覚
root@tasksapp-58b678577f-wkm2j:/# cat /etc/resolv.conf
search {ここに組織のドメイン名}
nameserver 127.0.0.53
options edns0 trust-ad


---
Kubeconfigがない
```zsh
taka@doktor:~/kn/knative-docs/docs/serving/samples/hello-world/helloworld-python$ kn service create helloworld-python --image=docker.io/{username}/helloworld-python --env TARGET="Python Sample v1"
Error: no kubeconfig has been provided, please use a valid configuration to connect to the cluster
Run 'kn --help' for usage
```
https://github.com/docker/compose-on-kubernetes/issues/59

移動して解決

---
vmを再起動するとmicrok8sが使えなくなってしまう
```
yama@yama-mk8s-1:~$ microk8s kubectl get node
Unable to connect to the server: x509: certificate has expired or is not yet valid: current time 2021-07-14T11:59:19Z is before 2021-07-14T19:32:55Z
yama@yama-mk8s-1:~$ microk8s status
microk8s is not running. Use microk8s inspect for a deeper inspection.
```
証明書切れの可能性があるが確認したら日数は残っていた
```
yama@yama-mk8s-1:~$ sudo microk8s.refresh-certs -c
[sudo] password for yama:
The CA certificate will expire in 3612 days.
```

期限が残っていたが証明書を更新することで解決
```
yama@yama-mk8s-1:~$ sudo microk8s refresh-certs
Taking a backup of the current certificates under /var/snap/microk8s/2264/var/log/ca-backup/
Creating new certificates
Signature ok
subject=/C=GB/ST=Canonical/L=Canonical/O=Canonical/OU=Canonical/CN=127.0.0.1
Getting CA Private Key
Signature ok
subject=/CN=front-proxy-client
Getting CA Private Key
1
Creating new kubeconfig file
Stopped.
Started.

The CA certificates have been replaced. Kubernetes will restart the pods of your workloads.
Any worker nodes you may have in your cluster need to be removed and re-joined to become aware of the new CA.

yama@yama-mk8s-1:~$ k get node
NAME          STATUS   ROLES    AGE   VERSION
yama-mk8s-3   Ready    <none>   37d   v1.20.7-34+984a1cd176537e
yama-mk8s-2   Ready    <none>   37d   v1.20.7-34+984a1cd176537e
yama-mk8s-1   Ready    <none>   37d   v1.20.7-34+984a1cd176537e
```
PowerAutomateの覚え


ちょっと業務で使うらしいのでまとめておきたいと思います。

# マニュアル
[Microsoft Power Automate ドキュメント](https://docs.microsoft.com/ja-jp/power-automate/)

# MicrosoftFlowとPowerAutomate
Microsoft Flowは、複数のタスクを自動化し、さまざまなクラウドアプリケーションとサービスを組み合わせることにより、ワーカーの生産性を向上させることに重点を置いたOffice365ツールでした。これらの自動化されたワークフローの作成により、通知の取得、ファイルの同期、データの収集などの可能性が提供されました。

最後に、Microsoftはそのツールの名前を変更し、Power Platformに含めることを決定し、MicrosoftPowerAutomate構造の一部になりました。
[What is Microsoft Power Automate? What about Microsoft Flow?](https://www.plainconcepts.com/what-is-microsoft-power-automate/)

# 重要な用語

**Triggers**
それらはワークフローを開始するものです。新しいドキュメントが保存されたときの新しいメール、またはYouTubeチャンネルの新しいビデオの場合があります。各コネクタには、少なくとも1つのトリガーがあります。

**Actions**
プロセスがすでに開始されている場合、実行するアクションを定義する必要があります。たとえば、ファイルをOneDriveにアップロードし、特定の人から電子メールを受け取ったときに承認プロセスを開始します…各フローには1つ以上のアクションがあります。

**Connections**
3番目の要素は、2つのアプリケーションを接続するタイミングを示します。これは、ツールが接続する各アプリケーションの資格情報を要求するためです。これらはMicrosoftのセキュリティで暗号化されており、必要に応じて簡単に削除できます。

# Power Automate の重要な概念

+ すべてのフローには、2 つの主な要素があります: トリガー と 1 つ以上の アクション です。
+ トリガーは、フローの開始アクションと見なすことができます。 トリガーには、受信トレイにある新しいメールや、Microsoft Lists のリストに追加される新しい項目などがあります。
+ アクションは、トリガーが呼び出されたときに実行させるものです。 たとえば、新しい電子メール トリガーでは、OneDrive for Business で新しいファイルを作成するアクションが開始されます。 他のアクションの例には、メールの送信、ツイートの投稿、承認の開始などがあります。


# 関連資料

+ [Send Reminder Email Using Power Automate Flow](https://www.c-sharpcorner.com/article/send-reminder-email-using-power-automate-flow/)
laravel Hashされた文字列と平文を比較

# 概要

- laravelにてHash化された文字列と平文の文字列を比較する方法をまとめる。

# ご案内

- laravelではなくPHPでHash化された文字列と平文の文字列を比較したい場合はこちら
    - [PHP ハッシュ化された値と通常の文字列を比較する](https://qiita.com/miriwo/items/c4f84b77bb163edecdcb)

# そもそも

- laravelのHash化はBcryptHasherが使用されている場合、結局vendorディレクトリ直下でPHPのpassword_hash()関数が用いられている。
    - [https://www.php.net/manual/ja/function.password-hash.php](https://www.php.net/manual/ja/function.password-hash.php)
    - [laravel Hashファサード 文字列ハッシュ化までの道](https://qiita.com/miriwo/items/b3fa105c28566d5f8cb7)
- これは不可逆ハッシュアルゴリズムなので、「一度ハッシュ化された文字列を平文に戻し、if文で文字列として比較する」なんてことはできない。（そもそもハッシュ化する文字列はそれなりに意味があってハッシュ化している。安易にコード内で平文に戻さないほうが良いのかもしれない。）

# 方法

- 下記のようにHashファサードを用いることで平文文字列とハッシュ化された文字列を比較する事ができる。

    ```php
    Hash::check(平文の文字列, ハッシュ化された文字列)
    ```

# 参考文献

- [laravel 8.x ハッシュ](https://readouble.com/laravel/8.x/ja/hashing.html)
- [https://readouble.com/laravel/8.x/ja/hashing.html#verifying-that-a-password-matches-a-hash](https://readouble.com/laravel/8.x/ja/hashing.html#verifying-that-a-password-matches-a-hash)
AWS Database Migration Service (DMS) でいくつかのテーブルにデータが入らないエラーを解消する方法

# 現象
AWS Database Migration Service (DMS) で複数のテーブルにデータを入れようとすると、いくつかデータが入らないテーブルが出てきます。

# 原因
テーブルにリレーションを張っていると、参照元テーブル→参照先テーブルの順にデータを入れないとデータが入りません。
しかしAWS Database Migration Service (DMS)は順番関係なくデータを入れようとしますので、データが入らないことがあります。

# 対応策
エンドポイントの「追加の接続属性」に

```
initstmt=SET FOREIGN_KEY_CHECKS=0
```

を入れておくことで、リレーションのエラーを回避させることができます。

エンドポイント→エンドポイント名を選択→右上の「アクション」ボタンを押し「変更」ボタンを押す→「エンドポイントの変更」画面で

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/561175/0a071ca7-4df9-2d16-bc0c-274df96fd14b.png)

このように設定して、「保存」ボタンを押します。


この設定をすると、接続中は外部キーエラーのチェックをしなくなるので、リレーションのエラーが出ずに、全テーブルのデータをきちんと入れることができます。

# 参考文献
[https://www.wantedly.com/companies/serverworks/post_articles/115869](https://www.wantedly.com/companies/serverworks/post_articles/115869)

[https://application-migration-with-aws.workshop.aws/ja/database-migration/create-source-and-target-endpoints.html](https://application-migration-with-aws.workshop.aws/ja/database-migration/create-source-and-target-endpoints.html)

[https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Target.MySQL.html](https://docs.aws.amazon.com/dms/latest/userguide/CHAP_Target.MySQL.html)
【C++】基礎を学ぶ②～文字列・数値を出力する～

# 文字列を出力する

文字列はダブルクォーテーションで囲います

```cpp
#include <iostream>

using namespace std;

int main(){
  cout << "Hello World!\n";
  return 0;
}
```
```
Hello World!
```

# 数値を出力する
数値はそのまま書くだけ
```cpp
#include <iostream>

using namespace std;

int main(){
  cout << 100;
  return 0;
}
```
```
100
```

# 文字列と数値を合わせて出力する
文字列と数値をシフト演算子`<<`でつなげる
```cpp
#include <iostream>

using namespace std;

int main(){
  cout << 123 << "円" << endl;
  cout << 100;
  cout << "円";
  return 0;
}
```
```
123円
100円
```

# 次の記事
[【C++】基礎を学ぶ③～整数同士の四則演算～](https://qiita.com/rapirapi/items/a9113d19dc371e4dde5e)
Unityゲーム制作奮闘記 - AudioClipによるメモリ使用量を削減する

## はじめに

本記事は、AudioClipがメモリを消費し過ぎることで、ゲームの起動が遅くなったり、
プレイに必要な必須メモリ量が増えてしまう、といった事象を解消する為に、
設定を見直した際の覚書です。

まず前提として、作成しているゲームは以下の音声を組み込んでいます。

◆前提
・キャラボイス：1000ファイル以上
・BGM：5ファイル前後
・SE：100ファイル前後

先に結論を書くと、
**キャラボイスのAudioClip設定から「Preload Audio Data」のチェックを外す**
というのが今回の本題です。

## 原因
まず、原因を簡単に整理すると以下になります。
①キャラボイスの量が多いこと
②**起動時に全音声ファイルを読み込んでいたこと**

①についてはボイスを減らすわけにもいかないので、
解消すべき原因は②になります。

見直し前は、ゲーム起動時に非同期で全AudioClipを読み込む処理にしていました。
```C#
AudioClip[] voiceClips = Resources.LoadAll<AudioClip>("Audio/Voice");
```
AudioClipの設定は、下記のようにLoad Typeを「Compressed In Memory」に変更していました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/401336/3f236a2e-b56f-deb0-ad01-19c7cbd5b339.png)
**Compressed In Memory：圧縮状態でメモリに格納**
上記の設定にしておけば起動遅延は殆ど感じなくなるのですが、
それでもファイル数が増えるとメモリをかなり使ってしまうので、やはり見直しが必要でした。

## 対策
検討の結果、今回の対策は以下にしました。
**①キャラボイス(AudioClip)の読み込みタイミングを「起動時」から「再生直前」に変更する
②キャラボイス(AudioClip)再生後に読み込んだ音声ファイルをアンロードする
③キャラボイス(AudioClip)のLoad Typeを「Decompressed On Load：ロード中に解凍」にする
④キャラボイス(AudioClip)の「Preload Audio Data：オーディオデータをプリロード」のチェックを外す**

但し、これは一概にこうすれば良いというモノでは無く、
再生直前で読み込むというのは当然負荷も増えるため、
再生遅延が生じる可能性があると想定されます。

今回のキャラボイスは、1ファイルのサイズが小さめ（5MB以下）なので殆ど遅延は無いですが、
サイズが大きいようなら別の設定を検討する方が良いかもしれません。

##### ①キャラボイス(AudioClip)の読み込みタイミングを「起動時」から「再生直前」に変更する
これは単純に再生処理の話です。
起動時のAudioClip読込み処理を無くして、代わりに再生直前に読み込みます。
```C#
AudioClip loadClip = Resources.Load<AudioClip>("Audio/Voice/" + name);
mainVoiceSource.clip = loadClip;
mainVoiceSource.Play();
```
##### ②キャラボイス(AudioClip)再生後に読み込んだ音声ファイルをアンロードする
これも再生処理の話です。
アンロードしないとメモリが解放されないので、見直した意味が無くなってしまいます。
※ただ「音声の再生が完了」してからアンロードする必要があると思われるので注意。
```C#
Resources.UnloadAsset(loadClip);
```

##### ③キャラボイス(AudioClip)のLoad Typeを「Decompressed On Load：ロード中に解凍」にする
Load Typeはそれぞれメリット/デメリットがあるため、音声の種類によって使い分ける必要があります。

**【Load Typeの種類】**
・Decompressed On Load：ロード中に解凍
　読込と同時にメモリへ展開する。
　再生負荷が少ないが、圧縮していない為、メモリ使用量が多い。

・Compressed In Memory：圧縮状態でメモリに格納
　圧縮されてメモリに載り、再生時に展開される。
　再生時に展開する為、再生負荷がかかるが、メモリ使用量は減る。

・Streaming：ストリーミング
　読込/展開を都度実行する。
　再生負荷は高いが、メモリ使用量は少ない。再生遅延が発生する。

色々調査してみると、以下となっている場合が多いようです。
・BGMはサイズが大きく、再生遅延が生じても問題ない為、Streaming
・サイズが小さいSE等は、Decompressed On Load
・ボイスやその他は、Compressed In Memory

ただ、今回の処理方法（再生直前にロードし、再生後にアンロード）を加味すると、
わざわざ負荷を上げる必要は無いので「Decompressed On Load：ロード中に解凍」にしました。

##### ④キャラボイス(AudioClip)の「Preload Audio Data：オーディオデータをプリロード」のチェックを外す
実は、今回メインで書きたかった内容はコレです。
上記①～③を設定する事でメモリ使用率が減ると想定していたのですが！
結果は…全然減らなかったのです。

①の対策で起動時の読込みは無くした筈なのに、どう見ても読込んでいるのです…
そして色々調べた結果、この「Preload Audio Data」のせいでした。

・Preload Audio Data：オーディオデータをプリロード
　アプリ起動時にメモリ上へ展開する。

もう見たままなんですが、デフォルトでこの設定になっている為、
全てのAudioClipがメモリ上に載ってたのです…

Preload Audio Dataをオフにする事で今回の設定変更が効き、
メモリ使用量を1/100程度まで削減出来ました。


## おわりに
Audioの設計も中々奥が深いですね。
今回はPCゲームなのでまだ良いですが、
これがスマホゲームなら致命的な問題になる可能性もあります。

同じ悩みを抱えている人に、何かしら参考になる部分があれば幸いです。
ここまでお読みいただき、ありがとうございました。
laravel Mockeryで定義したリポジトリインターフェースの戻り値が何を設定してもnullが帰ってくる

## 概要

- laravelにてMockeryを用いてDBへの問い合わせ処理部分のリポジトリインターフェースの関数の戻り値設定を行ったが何を設定してもnullが帰ってきてしまう問題の原因がわかったのでまとめる。

## 原因

- Mockeryで戻り値を指定しているリポジトリインターフェースの関数の戻り値指定がvoidになっていた。

## 各種クラス

- 使用しているコードをかなり簡素化して記載する。（このままコピペしても動作しないので注意）
- モック化したいリポジトリインターフェースクラスと関数

    ```FooRepositoryInterface.php
    <?php
    
    interface FooRepositoryInterface
    {
        public function update(Foo $foo): void;
    }
    ```

- テストコードによるモック化処理と戻り値設定

    ```Unit/FooTest.php
    <?php

    class FooTest extends TestCase
    {
    
        public function setUp(): void
        {
            parent::setUp();
            $this->FooRepository = Mockery::mock(FooRepositoryInterface::class);
        }
    
        public function test_何かしらのチェック(): void
        {
            // FooRepositoryInterfaceのupdate関数を実行した際、引数に関係なく「true」を返すようにMockeryを設定
            $this->FooRepository
                ->shouldReceive('update')
                ->andReturn(true);

            // アサーションによるチェック処理
        }
    ```

## 細かい原因

- FooRepositoryInterface.phpのupdateの戻り値のタイプヒンティング（型宣言）にてvoidが指定されてしまっていることが問題だった。
- Mockeryは当該のリポジトリインターフェースクラスを元にモックを設定している。
    - テストコード側のsetUp()関数でリポジトリインターフェースを元に生成したモックをプロパティーに登録している。

        ```Unit/FooTest.php
        public function setUp(): void
        {
            parent::setUp();
            $this->FooRepository = Mockery::mock(FooRepositoryInterface::class);
        }
        ```

- なのでいくら戻り値の設定をテスト関数無いで設定しても、もともとのリポジトリインターフェースの戻り値のタイプヒンティングの設定が勝ってしまい、戻り値を設定しても何も帰ってこない。
- ようは今回はモック化したい関数そのものの意図に反する戻り値をモックで設定してしまった。（本来戻り値がvoidの関数をモックで戻り値がtrueになるように設定）
- どうしてもモックの戻り値設定を生かしたいなら下記のようにリポジトリインターフェースの当該関数の戻り値のタイプヒンティングのvoidを消せば良い。（ただこれだと根本解決になっていないのであくまで問題の切り分け用としての確認方法になる。）

    ```FooRepositoryInterface.php
    <?php
    
    interface FooRepositoryInterface
    {
        public function update(Foo $foo);
    }
    ```
Elasticsearchで見る検索エンジンの仕組み(8): Kibana起動エラーのトラブルシューティング

##### [前回] [Elasticsearchで見る検索エンジンの仕組み(7): マッピング編](https://qiita.com/mingchun_zhao/items/ff5b538d27d31e5ef6da)

## はじめに

前回は、Elasticsearchのマッピングを理解しました。
今回は、Kibana起動失敗時のトラブルシューティングです。

## トラブル事象

- `kibana`コマンドでKibanaを起動したら、エラー発生
    - エラーログから、Elasticsearchノードに接続できずタイムアウトした模様
    - ElasticsearchノードのIPアドレス`172.23.224.1`がどうやら怪しい
    ```
    Unable to retrieve version information from Elasticsearch nodes.
    connect ETIMEDOUT 172.23.224.1:9200
    ```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/6dd9904a-2fd7-0ac4-1934-8389e05fad7f.png)

- Kibana画面には、`Kibana server is not ready yet`エラーが表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/cd195343-4138-c237-1d60-40b1160b5f7d.png)

## 原因調査

- エラーログに表示されたIPアドレスへ、pingコマンドで接続確認
    - 要求がタイムアウト、このIPアドレスは何者?

```
> ping 172.23.224.1

172.23.224.1 に ping を送信しています 32 バイトのデータ:
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。
要求がタイムアウトしました。

172.23.224.1 の ping 統計:
    パケット数: 送信 = 4、受信 = 0、損失 = 4 (100% の損失)、
```

- Kibanaの設定ファイル`config/kibana.yml`を確認
    - KibanaからElasticsearchへの接続先となる`elasticsearch.hosts`に問題IPアドレスが指定されていた
    - Kibanaセットアップ時に、動的に割り当てられていたIPアドレスが使用され、そのまま設定ファイルに記載されたか?
        - その後、OS再起動によりIPアドレスが変わったので、接続できなくなったかも

```
# This section was automatically generated during setup.
elasticsearch.hosts: ['https://172.23.224.1:9200']
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/d10f1dc4-faf9-62f7-87cb-5d9cb767ee21.png)


## 対処

- 開発環境のローカルに、ElasticsearchとKibanaを導入しているので
    - `elasticsearch.hosts`のIPアドレスをlocalhostに書き換える

```
elasticsearch.hosts: ['https://localhost:9200']
```

- Ctrl+CでKibanaを停止してから、`kibana`コマンドで起動
    - 今度は、起動ログにエラー発生せず

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/ff9a8623-dbdc-b053-115b-7418c31e95c5.png)

- Kibanaログイン画面も正常に表示される

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2523098/8dc900ce-51c9-a617-ae2f-f44710329f54.png)

## おわりに

Kibana起動エラー時のトラブルシューティングでした。
次回も続きます。お楽しみに。

##### [次回] [Elasticsearchで見る検索エンジンの仕組み(9): Kibana画面が応答しない事象のトラブルシューティング](https://qiita.com/mingchun_zhao/items/bf7f056f8fca0d82e0b2)
[JavaScript]moduleのexportとimport

## これなに？
JavaScriptにおける named exportとdefault exportの違い
Reactでの利用例

moduleを使う時に都度調べていたのですが、全然覚えないのでメモ


## default export
1ファイルから1つだけexportする時
defaultという名前でexportされる
```js
// アロー関数の場合のdefault export
const hoge = () => {
  // 処理
}

export default hoge;
```

```js
// 名前付き関数の場合のdefault export
// つまり関数宣言のdefault export
export default function hoge() {
  // 処理
}
```


## named export
1つのファイルから複数のmoduleをexportする時に使用
```js
export const tee = () => {
 // 処理
}

export const baru = () => {
 // 処理
}
```
```js
import {hoge, tee} from 'path'
```
---

## reactでよく使われるやつ
基本的に*default export*が使われる

*reactでnamed exportが使われる例*
```js:helper.js
// エントリーポイントでよく使われる
// 全てのexportしたコンポーネントを集めて
// ここから名前付きで再度exportする
{export default as Article} from './Article'
{export default as Content} from './Content'
```

```js
// メリットは親component側でimport文が
// 1行になること
import {Article, Content} from './helper.js'
```
deviseのサインアップにenumを使用したら, '0'is not a validとエラーが出る

## やりたいこと
- Railsのユーザ認証を行うgem deviseでサインアップするモデルのカラムをenumにしたい
- 該当するモデルのカラムはInteger型

```ruby
# app/models/user.rb
class User < ApplicationRecord
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable

  enum user_type: {
    user: 0,
    circle: 1
  }
end
```

```ruby
# db/schme.rb
ActiveRecord::Schema[7.0].define(version: 2022_07_02_083714) do
  create_table "users", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "user_type", default: 0, null: false
    t.string "name", null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
  end

end

```

## 発生した問題

- sign up 画面を編集するために以下のように`app/views/users/registrations/new.html.erb`を編集したところ、`ArgumentError in Devise::RegistrationsController#create '1' is not a valid hoge`のエラーが表示され、ユーザ登録できなかった。

```erb
# app/views/users/registrations/new.html.erb

<h2>Sign up</h2>

<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
  <%= render 'users/shared/error_messages', resource: resource %>

  <div class='field'>
    <%= f.label :email %><br />
    <%= f.email_field :email, autofocus: true, autocomplete: 'email' %>
  </div>

  ...略...

  <div class='field'>
    <div>
      サークルとして登録
      <!--  チェック時は0, 未チェック時は1を送信するように設定 -->
      <%= f.check_box :user_type, {}, 0, 1 %>
    </div>
  </div>

  <div class='actions'>
    <%= f.submit 'Sign up' %>
  </div>
<% end %>

<%= render 'users/shared/links' %>


```


- エラー画面
![Screen Shot 2022-07-07 at 7.12.21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/482077/d619bd0a-a823-b86d-288e-eed2e05b36f4.png)

## 解決策

- `app/views/users/registrations/new.html.erb`のフォームをenumのキーに変更する

```erb
# app/views/users/registrations/new.html.erb
...略...

## フォーム部分のチェック時の値を指定する箇所を数値から
-- <%= f.check_box :user_type, {}, 0, 1 %>

## 以下のようにenumのキーにする
++ <%= f.check_box :user_type, {}, :circle, :user %>
```

## 参考
- https://zenn.dev/yusuke_docha/articles/89b49fd29c16c6
【失敗例に関する記事】Controllerで使用しているインスタンスを、他のControllerへそのまま渡すのは難しい

他のControllerで使用されているインスタンスを、別のControllerへ受け渡して使うことができないか試みた。
具体的には、名前空間に別のControllerを記載し、メソッドの引数として指定しようとした。

↓以下のようなコードを書いてみた。　※失敗例なので参考にしても動きません

```php:ManualController
//呼び出される側のController
public function store(Request $request)
{
    $inputs=$request->validate([
        'title'=>'required|max:30',
    ]);

    $manual=new Manual();
    $manual->title=$request->title;
    $manual->user_id=auth()->user()->id;
    $manual->save();

    return redirect()->route('step.create');
}

public function getManual()
{
    return $this->manual;
}
```


```php:StepController
//呼び出す側のController
public function store(Request $request)
{
    $inputs=$request->validate([
        'body'=>'required|max:500',
        'image'=>'image|max:1024'
    ]);

    global $number;
    $step=new Step();
    $step->id=$number;
    $step->body=$request->body;

    $called = app()->make('App\Http\Controllers\ManualController');
    $manual = $called->getManual();
    $step->manual_id=$manual->id;

    if (request('image')){
        $original = request()->file('image')->getClientOriginalName();
        $name = date('Ymd_His').'_'.$original;
        request()->file('image')->move('storage/images', $name);
        $step->image = $name;
    }

    $step->save();
    $number++;

    return view('step.create', [
        'step_num' => $number,
    ])->with('message', 'このステップを保存しました');
}
```

結果的にうまくいかず。
代替案として、URLにモデルのIDを載せることで、URLから情報を取得する方法を採用した。
そちらに関しては、また別途記事を作成します。
数式が正しいと思えるが機能していないとき

+ [Formula with IF, OR, AND](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54S00000JfyPk)

:::note
I am an idiot... Need to use the API of the picklist values.. took by accident the Text and didn't realized
:::

選択リストがあれば、API名を使わずにラベルにしていることをチェックする

+ [式がうまくいかないことがありますか？](https://trailhead.salesforce.com/trailblazer-community/feed/0D54S00000JfsIG)

正直理解できません。

これを理解しようとして1年以上経った後、最終的に式のすべての値を小数点以下2桁に丸め、現在は正しく機能しています. これは、すべての通貨フィールドがすでに小数点以下 2 桁で設定されているにもかかわらずです。オブジェクトマネージャを確認すると、すべて「Currency(16, 2)」です。 


+ [Validation rule on dependent fields](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007epyQI)

:::note
Are the API values ​​in the picklist correct? Are you using labels?
:::

+ [実行中のユーザー数式が 1 人のユーザーに対して機能しない](https://trailhead.salesforce.com/ja/trailblazer-community/feed/0D54V00007eqaNN)

:::note
テキストを返す 2 つのテスト数式フィールドを作成できますか?

1番目のフィールド:
レポート担当者検索__r.Id

2番目のフィールド
$ユーザーID

少なくとも、2つを比較して、なぜこの特定のユーザーで機能しないのかを確認できます。
:::

+ [”商品名”という項目が空欄の場合に入力規則をかけたのですが、うまく挙動しません。 ](https://trailhead.salesforce.com/trailblazer-community/feed/0D5KX000000TcsU)

:::note
NOT()を付けた場合はどうなりますか？ 

これで何も起こらなければ、この項目のAPI名が違うのかもしれません
:::
STM32G031と温度センサーMCP9701で温度をシリアル出力(テーブル方式)

x MCP9701-E/TO 販売コード 103199

x PA2をGPIOにがわかる人むけ

目的
安価に温度を測る。

センター　400mV
ステップ　19.5mV 1℃

1 ADC
2 VDD
3 GND
4 Serial

8 SWD
7 SWD
6 未使用-未接続
5 未使用-未接続


![o_con566.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/30c564c8-6027-3ccd-0350-a049fd00f296.jpeg)



```c++


//SER_MCP9701_table_031_1

static const char tmp_t[]={
0*2+0,0*2+1,0*2+1,
1*2+0,1*2+1,1*2+1,
2*2+0,2*2+1,2*2+1,
3*2+0,3*2+1,3*2+1,
4*2+0,4*2+1,4*2+1,
5*2+0,5*2+1,5*2+1,
6*2+0,6*2+1,6*2+1,
7*2+0,7*2+1,7*2+1,
8*2+0,8*2+1,8*2+1,
9*2+0,9*2+1,9*2+1,
10*2+0,10*2+1,10*2+1,
11*2+0,11*2+1,11*2+1,
12*2+0,12*2+1,12*2+1,
13*2+0,13*2+1,13*2+1,
14*2+0,14*2+1,14*2+1,
15*2+0,15*2+1,15*2+1,
16*2+0,16*2+1,16*2+1,
17*2+0,17*2+0,17*2+1,
18*2+0,18*2+0,18*2+1,
19*2+0,19*2+0,19*2+1,
20*2+0,20*2+0,20*2+1,
21*2+0,21*2+0,21*2+1,
22*2+0,22*2+0,22*2+1,
23*2+0,23*2+0,23*2+1,
24*2+0,24*2+0,24*2+1,
25*2+0,25*2+0,25*2+1,
26*2+0,26*2+0,26*2+1,
27*2+0,27*2+0,27*2+1,
28*2+0,28*2+0,28*2+1,
29*2+0,29*2+0,29*2+1,
30*2+0,30*2+0,30*2+1,
31*2+0,31*2+0,31*2+1,
32*2+0,32*2+0,32*2+1,
33*2+0,33*2+0,33*2+1,
34*2+0,34*2+0,34*2+1,
35*2+0,35*2+0,35*2+1,
36*2+0,36*2+0,36*2+1,36*2+1,
37*2+0,37*2+1,37*2+1,
38*2+0,38*2+1,38*2+1,
39*2+0,39*2+1,39*2+1
};

static const char data[][5]={
"00.0","00.5","01.0","01.5","02.0","02.5","03.0","03.5","04.0","04.5","05.0","05.5","06.0","06.5","07.0","07.5","08.0","08.5","09.0","09.5",
"10.0","10.5","11.0","11.5","12.0","12.5","13.0","13.5","14.0","14.5","15.0","15.5","16.0","16.5","17.0","17.5","18.0","18.5","19.0","19.5",
"20.0","20.5","21.0","21.5","22.0","22.5","23.0","23.5","24.0","24.5","25.0","25.5","26.0","26.5","27.0","27.5","28.0","28.5","29.0","29.5",
"30.0","30.5","31.0","31.5","32.0","32.5","33.0","33.5","34.0","34.5","35.0","35.5","36.0","66.5","37.0","37.5","38.0","38.5","39.0","39.5"
};

#include <Arduino.h>

//初期化処理
void setup()
{

  delay(3000); //not delete

  //シリアルの初期化
  Serial.setTx(PA2_ALT1);
  Serial.setHalfDuplex();
  Serial.begin(9600);

} //setup

//メインループ
void loop()
{

  //センサーの値を読み込む
  analogReadResolution(12); // ADC 12bit mode
  int s = analogRead(A9);   // PB7  PIN1 031 センサーの読み取り値

  //温度の表示
  s = (s >> 3);
  if (s >= 184) {
    Serial.print("40.0");
  } else if (s <= 62) {
    Serial.print("-0.0");
  } else {
    Serial.print(data[tmp_t[s - 63]]);
  }
  Serial.println();

  //1秒の待ち
  delay(1000);

} //loop



```
M1 Macでarm版JupyterをDockerで使う．

## 目的

通常Jupyter LabをDockerで使う場合，Docker HubにあるJupyterが提供するDockerイメージを使えば良い．しかし，Dockerイメージがamd64版しかなく，M1 Macでもamd64版を動かすことになる．せっかくM1なのにamd64版を動かすのも面白くないので，arm64で動かしたい．

## 解決法

次のDocker fileを使えば arm64のJupyterを動かせる．

```
FROM python:3-slim
RUN apt-get -y update &&apt-get -y upgrade
RUN apt install build-essential -y
RUN pip install -U pip
RUN pip install numpy scikit-learn scipy matplotlib networkx ipython torch torchvision jupyterlab
RUN apt remove build-essential -y
RUN mkdir /opt/work
```

実行コマンドは次の通りである．
```
docker build -t タグ名 -f Dockerファイル ディレクトリ
docker run -i -t -p 8888:8888 -v $(pwd):/opt/work タグ名 /bin/bash -c "jupyter lab --notebook-dir=/opt/work --ip='*' --port=8888 --no-browser --allow-root"
```
実行するとURLが出てくるので，それをブラウザに打ち込めば動く．このコマンドは[Docker Hubのanaconda3のページ](https://hub.docker.com/r/continuumio/anaconda3)を参考にした．

## 備考

* Jupyter Labをインストールするためにbuild-essentialが必要だった．
* anaconda3でもarm版のJupyterが動くが，容量が大きいので使わなかった．
* Visual Studio CodeのRemote - Containersを使えばvscodeの機能を使いながらJupyterを動かせる．
Ectoのconfigに1行足してAuroraのフェイルオーバーに対応する

MyXQLやPostgrexのドキュメントを読めば書いてあるのですが、結構調査に時間がかかったのでメモ。

MySQLの場合は`disconnect_on_error_codes: [:ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION]`、また、PostgreSQLの場合は`disconnect_on_error_codes: [:read_only_sql_transaction]`を足せばＯＫです。

MySQLの例

```elixir
config :my_app, Repo,
  database: "ecto_simple",
  username: "user",
  password: "pass",
  hostname: "localhost",
  disconnect_on_error_codes: [:ER_CANT_EXECUTE_IN_READ_ONLY_TRANSACTION]
```

### 備考: Auroraのフェイルオーバー問題とは

AWSのAuroraはMultiAZでフェイルオーバーすると、ReaderとWriterのノードが入れ替わります。このときEctoのようなコネクションをプールするDB接続ライブラリでは、Writerのつもりで入れ替わったReaderに書き込みリクエストを送り、エラーになるという現象が起きます。

このように読み取り専用DBに書き込みリクエストを送ったエラーが出たときに、DB接続ライブラリがプールしていたコネクションを破棄して再接続してくれれば、システム全体としては自動復旧します。逆に破棄してくれないとすると、故障した状態が維持されてしまい、最悪手動で再起動が必要な事態になってしまいます。

ただ、"読み取り専用DBに書き込みリクエストを送ったエラーが出たときに、DB接続ライブラリがプールしていたコネクションを破棄して再接続"はAuroraでは必須でほしい挙動ですが、Aurora以外のMySQL/PosgreSQLを使っている場合は逆に意味不明な挙動です。よってEctoではオプショナルなのだと思います。他のDB接続ライブラリだと、例えばActiveRecord (Rails)では設定オプションで有効にもできないので、自分でモンキーパッチをあてて解決する方法が有名だったりします。

### 参考

* [Ecto\.Repo — Ecto v3\.8\.4](https://hexdocs.pm/ecto/Ecto.Repo.html)
* MyXQLのドキュメントに書いてあるdisconnect_on_error_codesの説明
    * https://hexdocs.pm/myxql/MyXQL.html#start_link/1-disconnecting-on-errors
* Posgrexのオプション
    * https://hexdocs.pm/postgrex/Postgrex.html#start_link/1-options
* 関連PR
    * [Disconnect on read\-only transaction error by wojtekmach · Pull Request \#414 · elixir\-ecto/postgrex](https://github.com/elixir-ecto/postgrex/pull/414)
文字コード【character code】キャラクターコード

![d3a2218dfb801446034f3ac9a51402dd.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637823/a099f1d6-ea66-71d3-f8ca-132f77e8ffd4.png)
図引用元 URL

https://www.nexaweb.co.jp/column/it-sampo/2192/

## 符号化文字集合と符号化形式
>１．符号化文字集合:「文字」と「文字に割り当てた番号」の対応表
>２．符号化形式:「文字に割り当てた番号」と「実際にコンピュータさんが扱う数字」の対応表
>参考：アスキーコードなどは「文字に割り当てた番号」と「実際にコンピュータさんが扱う数字」が同じ

引用元 URL

https://wa3.i-3-i.info/word15291.html


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/637823/0d1f3c9e-8bc3-0032-d667-e27c2ad4a855.png)

図引用元 URL

https://qiita.com/omiita/items/50814037af2fd8b2b21e


## UnicodeEncodeError
→エンコードできなかった際に発生する
### 「あ」のエンコード結果
"あ".encode('utf-8')  >>> b'\xe3\x81\x82'
"あ".encode('cp932')  >>>  b'\x82\xa0'
### 「�」のエンコード結果
"�".encode('utf-8')  >>>  b'\xef\xbf\xbd'
"�".encode('cp932') >>> UnicodeEncodeError

|項目|説明|備考|
|----|----|----|
|b’...‘|バイトコード||
|u’...‘|Uniコード（python3.xからは不要）||
|\x○○|16進数hexを表す||

### BOM
#### "あ" encode('utf-8')
||BOM|BOM|BOM||||
|----|----|----|----|----|----|----|
|10進数||||227|129|130|
|16進数||||e3|81|82|
|10進数|239|187|191|227|129|130|
|16進数|ef|bb|bf|e3|81|82|


 
## ASCII 
・7ビット(2^7)で表現
・先頭の「0」(=1ビット)は「パリティ」
|-|上桁（2進数）|0000<br>制御|0001<br>制御|0010|0011|0100|0101|0110|0111|
|----|----|----|----|----|----|----|----|----|----|
|<b>下桁（2進数）</b>|16進数|0|1|2|3|4|5|6|7|
|<b>0000</b>|0|NUL|DLE|SP|0|@|P|`|p|
|<b>0001</b>|1|SOH|DC1|!|1|A|Q|a|q|
|<b>0010</b>|2|STX|DC2|"|2|B|R|b|r|
|<b>0011</b>|3|ETX|DC3|#|3|C|S|c|s|
|<b>0100</b>|4|EOT|DC4|$|4|D|T|d|t|
|<b>0101</b>|5|ENQ|NAK|%|5|E|U|e|u|
|<b>0110</b>|6|ACK|SYN|&|6|F|V|f|v|
|<b>0111</b>|7|BEL|ETB|'|7|G|W|g|w|
|<b>1000</b>|8|BS|CAN|(|8|H|X|h|x|
|<b>1001</b>|9|HT|EM|)|9|I|Y|i|y|
|<b>1010</b>|A|LF|SUB|*|:|J|Z|j|z|
|<b>1011</b>|B|VT|ESC|+|;|K|[|k|{|
|<b>1100</b>|C|FF|FS|,|<|L|\|l|||
|<b>1101</b>|D|CR|GS|-|=|M|]|m|}|
|<b>1110</b>|E|SO|RS|.|>|N|^|n|~|
|<b>1111</b>|F|SI|US|/|?|O|_|o|DEL|

### 例 
|文字|上桁|下桁|文字コード|
|----|----|----|----|
|A|0100|0001|01000001|

### 制御文字
「0000」と「0001」の2列を制御文字という


## 比較

|コード名|サイズ|備考|
|----|----|----|
|ASCII|7bit(=2^7)||
|Jis|1byte(=8bit =2^8)||
|SJis|2byte(=16bit =2^16)|Windows|
|EUC|2byte or 3byte(補助漢字など)|UNIX|
|Unicode|1~6byte可変長|世界中の文字に対応|
[UE5] ルートモーションのリターゲットがうまくいかない場合の確認事項

ルートモーション有りのアニメーションをリターゲットするとき、毎回うまくいかないので確認事項をメモ

### リターゲット元のアニメーションはルートモーションのチェックを外す
アニメーションシーケンスでルートモーションが問題ないか確認したまま、チェック外してないことがよくある。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426502/1ef9f22f-7c20-424f-27d9-ab4c2c8917e6.png)

### IKリターゲッターのトランスレーションモードの変更
UE5の初見殺しの1つだと思いますが、IKリターゲッターのチェーンマッピングで、`Root` となるターゲットチェーンを選択し、  
その上の詳細タブの「FKアドジャストメント」→「トランスレーションモード」を `Globally Scaled`に変更する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426502/a031bd57-f82d-e0fa-fd97-41db465ee0e1.png)

### アニメーションBP上の設定  
アニメーションBPでアニメーションモンタージュ以外でルートモーションを再生する場合、
「クラスのデフォルト」→「ルートモーション」→「Root Motion Mode」を `Root Motion From Everything` などに変更する必要がある。  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426502/40941bc3-e023-bb89-8d39-ae1c2800b8d0.png)
（環境によっては「クラスのデフォルト」が隠れてしまって見つけにくいかも）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426502/8541858d-eacb-ac74-634b-3dd04c7d7374.png)

他思い出したらまた追記します。
【React / Next】遷移元を検知できるようにする

個人的な備忘録です。

# やりたいこと
- 特定の遷移元からしか、ページを表示できないようにしたい
- vue-router のように、「from」の情報を取得したい
- userRouter には遷移元の情報がない
- document.referrer では正確な情報が取得できない

# 環境
- Next: 11.1.3
- React: 17.0.2

# パターン1：Contextを使用したパターン
```tsx:hooks/historyContext.ts
import { createContext } from 'react';

export const HistoryContext = createContext<string[]>(['', '']);
```

```tsx:pages/_app.tsx
import { useEffect, useState } from 'react';
import { HistoryContext } from 'hooks';
import type { AppProps } from 'next/app';
import { useRouter } from 'next/router';

const MyApp = ({ Component, pageProps }: AppProps) => {
  const router = useRouter();
  const [history, setHistory] = useState([router.asPath, '']);

  useEffect(() => {
    setHistory([router.asPath, history[0]]);
  }, [router.asPath]);

  return (
    <HistoryContext.Provider value={history}>
      <Component {...pageProps} />
    </HistoryContext.Provider>
  );
};

export default MyApp;
```

```tsx:component
import { useContext, useEffect } from 'react';
import { useRouter } from 'next/router';
import { HistoryContext } from 'hooks/historyContext';

export const Component = () => {
  const history = useContext(HistoryContext);
  const router = useRouter();

  useEffect(() => {
    // 特定のページから遷移してきたか特定
    const isFromHoge = history[0].includes('hoge');

    // 特定のページから遷移していなければ、強制的に別のページへ飛ばす
    if (!isFromHoge) {
      router.replace('/foo');
    }
  }, []);

  return (
    <></>
  )
};

```

# パターン2：SSRを使用したパターン
```tsx:pages/hoge.ts
import { GetServerSideProps } from 'next';
import { useRouter } from 'next/router';

interface Props {
  referer?: string;
}

const Component = ({ referer }: Props) => {
  const router = useRouter();

  return <></>;
};

export const getServerSideProps: GetServerSideProps = async (context) => {
  // あれば fetch

  // context の中に遷移元の情報がある
  const referer = context.req.headers.referer;

  return { props: { referer } };
};

export default Component;

```


# 参考
https://stackoverflow.com/questions/55565631/how-to-get-previous-url-in-nextjs
[宇宙一わかりやすい] n + 1 問題とはなにが問題なのか

# はじめに

バックエンド側の開発を行っているとかならず遭遇するN+1問題。
今回は初心者向けにN+1問題はなぜ避けるべき対象とされているのか。例えを用いて分かりやすく解説していきたいと思います。


# 対象読者
- 初心者エンジニア
- Rails を触り始めたエンジニア

# N+1問題とは

> ループ処理の中で都度SQLを発行してしまい、大量のSQLが発行されてパフォーマンスが低下してしまう問題のことです。

まずはN+1問題の概要から。どうやらDB周りの処理によってパフォーマンスが低下してしまう問題のようですね。これだけだといまいちよく分からないかも知れません。ただパフォーマンスが低下するということはつまり非効率な動作を行なってしまっているという理解までできていれば問題ないです。

# 非効率性を身を持って体感してみよう
ではN+1を根底から理解するため、実際に検索行為という例えを通して非効率性を体感してみましょう。早速お好きなブラウザを開いて、以下の単語の検索結果を表示してください。そして一番最初の結果のURLをメモしておきましょう。

- ActiveRecord
- prisma
- TypeORM

メモしておきましたか？ありがとうございます。それでは次はまた頭から検索して、今度はその二番目の結果のURLを教えてください。さっきは言いませんでしたが、二番目のサイトも私は知りたかったのです。

え？だったら最初からそう言えって？？素晴らしい！あなたはもうN+1問題を十分に理解しています。ええ、お分かりであるように三回で済むはずの検索行為が六回と二倍にまで膨れ上がってしまいました。この行為は非効率と呼ぶべき代物ですね。これがソフトウェアにおいてN+1問題と呼ばれる現象を現実に持ち込んだ一例になります。

# 実際の問題に当てはめてみる

> ループ処理の中で都度SQLを発行してしまい、大量のSQLが発行されてパフォーマンスが低下してしまう問題

こちらを先ほどの例に当てはめてみましょう。

「URL取得処理の中で都度検索をしてしまい、大量の検索が行われてパフォーマンスが低下してしまう問題」

どうでしょうか。先ほどの見た時よりも理解しやすくなっているのではないでしょうか？本来少ない数で済むはずの行為が繰り返し処理によって無駄に処理が増える現象。これがN+1問題と呼ばれる状態を指すことが理解できたと思います。

それでは実際のN+1問題が発生しているコードも載せておきます。

```ruby
# 全ての映画情報を取得
Movie.all.each do |movie|
  # directorテーブルから名前を取得し、カンマ区切りで結合する
  director_names = movie.directors.pluck(:name).join(",")
end
```

このようなコードは一度取得したあと再度別の情報にアクセスしているため、n+1問題が発生し、パフォーマンスが低下します。先ほどの三件ほどの検索でしたら少し筆者に腹が立つくらいで済むでしょうが、一万件ともいけば訴訟ものです。

# 対策
ではN+1問題の対策はどうすればいいのでしょうか？実は既にあなたは答えを導き出しています。

>え？だったら最初からそう言えって？

そうです。最初のデータを取る前に必要なデータは何が必要か明示しておけば良いんですね。以下のコードのように最初に使う予定のテーブルもまとめて一度のクエリで取得してしまえば、効率的にデータを取得することができます。

```ruby
# 全ての映画情報を取得
Movie.preload(:directors).all.each do |movie|
  # directorテーブルから名前を取得し、カンマ区切りで結合する
 director_names = movie.directors.pluck(:name).join(",")
end
```

※　Rails には `preload`, `eager_load`, `includes` 等いくつかN+1問題に関わるメソッドが存在しますがここではその違いについては解説しません。詳しい説明が欲しい方は以下記事を参考にすると良いかもしれません。

https://qiita.com/k0kubun/items/80c5a5494f53bb88dc58

# おわりに
N+1問題についていままで解説を読んでも理解できなかった方々へ少しでも理解につながれば幸いです。

また、検索対象とした文字列は全てORMと呼ばれるN+1問題に関わるライブラリです。最近勢いのある `prisma` などはもとからN+1問題を防ぐ機構が備えてあるらしく、いずれN+1問題について気にせずに開発できる時代が来るかもしれません。

# 参考記事
https://qiita.com/massaaaaan/items/4eb770f20e636f7a1361

https://zenn.dev/alea12/articles/15d73282c3aacc
【Python】AmazonAPIを使って自分が欲しい商品の値下げをLINEに通知

# 【ソースコード】
```
import requests
from bs4 import BeautifulSoup # データの抽出を行うためのライブラリ
import time

url = "AmazonのURL"

# トラッキングの設定
def amazon_tracking_price():
    amazon_page = requests.get(url)
    soup = BeautifulSoup(amazon_page.content, "html.parser") # BeautifulSoup(調べたい内容：Amazonページのコントテンツの内容，調べ方：html形式で解析)
    # print(soup)

    title = soup.find(id = "productTitle").get_text() # find(ここの設定は"find()の中身の決め方"を参考)
    price = soup.find("span", class_="a-price-whole").get_text().replace(',', '')
    print(title)
    print(price)
    
    # 通知する価格を設定
    if int(price) < 8000:
        send_line_notify(price)

# LINEに通知    
def send_line_notify(price):
    print("lineに通知がいきした")
    line_notify_token = "発行した自分のトークンをここにペースト"
    line_notify_api = "https://notify-api.line.me/api/notify" # LINEへの通知のためのAPI
    notification_message = "価格：" + price + "円になりました．" + url # 通知メッセージの内容
    headers = {"Authorization": f"Bearer {line_notify_token}"}
    data = {"message": f'message: {notification_message}'}
    requests.post(line_notify_api, headers=headers, data=data)

while(True):
    print("トラッキングしました")
    time.sleep(60*60*24)
    amazon_tracking_price()

```

## Requests, BeaufifulSoupのインストール
下記のコマンドをコマンドプロンプト(または，ターミナル)から実行することでimportが可能になる
```
pip install requests
pip install beautifulsoup4
```

## find()の中身の決め方
1. 商品ページに行きディベロッパーページ[F12]を開く．
2. 下記の画像の赤丸のアイコンをクリック
3. カーソルを価格のところに合わせるとそこに対応するhtmlのコードがハイライトされる
4. ハイライトされたコードのclass名 or id名 をコピー
5. find() の中にペースト
![スクリーンショット 2022-07-07 011229.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725707/f12e9481-0a09-d1a9-d0fe-d650424f3cdf.png)

## LINEへの通知のためのAPI
下記のリンクにアクセスし，画像のURLをコピーしline_notify_api = ""に貼り付ける
https://notify-bot.line.me/doc/ja/
![スクリーンショット 2022-07-07 012015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725707/2f8ce9ca-c6ae-7e91-5e4e-36400c0e493c.png)

## line_notify_tokenの発行
1. 下記のページから自分のアカウントへログイン
1. マイページへ移動
1. アクセストークンの発行(開発者向け) から「トークンを発行する」を押す
1. 発行されたトークンをコピーしてペースト
https://notify-bot.line.me/ja/
![スクリーンショット 2022-07-07 012509.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725707/9219c51d-0a04-ce3d-17f6-4a881db5f95b.png)

## 実行結果
![Screenshot_20220707-013639.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2725707/d655f701-78c5-23c7-93ad-41e6441d2fa7.png)
【Django】詳細ページをfunction-based viewで作成する。

　こんにちは、k_ukiです。現在Djangoで、卒業研究のWEBアプリケーション開発をしております。
　その中で、モデルのpkに応じて内容を切り替える、詳細ページの作成をしました。また、複数のメソッドを掛け合わせる必要があったため、簡単に実装できる"class-based view"ではなく、拡張性の高い"function-based view"で実装をしました。今回は、その実装方法についてまとめていきます。
## urls.pyを実装する
まずは、urls.pyを編集し、ルーティングと参照するviews.pyの関数を指定していきます。
```
from django.urls import path
from .views import detail_func
from . import views 

urlpatterns = [
  path('suggest_result/<int:pk>/', detail_func, name='search_word'),
]
```
　urlの指定の際に書いてある ＜int:pk＞は、渡すオブジェクトの主キーを表しています。例えば、「suggest_result/1」というurlにアクセスした場合、pkが1番のオブジェクトの詳細ページであることを示唆しています。
　pathの第二引数である"detail_func"は、このurlにアクセスした際に参照する関数名を記載しています。今回だとviews.pyにあるdetail_funcを実行することになります。
　pathの第三引数である「name='search_word'」は簡単にいうと「urlにアクセスするためのショートカットキー」のようなものです。renderなどで遷移する際にurlを入力する代わりに、ここに書いた文字列を指定することで画面を遷移することができます。※Railsに触れている人だと「名前付きパス」といった方が分かりやすいかもしれません。

## views.pyを編集する
```
def detail_func(request, pk):
    object = SearchWord.objects.get(pk=pk)
    # viewに渡す物を辞書型配列に変換
    context = {'object': object}
    return render(request, 'search_word/suggest_result.html', context)
```
　detail_funcの引数に<b>requestとpk</b>の二つを指定しています。これらについて解説していきます。<b>request</b>はページにアクセスしようとした際に送信されるHttpRequestオブジェクトのことです。例えば、urlがhttpなのかhttpsなのかといった情報が含まれます。また、第二引数のpkには、渡したいオブジェクトの主キーが入ります。ここでpkを受け取ることによって特定のオブジェクトを取得できるようになるのです。その特定のオブジェクトを取得しているのが下記のコードになります。
```
object = SearchWord.objects.get(pk=pk)
```
　"SearchWord"は取得するモデル名のことです、"objects.get(pk=pk)"とすることによって、先ほど渡したpkを基にSearchWordモデルのオブジェクトを1件取得してくることができます。

　次は以下のコードを見てみます。
```
    context = {'object': object}
    return render(request, 'search_word/suggest_result.html', context)
```
　この二行で何をしているのか端的に説明すると<b>templateに渡す情報を定義しそれをrenderで返しています。</b>変数"context"では、templateに渡したいオブジェクトや変数を辞書型配列に変換し渡せるようにしています。辞書型であるため、渡したい変数が増えたとしてもその分keyとvalueを追加するだけで渡す変数を増やすことができます。
　renderの部分では、左から<b>リクエスト, 表示するhtmlファイル, 渡すオブジェクト等の情報</b>の順で記載しています。この関数実行後はrenderの中に書かれた記述を基にtemplateが返され表示されます。

## templateを編集
```
{% extends 'base.html' %}
{%block title%}実行結果 {%endblock%}
{% block content %}
<div class="container">
    <div class="row">
        <div class="col-lg-8">
            <h2>実行結果</h2>
            <table>
                <tbody>
                    <tr>
                        <td>{{object.hoge}}</td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>
{% endblock content %}
```
　テンプレートでは、渡したobjectを{{object.hoge}}とすることで出力しています。

## さいごに
　以上がfunction-based viewの詳細ページの実装方法になります。元々Railsを触っていた身からすると少し毛色が違い戸惑う箇所もありましたが、慣れてきたら以外に単純な構造であることが分かりました！
STM32L010とMCP9701で温度をシリアルに出力 (RawSerial)(テーブル方式)


x MCP9701-E/TO 販売コード 103199

x Mbed2のリビジョンは、125
x あまり正確では、ない

目的
秋月で売っている安価なMCP9701(約25円)を使って温度を出力する。

A0は、PA_0の事



![o_con565.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/840352/1b3231f0-3144-1d3d-ff19-fe8507a4cdb9.jpeg)




```c++

//SER_MCP9701_table_010_1

//温度

static const char tmp_t[]=
{
0*2+0,0*2+1,0*2+1,
1*2+0,1*2+1,1*2+1,
2*2+0,2*2+1,2*2+1,
3*2+0,3*2+1,3*2+1,
4*2+0,4*2+1,4*2+1,
5*2+0,5*2+1,5*2+1,
6*2+0,6*2+1,6*2+1,
7*2+0,7*2+1,7*2+1,
8*2+0,8*2+1,8*2+1,
9*2+0,9*2+1,9*2+1,
10*2+0,10*2+1,10*2+1,
11*2+0,11*2+1,11*2+1,
12*2+0,12*2+1,12*2+1,
13*2+0,13*2+1,13*2+1,
14*2+0,14*2+1,14*2+1,
15*2+0,15*2+1,15*2+1,
16*2+0,16*2+1,16*2+1,
17*2+0,17*2+0,17*2+1,
18*2+0,18*2+0,18*2+1,
19*2+0,19*2+0,19*2+1,
20*2+0,20*2+0,20*2+1,
21*2+0,21*2+0,21*2+1,
22*2+0,22*2+0,22*2+1,
23*2+0,23*2+0,23*2+1,
24*2+0,24*2+0,24*2+1,
25*2+0,25*2+0,25*2+1,
26*2+0,26*2+0,26*2+1,
27*2+0,27*2+0,27*2+1,
28*2+0,28*2+0,28*2+1,
29*2+0,29*2+0,29*2+1,
30*2+0,30*2+0,30*2+1,
31*2+0,31*2+0,31*2+1,
32*2+0,32*2+0,32*2+1,
33*2+0,33*2+0,33*2+1,
34*2+0,34*2+0,34*2+1,
35*2+0,35*2+0,35*2+1,
36*2+0,36*2+0,36*2+1,36*2+1,
37*2+0,37*2+1,37*2+1,
38*2+0,38*2+1,38*2+1,
39*2+0,39*2+1,39*2+1
};


static const char data[][5]={
"00.0","00.5","01.0","01.5","02.0","02.5","03.0","03.5","04.0","04.5","05.0","05.5","06.0","06.5","07.0","07.5","08.0","08.5","09.0","09.5",
"10.0","10.5","11.0","11.5","12.0","12.5","13.0","13.5","14.0","14.5","15.0","15.5","16.0","16.5","17.0","17.5","18.0","18.5","19.0","19.5",
"20.0","20.5","21.0","21.5","22.0","22.5","23.0","23.5","24.0","24.5","25.0","25.5","26.0","26.5","27.0","27.5","28.0","28.5","29.0","29.5",
"30.0","30.5","31.0","31.5","32.0","32.5","33.0","33.5","34.0","34.5","35.0","35.5","36.0","66.5","37.0","37.5","38.0","38.5","39.0","39.5"
};


#include "mbed.h"


//アナログ入力の設定
AnalogIn adc_vbat(A0);

RawSerial pc(PA_2, PA_3); //010

//メイン関数
int main() {

    int       s;        //ADCの値


    //無限ループ
    while(1) {

        //ADCの読み込み 0から4096
        s = (adc_vbat.read_u16()>>4);
       
        //温度の表示
        s = (s >> 3);
        if(s >= 184) {
            pc.puts("40.0");
        } else if(s <= 62) {
            pc.puts("-0.0");
        } else {
            pc.puts(data[tmp_t[s-63]]);
        }
        pc.puts("\r\n");

        //1秒の待ち
        wait_ms(1000);

    } //while

} //main

//容量削減
void error(const char* format, ...){}



```
完全無料ホスティングでDiscordBotを作った話。

# :stuck_out_tongue: 概要

`on_voice_state_update`を利用してDiscordの通話を記録するBOTを作成する。
無料のホスティングサービスを使う。

# :stuck_out_tongue: 環境

まずホスティングは「replit」を使用する。

https://replit.com/

# :stuck_out_tongue: 実装

BOTを早速実装していきます。

## コード作成

:::note info
**コードを利用する場合に際して**
`<サーバーID>`と`<テキストID>`は適宜、置き換えてください。
:::

```python:main.py
# 必須ライブラリをインポート
from os import sync
import discord
from datetime import datetime, timedelta


# tokenファイルを読みこみ、内容を返す
# 第一引数にトークンのファイルパスを取る
def getToken(filePath):
	f = open(filePath, 'r', encoding="UTF-8")
	data = f.read()
	f.close()
	return data


# トークンと環境変数等を取得する
TOKEN = getToken("token")
SERVER_ID = <サーバーID>
TXT_ID = <テキストID>
print("Success > Got token and SERVER and TEXT ID.")

client = discord.Client()

# クライアントクラスを作成する
@client.event
async def on_ready():
	print("Success > Login.")

# ボイスチャットに変化があった際のイベント
@client.event
async def on_voice_state_update(member, before, after):
	print("Log > Event was called.")
	if member.guild.id == SERVER_ID:
		if before.channel != after.channel:
			now = datetime.utcnow() + timedelta(hours=9)
			alert_channel = client.get_channel(TXT_ID)
			if before.channel is None:
				msg = f"== {now:%m/%d %H:%M} ==\n{member.name} さん <#{after.channel.id}> へようこそ！"
				print(msg)
				await alert_channel.send(msg)
			elif after.channel is None:
				msg = f"== {now:%m/%d %H:%M} ==\n{member.name} さん <#{before.channel.id}> へまた来てね！"
				print(msg)
				await alert_channel.send(msg)

# クライアントクラスを実行する。
client.run(TOKEN)
```

## コード中の必須情報

Discordの開発者モードをオンにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/95cdf1c8-336a-b444-3f74-8f658a11c7e8.png)

`<サーバーID>`は記録するサーバーのIDです。
記録したいサーバーのアイコンを右クリックして「IDをコピー」から取得してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/00d0ab13-b28d-6e9e-b4cc-e6672ebf4017.png)

`<テキストID>`はログを吐き出すテキストチャンネルのIDです。
テキストチャンネル上で右クリックをして「IDをコピー」から取得してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/5554bd6f-0c9c-b8a7-fb97-870162dab8fb.png)

次にBOTのトークンを入れるファイル（`token`）を作ります。
```:token
トークンをここに書き込む
```

ここまでのコードをGitHubに置いておきました。

https://github.com/ayato-shitomi/discord_vc_logger

## 実行
VCに入退出した時にメッセージが送信されて、標準出力に書き出されていればOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1523062/3b977313-aa3e-325a-3b34-330fd41e6fcc.png)

# :stuck_out_tongue: ホスティングサービスに乗っける

## shellから`discord.py`の導入

以下コマンドで導入する。

```bash
> pip3 install -U discord.py[voice]
```
導入できたことを確認するには`Console`にて以下コマンド。

```bash
>>> import discord
```
こんな感じでエラーが出なければ、良きです。

## Gitからクローンする

```bash
> git clone https://github.com/ayato-shitomi/discord_vc_logger.git
```

あとはReplitで実行すればOK！

## 常時動かす

常時起動したい！って方はこちらを参考にしてみるといいかもです！

https://qiita.com/eureyuri/items/c5f041773c93a54b9f92


# :stuck_out_tongue: 参考リンク

https://ikayome.hateblo.jp/entry/2018/11/12/121451

https://qiita.com/1ntegrale9/items/9d570ef8175cf178468f

https://qiita.com/aiotter/items/69f8d5a4c5a75313e77a
「愛知県民」なので自動運転に使用されるAI技術についてまとめてみた　②2022/7/7時点の自動運転車・AI技術

# 1.はじめに
どうも、ARIの名古屋支社に勤務している愛知県民です♪
(/・ω・)/

**愛知県といえばトヨタ、トヨタといえば車、車といえば自動運転**ということで、
ふと自動運転ではどのような技術が使われているのかが気になり、
前回は自動運転に使用されるAI技術の概要をまとめてみました。

https://qiita.com/Aichi_Lover/items/07f193ceaa698bb7fc85

そこで今回は**現時点で使用された実績のある自動運転車・AI技術についてまとめてみたいと思います♪**
車のIT技術について勉強中の方の参考になれば幸いです。
(*^^)v

:::note info
※現時点 = 2022/7/7時点　です。
:::

# 2.現時点の自動運転車
## 2.1.レジェンド
前回の記事でも紹介したホンダのレジェンドは、
**2021年3月に世界初の高速道路における完全自動運転を実現した車**です。

高額なLiDAR（図中の緑丸、ライダーセンサ）を5つ使用し、
**値段は1100万円**と高額ですが、コストよりも信頼性を優先する形で販売されました。
現在はリースのみ100台限定とのことです。

|![1609761.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/fb28378e-4024-ab44-6193-83055fdade65.jpeg)|
|:--|
図：ホンダ レジェンドのセンサー配置　出典：Automotive media Response   https://response.jp/article/2021/03/04/343661.html

## 2.2.e-Palette(イーパレット)

自動運転車の例としてトヨタのe-Paletteもあります。
こちらはニュースで見た人もいると思いますが、**東京オリンピックの選手村にて、選手用の巡回バスとして使用されました。**
（一般の人への販売はしていません。）

|![001.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/89cda0c8-485b-b9d0-2e64-c6f5b1daaf7a.jpeg)|
|:--|
図：e-Paletteの外見　出典：トヨタHP　https://global.toyota/jp/newsroom/corporate/29933339.html

カメラやLiDARなどのセンサーを用いて周囲360°を常に監視し、
高精度3Dマップ情報を用いて低速自動運転を実現しています。

形状は前後対称の箱形をしており、内部はフラットな広い空間になっています。
これは**車椅子の乗降に考慮したバリアフリー構造であるだけでなく、
移動式の宅配ロッカーやアパレルショップ等のサービスとして活用することが考えられています。**

|![insidetoyota_115_11.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/53a2f342-aeef-966e-10c0-6898b827fe57.jpeg)|
|:--|
図：アパレルショップ仕様のe-Palette　出典：トヨタイムズHP https://toyotatimes.jp/toyota_news/115.html

# 3.現時点でのAI技術
## 3.1.ライトの自動調光
運転だけでなく、ライトの調光も自動化が進んでいます。
ホンダでは、夜間走行時に状況に応じて照射範囲を自動で切り替える、
アダプティブドライビングビームが使われています。

|![outline.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/d75abe13-0b3a-f9a5-c6f4-d81394f0c563.png)|
|:--|
図：夜間のアクティブドライビングビーム使用例　出典：ホンダHP https://www.honda.co.jp/tech/auto/safety/adb.html

先行車や対向車がいない場合は、ハイビームを使用し、歩行者の早期発見をしたり道路形状を見やすくしたりしています。
カメラで先行車や対向車を検知した場合は、眩惑を軽減するためロービームに自動で調整されます。

**夜間歩行者の交通死亡事故の9割はロービームのみ点灯中に発生しているため、
視認性向上により事故低減効果が期待されています。**

## 3.2.車内システムの自動化
自動化は車内システムにも採用されています。
マツダは、2022年3月にドライバ・パーソナライズ・システムを搭載する新型SUVを発表しました。
これは、**ドライバの目の位置を検知した上で体格を推定し、自動で最適なシートポジションに調整してくれます。**
その他にハンドルやミラー、ディスプレイの位置も自動で変更されます。

|![drivingposition_3step_img02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372071/b12dba17-b827-401c-4689-feea3c9d3aa0.jpeg)|
|:--|
図：ドライバ・パーソナライズ・システムのイメージ図　出典：マツダHP https://www.mazda.co.jp/beadriver/cockpit/drivingposition/01/

また、顔認証機能を用いて、ドライバの好みのシート位置、システムの音量、エアコン、周囲照明など
**個人が設定した100以上の項目を自動で調整することが可能**です。

ドライバにとって理想のドライビングポジションや運転環境を実現することで、
疲れにくく安全に運転を楽しむことができます。

# 4.おわりに
ここまで読んで下さり、ありがとうございます！！！
(^^)

今回も色々調べてみて、知らないことをたくさん知れたので非常に楽しかったです！
数十年後には自動運転も当たり前になっていると思うので、
その時までなんとか生きていこうと思いました。

次回は・・・未来の車とAI技術についてまとめてみたいと思います♪
(:3_ヽ)_
Visual Studio Codeでビルド環境を整える

# やりたいこと
C言語開発をする上で、ビルドできる環境を整えたい。

# 環境
CPU：Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz   1.80 GHz
実装RAM：8.00 GB
システムの種類：64 ビット オペレーティング システム、x64 ベース プロセッサ

# 手順
以下の記事を参考。
https://qiita.com/N_Matsukiyo/items/464594d1fd3e6ef576a4
丁寧にまとめられており、これで十分(@N_Matsukiyo さんに感謝)。
Atcoder 解いてみた AGC 011 A - Airport Bus　

# AGC 011 A - Airport Bus 解いてみた
問題は[こちら](https://atcoder.jp/contests/abc072/tasks/arc082_a)

## 私の回答
問題を見て、素直にコード化した。
しかし、結果は時間オーバー、、、
```C++
#include <iostream>
#include <algorithm>

using namespace std;

int n, c, k;
int T[100005];


int main() {
	cin >> n >> c >> k;
	for (int i = 0; i < n; i++) {
		cin >> T[i];
	}

	std::sort(T, T+n);

	int num_bus = 0;

	int first_passenger = 0;
	int passenger_num = 0;
	int first_pass_index = 0;

	int first_passenger_limit=0;

	bool is_finish = false;

	while (true) {
		first_passenger_limit = T[first_pass_index] + k;
		passenger_num = 0;

		for (int i = first_pass_index; i < n; i++) {
			
			// passenger_numカウント
			if (T[i] <= first_passenger_limit) passenger_num++;

			//途中で、バスカウントされたら、break
			//定員or客が待てなかったら、バスカウント
			if (passenger_num == c) {
				num_bus++;
				first_pass_index = i+1;
				break;
			}
			if(T[i] > first_passenger_limit){
				num_bus++;
				first_pass_index = i;
				break;

			}

			// 探索が最後まで行ったら終了
			if (i == n - 1) {
				num_bus++;

				is_finish = true;
				break;
			}
			
		}

		if (is_finish == true) break;
	}
	cout << num_bus << endl;
}

```

## 模範回答

```C++
#include <iostream>
#include <algorithm>

using namespace std;

int n, c, k;
int a[100005];


int main() {
	cin >> n >> c >> k;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + 1 + n);
	int first_passenger = a[1];
	int cnt = 0;
	int bus = 1;
	for (int i = 1; i <= n; i++) {
		if (first_passenger + k >= a[i] && cnt < c) {
			cnt++;
		}
		else {
			bus++;
			first_passenger = a[i];
			cnt = 1;
		}
	}
	cout << bus << '\n';
}
```

## 振り返り
常にループを減らせないか考えてみる
A問題なのに、全然20分で終わらなかった、、、
デバックしてたらすぐ時間が過ぎる
速く実装するコツがありましたら、コメントいただけると幸いです。