OmniAICreator/Qiita-1.07M huggingface dataset:
ブロックチェーン開発の基礎知識 ユースケース、仕組み、注意点

1. ブロックチェーン開発とは？
ブロックチェーンとは、デジタル資産のデータの暗号化されたブロックが保管されている、連鎖したりされるデジタル台帳またはデータベースで、データの時系列的な信頼できる唯一の情報源を形成します。

ブロックチェーン開発とは、ネットワーク内で取引を安全に記録し、資産を追跡する、共有され、変更できない分散型台帳技術（distributed ledger technology、略称：DLT）を作成するプロセスです。

ブロックチェーン技術の仕組みは、Googleドキュメントに例えると分かりやすいでしょう。 Googleドキュメントは、グループで共有されてもコピーや譲渡されることはなく、その代わりに単に分散されます。これにより、分散化された配布チェーンが構築され、誰もが同時にベースドキュメントにアクセスできるようになります。他の関係者からの変更を待ってロックアウトされることはありません。また、ドキュメントに対するすべての変更はリアルタイムで記録され、変更は完全に透明化されます。しかし、Googleドキュメントとは異なり、ブロックチェーン上のオリジナルのコンテンツやデータは、一度書き込まれると変更できないため、セキュリティレベルが高くなります。

もちろん、ブロックチェーンはGoogleドキュメントより複雑ですが、この例えはブロックチェーン技術の重要なアイデアを強調しているため、適切です。

ブロックチェーンの特徴をまとめると、以下のようになります。

デジタル資産はコピーや譲渡されるのではなく、単に分散されるのみ
デジタル資産は分散型であるため、複数の当事者がそれを管理し、リアルタイムでアクセスすることができる
ブロックチェーンの台帳は公開であり、すべての変更が記録されるため、完全性と信頼性が保たれる
ブロックチェーン技術は、その台帳が一般に公開され、固有のセキュリティ対策で構築されているため、ほとんどすべての業界で最有力候補となっている
2. ブロックチェーン技術の応用とユースケース
ブロックチェーン技術は現在、ゲームの革新、医療データの保護、食品サプライチェーンの透明性の提供、そしてデータや所有権の管理方法の全体的な変更するために利用されています。ここでは、ブロックチェーンのユースケースと応用の例を紹介します。

2.1. 暗号通貨におけるブロックチェーン開発
ブロックチェーンは、ビットコインのような暗号通貨の基盤を形成しています。米ドルは連邦準備理事会によって管理されています。ユーザーのデータや通貨は、この中央集権システムのもとでは、技術的に銀行や政府振り回されます。もし銀行がハッキングされれば、顧客の個人情報は危険にさらされます。銀行が破綻したり、政府が不安定な国に住んでいたりすると、通貨の価値も危うくなる可能性があります。2008年には、いくつかの破綻した銀行が、部分的に税金を使って救済されました。このような懸念から、ビットコインは最初に構想され、開発されました。

ブロックチェーン開発者
ビットコインは、ブロックチェーン技術を利用して作成、分散、取引、保管される世界で最も人気のある暗号通貨です
ブロックチェーンは、ビットコインやその他の暗号通貨を、コンピュータのネットワークに活動を広げることで、分散的に活躍させます。これにより、リスクが下がるのみならず、多くの処理手数料や取引手数料の削減につながります。

2.2. NFTゲームにおけるブロックチェーン開発
現在、中央集権モデルが大部分のオンラインゲームで採用されています。これは、すべての関連データが、ゲームの管理者が完全な権限を持つサーバーに保管されていることを示します。データベースは一事業者が所有しているため、プレイヤーは自分のアカウントや物を実際に所有していません。さらに、集中管理型サーバーには、次のような欠点があります。アカウントの不当な禁止や、開発者や管理者によるゲーム経済におけるごまかしなどです。

ブロックチェーンを利用したシステムは、分散型データベースとして機能するため、ゲーム内の履歴、デジタルオブジェクト、トークン化された資産など、様々な種類のデジタルデータの認証と保護に利用できます。それぞれのアセットは、独自の代替不可能なトークン（NFT）で表されます。アセットには、キャラクター、ゲーム内カード、スキン、装備品等が含まれます。しかし、アセットの種類にかかわらず、それらはすべて分散型ネットワークによって管理されるブロックチェーントークンにリンクされることができます。このように、各プレイヤーは自分のアカウントとデジタルアセットを完全に管理することができ、これらのアセットを常に自由に取引することができます。
Read More: https://bit.ly/3CybaFk
新卒SE選択ソート書いてみた

基本情報技術者の擬似言語の学習のため実際にプログラム化してみました。
基本情報の問題集をもとにフローチャートを作成し、コーディングをおこなっております。

```java:Qiita.java
import java.util.*;

public class SelectionSort {

  public static void main(String[] args){

    try {
      Scanner sc = new Scanner(System.in);
      System.out.println("作りたい配列の要素数を入力してください。降順に並べます。");
      int size = Integer.parseInt(sc.next()); 
      int[] data_array = new int[size]; 


      /*
       * テストデータ
       * 要素数 8
       * 47,33,68,55,74,89,25,10
       * 3,5,8,4,0,6,9,1
       * 7,7,7,7,7,6,9,1
       * 0,0,0,0,0,0,0,0
       * 80,70,60,50,40,30,20,10
       * 70,60,40,70,30,70,50,70
       * 80,60,40,70,30,10,50,20
       * 80,60,40,70,30,10,50,20
       * 80,60,40,70,30,10,50,70
       * 
       *
       */


      System.out.println("配列要素数が" + size + "個になるよう各要素に格納する値を入力してください");
      for (int i = 0; i < size; i++) {
        data_array[i] = Integer.parseInt(sc.next());
      }

      System.out.println("配列入力結果→" + Arrays.toString(data_array));

      int return_swap_count = selectionSort(data_array); //選択ソート
      printResult(data_array, return_swap_count); //結果出力


    } catch (Exception e) {
      System.out.println("エラー;" + e.getMessage());// エラーメッセージ表示
      e.printStackTrace(); // スタックトレース

    }
  }

  public static int selectionSort(int[] data_array){
    int range_max = 0;
    int range_max_index = 0;
    boolean flag = false;
    int tmp = 0;
    int swap_count = 0;

    //選択ソート
    for(int i = 0; i < data_array.length - 1; i++){
      range_max = data_array[i];
      range_max_index = i;
      for(int j = i + 1; j < data_array.length; j++){
        if(range_max < data_array[j]){
          range_max = data_array[j];
          range_max_index = j;
          flag = true;
        }
        
      }

      if(flag){
        tmp = data_array[i];
        data_array[i] = data_array[range_max_index];
        data_array[range_max_index] = tmp;

        swap_count++;
        flag = false;
      }
    }
    
    return swap_count;
  }


  public static void printResult(int[] data_array, int swap_count){
    System.out.println("選択ソート結果");
    System.out.println(Arrays.toString(data_array));

    System.out.println("交換回数は"+ swap_count + "回です。");
  }
  
}
SUM(CASE WHEN)を使った条件付き集計~






dokoSQLを使用し、SUM関数で、sum関数の列以外の列を一緒に集計結果を取得できることがわかった。
当たり前っちゃ当たり前ですが、私にとっては新たな発見でしたので、メモ。



場面、
テーブルの表をそのまま取得してきたいけど、ある条件を満たしているレコードの件数を同じsqlで取得してきたい。
新人研修で同期がやっていてどうやってやるのか気になっていた。


```sql:insert.sql
insert into 家計簿アーカイブ(費目,メモ,入金額,出金額)values('給料','2月','10000','10000');
insert into 家計簿アーカイブ (費目,メモ,入金額,出金額)values('給料','3月','10000','10000');
insert into 家計簿アーカイブ (費目,メモ,入金額,出金額)values('給料','4月','10000','10000');
```


テーブルの中身
![FireShot Capture 121 - dokoQL - v3.dokoql.jp.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414082/6b49ac8b-5038-a6d5-8893-7c4514689d5f.png)




```sql: select.sql

select 日付,メモ,入金額,出金額,費目,(select sum(case when 費目 = '給料' then 1 else 0 end) from 家計簿アーカイブ) from 家計簿アーカイブ;

```

取得結果
![スクリーンショット 2022-12-31 17.57.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/414082/762e03d4-f005-abec-7e9c-51c35891d593.png)



副問合せの列だけ表に肉づけしている感じでしょうか。
デフォルトで入っているテーブルを操作しているので、よかったらご自身でやってみてください。




参考
https://dokoql.jp/workspace
https://sukkiri.jp/books/sukkiri_sql
ウェブサイトの最適化：ウェブサイトに関する9つのよくある間違い


はじめに
今日のeコマースでは、顧客が購入前にブランドのウェブサイトを訪問したり、オンラインで購入したりすることが多いため、良いウェブサイトを持つことは重要です。人々がウェブサイトでしばしば犯してしまう、SEOランキングや顧客体験を損なういくつかの間違いがあります。この記事では、それらの間違いを詳しく取り上げ、デジタルプレゼンスを高めるため、どのようにそれらを避けるかを解説します。

ウェブサイトの読み込みに時間がかかりすぎる
速く進める時代で、ユーザーの忍耐力も弱くなり、ウェブサイトが数秒で読み込まれることを期待し、読み込みに時間がかかるウェブサイトから離れるはずです。これは、もし低速のウェブサイトを持っているならば、知らないうちに大量の顧客を失う可能性があります。Googleは読み込みに3秒以上かかるサイトを好まないため、高速なウェブサイトは顧客体験に優れているだけでなく、Google検索エンジンで上位に表示されます。 

では、Webサイトの読み込みが遅くなる原因は何でしょうか？もし、ウェブサイトが3秒で完全にロードされない場合は、開発チームまたは第三者に問題を診断してもらい、ウェブサイトの最適化を改善するため、問題を解決してもらいましょう。

ポップアップが多い
訪問者のリードを獲得するために、人々はサイトでポップアップを使おうとしますが、この慣習はウェブブラウザにとって迷惑なものになります。自分の体験でも、ポップアップが表示された時、まず最初に、閉じるボタンを探すと思います。その上、ポップアップはウェブサイトの読み込み速度を遅くし、検索エンジンでのランクを下げる可能性があるので、ポップアップを使えば使うほどウェブサイトのランクが下がります。 

ポップアップがすべて無駄だと言っているわけではありませんが、オンラインでの買い物の過程において、顧客にとって関連性があり、価値のあるものであれば、合理的に使用すべきです。訪問者にお役立ち資料請求を表示することは、ポップアップの使い方として有効ではないと思えますが、チェックアウトページでの割引ポップアップは非常に効果的です。

明確なCTA（コール・トゥ・アクション）がない
CTA（Call to Action）とは、マーケティング用語で、マーケティング担当者がユーザーや訪問者に取って欲しい次のステップを意味します。CTAは、販売に直接つながることもあります。例えば、購入ボタンをクリックして販売を完了するよう読者に指示することもできます。単にその企業の消費者になるように、読者をさらに動かします。

陥りがちなのが、サイトに明確なCTAを設けていないことです。CTAとは、「メッセージはこちら」「お見積もりはこちら」「製品ページはこちら」など、ウェブサイトを閲覧する際に、訪問者が必要なものを見つけるため、何をすべきかを知るようなものです。せっかく製品に興味を持ってくれたのに、問い合わせができずに離脱してしまうことは、最も避けたいことです。

デザイン規範に反している
訪問者がウェブサイトにたどり着いた時、印象づけるのは最初の数秒だけです。デザイン性の高いウェブサイトは、訪問者との信頼関係を素早く構築し、閲覧を続ける動機付けとなるため、顧客の興味を引くために、できる限り魅力的なウェブサイト作りに努力を費やすようにしましょう。 

ここでは、Webデザインに取り組む際のヒントとは：

どのページも、内容が明確でわかりやすいものにする
訪問者が直感的に製品を操作できるような導線をサイト全体に構築する
標準的でないリンクカラーの使用を避ける 
製品を紹介するために、質の高い写真を撮る
ブランドの美意識を表す適切な色を使用する
Read More: https://bit.ly/3vMfJZ1
Googleプロジェクト管理：チェンジマネジメント

# はじめに

わたしが [Google プロジェクト管理:プロフェッショナル認定証で得られた素晴らしい体験][google]を、要点をまとめ小さく分割して、わかりやすく簡潔に紹介していきます。

興味があれば、ぜひ ***"Google プロジェクト管理:プロフェッショナル認定証"*** を受講してみてください。

[google]: https://qiita.com/mapami/items/317ae776a2268fd54c8f

https://jp.coursera.org/professional-certificates/google-project-management

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2358573/579e805c-6045-9c1c-543d-f9519b57d50c.png" width="800">

# チェンジマネジメント（変更管理）とは

プロジェクトマネジメントでは、完成したプロジェクトを提供し、それを人々に採用してもらうプロセスをチェンジマネジメントと呼びます。

　***<font color="MediumVioletRed">『チェンジマネジメントとは、完成したプロジェクトを納品し、組織内の他の人たちに採用してもらうためのプロセス』</font>***

たとえば、従業員向けに新しいタイムトラッキングシステムを立ち上げる場合、従業員が新しいシステムを採用しなければ、プロジェクトは成功とは言えません。

プロジェクトマネージャーとして、あなたはプロジェクトに必要なチェンジマネジメントのすべてを計画する責任を負っていないかもしれません。しかし、それとは関係なく、プロセスにおける自分の役割と、その変化に対する組織の反応を理解することで、プロジェクトの成功に貢献することができます。

新しいロゴに変更するという単純なことでも、社員にとっては大きな頭痛の種になります。古い文房具をすべて交換し、オフィスの全員が新しいロゴを正しく使っているかどうかを確認しなければならないのです。

プロジェクトの成功を考えるとき、

　***<font color="MediumVioletRed">『その結果、人々が実行しなければならない変化を心に留めておく』</font>***

ことが重要です。

# プロジェクトマネジメントとチェンジ・マネジメントの統合

　***<font color="MediumVioletRed">『チェンジマネジメントは、それ自体が一大事業であり、プロジェクトと言えます。』</font>***

プロジェクトマネージャーであるあなたは、チェンジマネジメントをプロジェクトの成功に必要なものと考えることができます。チェンジマネジメントとプロジェクトマネジメントは、どちらもプロジェクトの成功の可能性を高めることを目的としています。

プロジェクトの目標を達成する最も効果的な方法は、プロジェクトマネジメントとチェンジマネジメントを統合することであり、その責任はプロジェクトマネージャーであるあなたにあります。

プロジェクトに関連する変更管理について考えるとき、次のような質問を自分に投げかけることから始めてください。

- ***<font color="MediumBlue">組織は変化にどのように対応するのだろうか？</font>***
- ***<font color="MediumBlue">どのようなインフルエンサーが変化に影響を与えることができるのか？</font>***
- ***<font color="MediumBlue">最適なコミュニケーション手段は何か？</font>***
- ***<font color="MediumBlue">私のプロジェクトを成功に導くチェンジマネジメントのやり方は何か？</font>***

これらの質問に答えることで、さまざまな可能性のあるシナリオに備えることができ、プロジェクトの採用を効果的にサポートするためのソリューションを作り上げることができます。

# チェンジマネジメントに取り組むためのベストプラクティス

### 積極的に行動する

積極的かつ包括的なチェンジマネジメント計画を立てることで、影響を受ける可能性のあるステークホルダーに、今後の変更について常に注意を払うことができます。

- プロジェクト管理のステップにチェンジマネジメントを組み入れる。
    - 例えば、チームミーティングに時間を割いたり、フィードバック文書を作成したりして、チームメンバーが提案や懸念を表明する場を確保します。
- プロジェクトの終盤に、デモンストレーション、質疑応答フォーラム、マーケティングビデオなどの形で、ステークホルダーに成果物を紹介するステップを計画することもできます。

これらの決定をすべて計画に盛り込むことで、潜在的な変更がタイムラインに影響を与える可能性を低くすることができます。もし、これらのステップが計画に組み込まれていない場合は、ステークホルダーにチェンジマネジメント計画の重要性を強調し、エスカレーションすることができます。

### 今後の変化について伝える

影響を受けるステークホルダー、チェンジマネジメントチーム、プロジェクトチームの間で定期的にコミュニケーションを行う。

プロジェクトの成果物を利用するエンドユーザーにとって、変更がどのように良いエクスペリエンスになるかについて、プロジェクト全体を通して確認し、コミュニケーションをとるのです。こうすることで、プロジェクトが始動したときに、変更に対応するために必要な情報を全員に提供し、プロセスをサポートすることができます。

### 一貫したプロセスに従う

明確なチェンジマネジメントプロセスに従うことで、変更があるたびに一貫性を保つことができます。

チェンジマネジメントプロセスは、プロジェクトの早い段階で確立し、文書化して、プロジェクトがどのように変更を処理するかを導く必要があります。

また、あなたの組織には、プロジェクトに採用できる包括的なチェンジマネジメント計画があるかもしれません。この計画には、

- 変更の推進時期
- トレーニングの実施時期
- 立ち上げやリリースの時期
- プロセスの各段階に対応する手順

などが含まれる場合があります。

### 共感の練習をする
変化は避けられないものですが、私たちはしばしば変化に対して抵抗感を抱きます。変化がもたらす課題や不安に対して共感することで、そのプロセスをさりげなくサポートすることができます。


### ツールを使う

変更の採用を支援するツールを取り入れると、非常に便利です。ここでは、次のプロジェクトで使用できるいくつかの例を紹介します。

- アンケート調査などのフィードバックにより、ステークホルダーの意見を取り入れることができる。
- フローチャートは、プロジェクトの開発プロセスを視覚化することができます。
Tauri導入(Windows11環境)

# Tauri導入(Windows11環境)

RustのデスクトップアプリケーションフレームワークTauriの導入の個人的なメモ。
※この記事ではパッケージ管理ツールとしてcargoを使い雛形を動かすところまでの手順を書いています。

## 環境

- Windows11
- Rust導入済み

## 手順

### 準備

パッケージ管理ツールとして`cargo`を使う。
まずはツールチェインを最新版にしておく。

```powershell
rustup update
```

`create-tauri-app`をインストール。

```powershell
cargo install create-tauri-app
```

`tauri-cli`も必要になるのでインストール。

```powershell
cargo install tauri-cli
```

他にもプロジェクト作成時にWindowsでは`C++ビルドツール`と`WebView2`が要るよとリンクを教えてくれる。
(このリンクを表示してくれる:[https://tauri.app/v1/guides/getting-started/prerequisites/](https://tauri.app/v1/guides/getting-started/prerequisites/))

- C++ビルドツールはWindowsでRustをビルドできる環境が整っていれば既にインストール済み
- WebView2はWindows11であればデフォルトで入っているので特に用意する必要はない

### 雛形を動かしてみる

実際にTauriのプロジェクトを作って雛形を動かしてみる。
プロジェクトを作成したいディレクトリに移動して下記を実行。

```powershell
cargo create-tauri-app
```

すると、2023/01/09現在ではプロジェクト名、パッケージマネージャ、UIテンプレートを選択するように促される。
雛形を動かすだけなら例えばこんな感じでOK。

```Powershell
✔ Project name · test
✔ Choose your package manager · cargo
✔ Choose your UI template · vanilla
```

プロジェクトのディレクトリが作成されるのでその中に移動して雛形を動かしてみる。

```powershell
cargo tauri dev
```

下記のようなウィンドウが立ち上がれば成功。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/569165/6ec08516-81f2-5058-05a0-f8881fb95b0d.png)
エラトステネスのふるいによる素数生成 Python3


エラトステネスの篩による素数生成をします。
ファイルに、`chmod +x prime5.py`として実行権を付けて動かして下さい。
`$ prime5.py <n>`で、ｎまでの素数を生成します

```prime5.py
#!/usr/bin/python3
import sys

def primes(n):
  p = [i for i in range(n + 1)] # 0からｎまでの数のうち、
  for i in range(2, int(n**0.5)+1): # 2 から√ｎまでのうち、
   if p[i] != 0: # 最初の数が見つかったら
      for j in range(2, int(n/i)+1): # 倍数を次々と消してゆく
           p[i*j]=0
  return( [_ for _ in p if _ != 0][1:] ) # リストを整形する

argvs=sys.argv
n =int(argvs[1])
pl=primes(n)
print(pl)
print(len(pl))

```
CSV形式の行列を読み込むプログラム(C++)

# プログラムについて
https://qiita.com/persim/items/87f4812fe8bf0ab90d00
上の記事で作成したCSV形式の行列をC++で読み込む必要があったため，読み込むためのプログラムを作成しました．

# 環境
- MacBook Air(M1, 2020)
- Docker(Ubuntu 20.04.5 LTS)
- g++ (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0

# プログラム


```c++:readMatrix.cpp
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>

int main(int argc, char* argv[])
{
    const std::string inputFile = argv[1];
    std::ifstream ifs(inputFile, std::ios::in);

    std::string buf;
// ファイルの各行から文字列を取得する
    getline(ifs, buf);  

// 1行目のコメントに関する処理
    std::istringstream sstream(buf);
    std::string s;
    int count = 0;

    int N, max_nonzero, nonzero;
// コメントから行列の大きさ，非零要素数の最大値，非零要素数の取得
    while (std::getline(sstream, s, ',')) {
        if (count == 0){
            N = std::stoi(s.substr(2));
            count++;
        } else if (count == 1){
            max_nonzero = std::stoi(s);
            count++;
        } else if (count == 2){
            nonzero = std::stoi(s);
        }
    }
    // std::cout << N << std::endl;
    // std::cout << max_nonzero << std::endl;
    // std::cout << nonzero << std::endl;
    
    double a[N][N];
// ファイルから行列データを取得する
    for(int i = 0; i < N; i++){
        getline(ifs, buf);
        std::istringstream sstream2(buf);
        std::string s2;
        for(int j = 0; j < N; j++){
            std::getline(sstream2, s2, ',');
            a[i][j] = std::stod(s2);
        }
    }
// 行列の各要素を1倍して計算している
    for(int i = 0; i < N; i++){
        for(int j = 0; j < N; j++){
            a[i][j] *= 1;
            std::cout << a[i][j] << std::endl;
        }
    }
}
```

# 実行方法
```
g++ readMatrix.cpp -o read
./read filename
```

# 実行結果
ターミナルに出力された値と，行列ファイルの値が一致しているので問題ないはず．

```
$ g++ readMatrix.cpp -o read
$ ./read 3_3matrix20230109141857.csv 
0.28367,0.750385,0
0.935173,0.379778,0.487891
0.368338,0.189218,0.754602

$ cat 3_3matrix20230109141857.csv 
# 3,3,1
2.836696849382646102e-01,7.503854470601402094e-01,0.000000000000000000e+00
9.351732236040680712e-01,3.797781741383208232e-01,4.878913783131487714e-01
3.683378046364506053e-01,1.892181686700632470e-01,7.546015295953415469e-01
```
Elixir(Livebook) で VRM のサムネイルを取得してみる

# はじめに
前回では Elixir で VRM をパースして画像一覧を取得しました。

https://qiita.com/nasshu2916/items/b64cef37d4e0557862df

今回 VRM の Meta 情報を読んでサムネイルを取得しようと思います。

# VRM の Meta 情報
VRM の `"images"` の中にはファイル名の情報がありますが、どれがサムネイル画像かの情報はありません。Vroid Studio で作成した VRM は自動的にサムネイルのファイル名が `thumbnail.png` になりますが、Vroid Studio 以外で作られたファイルに対応出来ません。そのため、VRM の Meta 情報を読む必要があります。
```elixir
alicia_data["images"]
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081963/c3a9d399-343d-e9fa-9349-14fb3b8267c4.png)

glb は "extensions" の下に拡張して定義している情報を置けるようになっています。VRM 0.x の場合、ここに `VRM` という形で拡張情報を保存しています。また、VRM 1.0 以降の場合、`VRM`ではなく`"VRMC_vrm"`という形で拡張情報を保存します。

それぞれ保存できる内容は Json Schema にて定義されています。

https://github.com/vrm-c/vrm-specification/tree/master/specification

メタ情報は VRM0.x と VRM1.0 で中身は異なるのですが、作者の情報やライセンスに加え、サムネイル画像に関する情報も保存してあります。この情報は `"images"` の中でサムネイル画像がどれなのかの index 番号になります。

Meta のサムネイルの index 番号に関する情報は VRM0.x の場合 `texture`、VRM1.0 の場合`thumbnailImage` に保存されています。
https://github.com/vrm-c/vrm-specification/blob/master/specification/0.0/README.md#thumbnail
https://github.com/vrm-c/vrm-specification/blob/master/specification/VRMC_vrm-1.0/meta.md

# サムネイル画像の取得
case を使って `images` の index を探します。
```elixir
thumbnail_index =
  case alicia_data do
    %{"extensions" => %{"VRM" => vrm}} ->
      get_in(vrm, ["meta", "texture"])

    %{"extensions" => %{"VRMC_vrm" => vrm}} ->
      get_in(vrm, ["meta", "thumbnailImage"])
  end
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081963/b8d86f90-1b71-2e20-b214-688048b1c4c6.png)

images の中からサムネイルの index 番号を使ってサムネイル画像を特定し表示してみます。

```elixir
%{"bufferView" => index, "mimeType" => mime_type, "name" => name} = Enum.at(images, thumbnail_index)
%{"byteOffset" => offset, "byteLength" => length} = Enum.at(buffer_views, index)

<<_::size(offset)-bytes, content::size(length)-bytes, _::bits>> = binary_chunk_data
%Kino.Image{content: content, mime_type: mime_type}
```
![image](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081963/500b4f5a-63f5-a745-ab5f-c792e14269e6.png)

Kino.Download.new/2 を使うことでサムネイル画像をダウンロードすることも可能です。

```elixir
Kino.Download.new(fn -> content end, filename: "#{name}.png")
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3081963/25761430-0fef-bd91-da47-2c9421971405.png)
レイストはウェブサイトの技術スタック、訪問統計、企業情報を分析するChrome拡張プログラムです。

自分のチームで作ったプログラムについてQiitaの皆さんの評価を聞いてみたいと思ったので紹介してみます。
レイストはウェブサイトの技術スタック、訪問統計、企業情報を分析するクロム拡張プログラムです。

https://ray.st/ja

*　一部日本語翻訳の誤字があるかもしれません、私達は韓国からのチームですが、できるだけの翻訳をしてみました！

機能

- ウェブサイトに接続したとき、画面右側の領域に小さなバッジ アイコンが浮かんでいます。
- バッジアイコンをクリックすると、現在のウェブサイトの企業情報、訪問者統計、技術スタックをフローティングパネルを通じて表示してくれます。
- バッジアイコンはxを押して非表示にしたり設定から非表示にすることができ、非表示にした後もショートカットキー(Shift + R)を通じてパネルを開閉することができます。
- 技術スタックの場合、キャッシングされたデータがなければ、要求時点で分析を実行し、最大10秒ほどかかります。
- 検出可能技術スタック

Wappalyzerに似ています。

- Javascript Framework
- マーケティング·ツール
- 一部バックエンドフレームワーク
- 分析ツール
- その他等々

訪問統計

- 情報が最初からウェブに公開された特定ウェブサイトの場合、データが正確です。
- 訪問統計が分からないウェブサイトの場合、予測された数値。 誤差が生じることがあります。

企業情報

- スタートアップなど投資と関連した英語ニュース記事が識別可能な企業情報はよく識別します。
- 日本や英語圏でない企業情報は、一部の誤った結果がある可能性があります。
リンクを指定するhrefプロパティとsrcプロパティの違い

## 勘違いしていたこと
これまでHTMLを書いてきて、リンクを指定したい時に

```HTML
 <a href=URL>
```
このようにaタグにhref属性を付けることが多いと感じていました。
なので画像を埋め込みたい時に
```HTML
<img href=URL>
```
このように書いてしまい、当然画像は表示されませんでした。
では、この二つの属性にはどのような違いがあるのでしょうか。

## href属性とsrc属性の違い
href(エイチレフ)とはhyper referenceの略でリンク指定の際に使われます。
それに対して
src(ソース)とはsourceの略で主に画像を埋め込む際に使われます。

この二つの属性の決定的な違いは、指定する情報の種類にあります。
hrefは<font color=blue>HTMLから他のHTML(外部リソース)へのハイパーリンク</font>であるのに対して
srcは<font color=blue>HTMLに埋め込むファイルのパス情報</font>を指定するものです。


<参考>
https://aqcg.jp/html-src-imi/#index_id1
WSLでVSCODEを使う際の注意点：Gitの差分がVSCODE上で確認できない

## 環境
- Windows11 
    - AMD Ryzen5000
- WSL2

## 背景
以下を参考にさせてもらってサクッとWSL2にGitをインストールしたときの話

https://learn.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-git

https://qiita.com/Michi1090/items/094a13cad3133e97d202

公式にある`git config`の設定も完了してssh接続もできて「gitが使える！」と思った矢先、VSCODE上で青色や緑色で表示される差分（※）が確認できなかった

※[Gutter indicators](https://code.visualstudio.com/docs/sourcecontrol/overview#_gutter-indicators)っていうらしい

ただ、`git push`とかのgitコマンドはすべて使えるしgitに問題があるわけではなさそうだった

## やったこと
VSCODEの拡張機能[Remote Development](https://marketplace.visualstudio.com/items?itemName=ms-vscode-remote.vscode-remote-extensionpack)をインストールするだけ。

これによってCLIで、`code`を打つだけでWSL上からファイルの本体（シンボリックリンクじゃない）をVSCODEで開くことができるのでVSCODE上のGitの機能をフルで使えるようになる。

```bash
$ code .
```

もちろん上述で問題になっていた[Gutter indicators](https://code.visualstudio.com/docs/sourcecontrol/overview#_gutter-indicators)も使えるようになった

## なんで拡張機能が必要なのか

浅い理解ですが以下の記事を見ていると拡張機能なしでVSCODEを起動するとシンボリック経由でファイルを開くためVSCODEが本来持つ機能をフルで使えないのだと思いました（※）

https://blog.mori-soft.com/entry/2021/05/06/145541

https://github.com/microsoft/vscode/issues/109865

https://stackoverflow.com/questions/53309911/visual-studio-code-git-decorations-disappear


※これは公式ドキュメントにある「オートコンプリート、デバッグ、リンティングなどのサポートが失われます。」と書かれている意味も含まれていると解釈。違っていたらごめんなさい。

https://learn.microsoft.com/ja-jp/windows/wsl/tutorials/wsl-vscode

## 補足

公式ドキュメントにはちゃんと拡張機能使ってね、という注意書きが書かれてました

> WSL 拡張機能なしで VS Code で WSL を使用することはお勧めしません。


--- 

備忘で書いたのですが、サーバー周りの理解が全く乏しいので拡張機能が必要な理由について「全然違う！」ってことであれば補足なり指摘なりもらえると嬉しいです
（理解は努めます）
Ktorでネストしたクラスのルーティング(resources)がうまくいかない

# はじめに

以下の書籍の10章でKtorのルーティングをしている際にかなり躓いたのでまとめます

https://www.amazon.co.jp/Kotlin-%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%82%B5%E3%82%A4%E3%83%89%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E5%AE%9F%E8%B7%B5%E9%96%8B%E7%99%BA-%E7%AB%B9%E7%AB%AF-%E5%B0%9A%E4%BA%BA/dp/4297118599/ref=sr_1_5?__mk_ja_JP=%E3%82%AB%E3%82%BF%E3%82%AB%E3%83%8A&crid=1BYA2OWTX6BT7&keywords=kotlin&qid=1673256586&sprefix=kotli%2Caps%2C192&sr=8-5

KtorのType-safe routingがうまく行かない方がいれば参考になればと思います

# 問題

書籍のP258パスの共通化をKtorの[Type-safe routing](https://ktor.io/docs/type-safe-routing.html#example_crud)で行いました

書籍では`Location`を使っていたため、`Resources`に書き換えて以下のコードにしました

```kotlin:Routing.kt
package com.example.plugins

import io.ktor.server.routing.*
import io.ktor.http.*
import io.ktor.resources.*
import kotlinx.serialization.Serializable
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.request.*
import io.ktor.server.resources.*
import io.ktor.server.resources.Resources

fun Application.configureRouting() {
    install(Resources)

    routing {
        get<User.New> { param ->
            val id = param.id
            call.respondText("$id")
        }
    }
}

@Serializable
@Resource("/user")
class User() {
    @Serializable
    @Resource("{id}")
    class New(val id: Long)
}
```

しかしアクセスすると以下のエラーが発生します

```
curl http://localhost:8080/user/1
```

```
  /{id}, segment:1 -> SUCCESS; Parameters [id=[user]] @ /{id}
    /{id}/(method:GET), segment:1 -> FAILURE "Not all segments matched" @ /{id}/(method:GET)
Matched routes:
  No results
Route resolve result:
  FAILURE "No matched subtrees found" @ /
```

ログを見る限り、`/{id}`というルーティングはありますが、`/user`はなさそうでした
どうすれば`/user/{id}`のルーティングを用意できるのでしょうか

# 解決方法

まずは最終的なコードを載せます

```kotlin:Routing.kt
package com.example.plugins

import io.ktor.server.routing.*
import io.ktor.http.*
import io.ktor.resources.*
import kotlinx.serialization.Serializable
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.request.*
import io.ktor.server.resources.*
import io.ktor.server.resources.Resources

fun Application.configureRouting() {
    install(Resources)

    routing {
        get<User.New> { param ->
            val id = param.id
            call.respondText("$id")
        }
    }
}

@Serializable
@Resource("/user")
class User() {
    @Serializable
    @Resource("{id}")
    class New(val parent: User = User(), val id: Long)
}
```

ポイントは

```
class New(val parent: User = User(), val id: Long)
```

の行になります。ここで`val parent: User = User()`をやっていますが、この箇所があることによって`/user`がパスの先頭(親)になるようでした

# おわりに

何度も公式のコードを見たり、調べたりしますがなかなか気づけなかったので多くの時間を使ってしまいました

# 参考

https://ktor.io/docs/type-safe-routing.html#example_crud
【時系列解析】ホワイトノイズ

時系列データのホワイトノイズ（白色雑音）の定義

```math
R_0 = 1, R_k = 0 (k \neq 0)
```
kはlag。lagが0の時は全てのデータは一致しているので自己相関は１、それ以外のlagでは自己相関が０になる時系列データのこと。

pythonでホワイトノイズを生成
-

平均０、標準偏差1のホワイトノイズ
```python
mean = 0
sd = 1
x = np.random.normal(mean, sd, 300)
plt.figure(figsize=(12,4))
plt.plot(x)
plt.show()
```
![スクリーンショット 2023-01-09 17.30.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707093/d46a4159-794f-8985-b326-fb7ef30638e9.png)

自己相関を確認。
```python
import statsmodels.api as sm
sm.graphics.tsa.plot_acf(x, lags=100)
plt.show()
```
![スクリーンショット 2023-01-09 17.32.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707093/c3372ffc-5b11-c62e-dfda-a68b95016bb4.png)
偶然、９５％信頼区間外にあるデータもあるが、k = ±1,±2,・・・,±100において自己相関がほぼ０であることが確認できる。

ホワイトノイズのスペクトル
-
ホワイトノイズのスペクトル（フーリエ変換後の値のこと）があらゆるスペクトルをフラットに含んでいることなどを図示しようとしたが、想定した綺麗な結果(y=１０のようなフラットな直線)にはならなかった。
```python:White_Noise
mean = 0
sd = 1
size = 300
x = np.random.normal(mean, sd, size)
X = np.fft.fft(x)
freqs = np.fft.fftfreq(len(x))
fig2, ax2= plt.subplots()
ax2.stem(freqs, np.abs(X), use_line_collection=True) # フーリエ変換の結果をステム(茎)プロットする
ax2.set_xlabel('Frequency in Hertz[Hz]')
ax2.set_ylabel('Frequency Domain (Spectrum) Magnitude')
ax2.set_xlim(0)
plt.show()
```
![スクリーンショット 2023-01-09 18.01.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707093/5f81d8bb-da49-7ccd-d9b2-4914d5581606.png)

sinカーブのスペクトル
```python:sin_curve
f_s = 1000# サンプルを観測する間隔
f = 100 #周波数
sin_range = np.linspace(0,10,f_s)
x = np.sin(f * 2 * np.pi * sin_range)
plt.plot(sin_range, x)
plt.show()
```

![スクリーンショット 2023-01-09 18.13.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707093/02071182-d557-7f8e-1209-7908e3cb8788.png)

```python:フーリエ変換、スペクトルの確認
X = np.fft.fft(x)
freqs = np.fft.fftfreq(len(x))*f_s

fig2, ax2= plt.subplots()
ax2.stem(freqs, np.abs(X), use_line_collection=True) # フーリエ変換の結果をステム(茎)プロットする
ax2.set_xlabel('Frequency in Hertz[Hz]')
ax2.set_ylabel('Frequency Domain (Spectrum) Magnitude')
ax2.set_xlim(0)
plt.show()
```
一応、ラインスペクトル（単振動の場合のスペクトル）っぽい形を確認できる。
![スクリーンショット 2023-01-09 18.28.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2707093/c67cbcbe-82d5-2842-d165-9cd8724a7659.png)


https://www.itd-blog.jp/entry/voice-recognition-10#1-Python%E3%81%A7%E3%82%B9%E3%83%9A%E3%82%AF%E3%83%88%E3%83%AB%E8%A7%A3%E6%9E%90
「ネットワーク資格情報の入力」とかいう敵に小突かれた話

# 背景など
現職場には検証用のWindows10端末があり、諸目的で色々な設定を行っています。ある時、社内の共有フォルダ（NAS）に接続しようとするとネットワーク資格情報の入力が求められるようになりました。他のWin10端末ではこれといった認証も無しに使用できているのに何で？と思いトラブルシューティングを行いました。その結果、やや不慣れな解決に至ったので投稿させていただいた次第です。

# 作業環境
* NAS ・・・　I-O DATA製1台、Synology製1台
* 問題端末　・・・　Windows10 Pro（22H2）

# 敵
![20230106_ネットワーク資格情報.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394613/617f0f97-ba96-2dde-6c9e-356445f8ccd6.png)

# 事象
**できていること**
* NASはパスワード無しでアクセスできるようなゲスト用のアカウントを作成しており、問題となっている端末以外はネットワーク資格情報の入力なしに接続できている。\\\\IPアドレスや\\\\ホスト名をエクスプローラで検索すれば認証なしに出てくる状態。
* NASに設定されているローカルアカウントをWindows資格情報に登録すると問題なく接続できる。

**できていないこと**
* Windows資格情報の登録やネットワーク資格情報の入力がなければNASにアクセスできない。
* 何れのメーカーのNASに対しても同様の現象。
* 敵はネットワーク資格情報の入力のPIN入力を求めてくるのですが、端末に設定されているPINを入力しても「ユーザー名またはパスワードが正しくありません」としてはじかれる。



# 歴戦のナレッジ
「Windows10　ネットワーク資格情報の入力」で検索をかけると以下のような記事があったのでまずはそれらを参考にしました。
https://www.iodata.jp/support/qanda/answer/s30089.htm
https://togeonet.co.jp/post-17466
https://aprico-media.com/posts/2380

「SMB1vが有効になっていない」というのは何度か経験があります。しかし、何れのNASもまあまあ新しいモデルなのでここが原因じゃないことは何となく想像できました。
「gpedit.msc」からいじれる［安全でないゲストログオンを有効にする］とやらも未構成→有効にしてみたのですが、解決せず。
やっぱりと言えばそうなんですが、Windows資格情報を入力することも解決策ではあるのですが、他の端末でできている以上納得はいきませんでした。

# 解決まで
とりあえず挙げられているナレッジはすべて試してみようということで、ネットワークの種類がプライベートであるか確認することにしました。現環境はWifi環境とイーサネット環境が同居しており、インターネット接続はWifiで、NAS接続はイーサネットで、という具合に運用しております。

![20230106_ネットワーク接続状態.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394613/840480e0-7237-409e-5038-496f905de624.png)

ここでそれぞれのプロパティをクリックするとWifiの方はパブリックとプライベートの切り替えが可能なんですが、イーサネットの方は識別されていないネットワークとして認識されていてパブリックとプライベートの切り替えはおろか現在の状態もわからないままでした。
![20230106_ネットワーク接続状態比較.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394613/fcb84168-a72a-a976-6f91-b0f0895602f8.png)

んで、改めて調べなおしてみると以下の記事を見つけました。
https://www.projectgroup.info/tips/Windows/comm_0064.html

なんでも、デフォルトゲートウェイが設定されていないネットワークは識別されていないネットワークとなり、パブリックネットワークとして扱われるのだとか。まずこの点がドンピシャでした。そして識別されていないネットワークをプライベートに変える手順も続けて記述がなされていたので、以下の通りに設定を変更。（手順は上記記事参照）

![20230106_識別されていないネットワーク.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/394613/6cd95f37-6495-bd41-3bb5-ca155eac5b17.png)

変更直後、NASにアクセスできるようになっていました。

# 所感
すぐに解決するだろうと思っていたトラブルでしたが、意外とてこずりました。
結局のところ原因がいまいち分かっていません。。。
一応その検証機と常用機で違っている点としては、
* Windowsのログインに使うPINを設定している
* セキュリティソフトが常用機はウィルスバスターであるのに対し、検証機はMicrosoft 365由来のMicrosoft Defenderである

というのが主な違いです。ネットワーク資格情報の入力の画面ですが、常用機の表示と少し違っています。検証機はPIN？のアイコンが表示されており、このPINの設定がネットワーク資格情報の入力を強力にしているのかなと予想しています。

たかがネットワーク資格情報だと思っていましたが、まさかパブリックネットワーク・プライベートネットワークの違いで反応が異なるとは思いませんでした。解決に至ったナレッジはどのようなトラブルを元に投稿されたのかは定かではありませんが、感謝です。

以下のことで躓いている方がいらっしゃったら、ググった先に上記の記事や当記事を見て何かの参考になればと思います。
* 突然ネットワーク資格情報の入力が現れた
* ネットワーク資格情報の入力がはじかれる
* ネットワーク資格情報の入力でPINの入力を求められる
* 識別されていないネットワークのネットワーク種類を変更する
Django + nginx + gunicorn + EC2(AWS)でアクセス系のエラー

◆前提

.bash_profileやNginxの設定ファイルを変更時は確かに反映させるように
gunicornも再起動させること

◆主な登場人物
セキュリティグループ(EC2)
.bash_profile
nginx.conf
settings.py

◆諸々エラー

◎502 Bad Gateway, CONNECTION_REFUSED
→EC2のセキュリティ設定がおかしい（ポートが開いていないとか）
→nginxで正しいportをlistenしていない
例）EC2でポート80番を許可しているが、nginxは10080番で待ち受けている

◎400 Bad Request
ALLOWED_HOSTSが誤っている
※os.environ.get('ALLOWED_HOSTS')は上手くいかないみたい
PrePoMaxによる等分布荷重を受ける両端支持梁（はり）の曲げ応力の計算

# はじめに
[前回](https://qiita.com/_Moony/items/8c30daaec5622489eb32)FreeCADで作成したモデルをPrePoMaxに読み込ませて、等分布荷重を受ける両端支持梁の曲げ応力とたわみを計算しました。

# 梁の寸法と荷重位置
図1に示します。材料は鋼（ヤング率210GPa、ポアソン比0.30）とします。荷重は単位長さ当たり1N/mmとします。梁全体には1000Nの荷重が加わっていることになります。

<img width="600"  alt="スライド3.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/4b93114b-3ff1-b903-e5b4-b2bef932e157.jpeg">

図1　等分布荷重を受ける両端支持梁の寸法

# 使用したモデルと境界条件
[前回](https://qiita.com/_Moony/items/8c30daaec5622489eb32)FreeCADで作成した1/4モデル（幅と長さをそれぞれ1/2としたモデル）を使います。荷重のかけ方以外の境界条件とメッシュサイズは前回と同じ（最大サイズ5mm）です。荷重は20mm×500mmの面全体に250Nを加えます（SurfaceTractionを使用）。図2に1/4モデルと設定した境界条件を示します。

<img width="600"  alt="スライド31.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/781b332d-8713-ee84-f256-36d66a057155.jpeg">

図2　1/4モデルの境界条件の設定

# 結果

図3に示しました。
Z変位の最小値が-2.33 mm（下方向に最大値）、X軸方向の応力の最大値が46.88MPaとなりました。材料力学による理論値は変位が2.33mm、応力値が46.88MPaですので、理論値と一致した結果が得られました。X軸方向の応力の最小値も-46.88MPaと理論値と一致しました。
なお、PrePoMaxには図4に示すように結果を対称表示する機能もあります。

<img width="600"  alt="スライド31.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/4f236ba7-291f-399f-fff5-2269014db0a6.jpeg">

図3　等分布荷重を受ける両端支持梁の1/4モデルのX軸方向の垂直応力の計算結果

<img width="600"  alt="[スライド33.JPG" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1729073/31d655ca-f0c0-53f2-017f-cbe65910ca52.jpeg">

図4　結果の対称表示
Git ブランチの使い方

<h4>・ブランチとは</h4>
　ブランチとは、gitの変更履歴を枝分かれさせる機能である。仕様を変更したいときや新しく機能を追加する際、１つのファイルにコードを書いてしまうとバグが発生した時に全体に影響を及ぼしてしまう。<br>
　そこでブランチを使うことによって、今使っているファイルとは別の場所にコードを書くことができ、たとえバグが起きたとしても全体に影響を及ぼさずにコーディングをすることができるのである。

<h4>・使い方</h4>

<h5>・ブランチの作り方</h5>
　①コマンドプロンプトで"<b>git checkout -b ”作りたいブランチの名前” master</b>"と入れる<br>
　⇒ `checkout` はブランチを切り替えるコマンド<br>
　　 `-b` と入れるとブランチの新規作成になる<br>
　　 ※`git branch "作りたいブランチの名前"` でもブランチを新規作成できる。（切り替えは行われない）<br>
　　 最後に入れる `master`　はmasterブランチから切り替えるという意味になる。

<h5>・ブランチの切り替え方</h5>
　①コマンドプロンプトで"<b>check checkout "切り替えたいブランチの名前"</b>"と入力する<br>
　⇒"<b>git branch</b>"と入れると現在自分がいるブランチと作られているブランチを見ることができる。

<h5>・ブランチのマージ</h5>
　マージとは、masterと分けたブランチとmasterを合流させることである。

　①`checkout ”ブランチ名(master)”`で、はじめに合流させたい、もとにしたいブランチに移動する。
　②次に"<b>git merge ”合流させたいブランチ”</b>"を入力すると完了する。
　③最後にリモートに反映させるためにプッシュをする。
　⇒`git push "ブランチ名"(master)`で完了

【参考】
【Git入門】Git + Github使い方入門講座🐒Gitの仕組みや使い方を完全解説！パーフェクトGit入門！
https://www.youtube.com/watch?v=LDOR5HfI_sQ
Progate HTML&CSS 中級編で学んだこと

## HTMLでクラスを付ける方法

タグにclass="(クラスの名前)"と書く。
※ダブルクオーテーション(")を忘れがちなので気を付ける

## CSSでクラスを指定する方法

クラス名の前にドット(.)を書く。
HTML&CSSの初級編をやったのが1カ月ほど前だから忘れていました。

<h3>CSSでクラスの中にあるh1やpなどを指定する方法

`
.(クラス名) (指定したい中身) {
}
`


とする。

私は`h1{ }`このように書きましたが、プロゲートの見本と同じような内容になっており、クリア判定になりました。
→もしもh1タグが他のクラスにもあった場合、そのクラスのh1タグにも処理内容が反映されてしまうようです。

## link relのrelはrelationの略。

rel属性は「linkタグが書かれているページとhrefで指定しているページとの間で、どのような関係があるのか」を示す。
リンクといえばaタグを思い浮かべますが別物のようです。
linkタグとaタグの違いはhttps://saruwakakun.com/html-css/basic/link-rel　
この記事がとても勉強になりました。

## opacityとrgbaの違い
どちらも何かを透明にするのに使うけれど、opacityプロパティが対象のものすべての透明度を決めるのに対して、rgbaは背景色のみの透明度を変えることが出来ます。
rgbaのaはalphaを意味しているようですが、英単語のalphaには透明的な意味は無いようです。

alphaについて：https://tmotooka.hatenablog.jp/entry/2014/02/23/222102

opacityとrgbaの違いについて：https://x.gd/g2n3F
Flutter開発のノウハウなど

<pre>よく使うサイト</pre>

■Webボタンを作れるサイト
http://box.aflat.com/buttonmaker/

＜アイコンの作成＞
■Canva
https://www.canva.com/
アイコンの場合、サイズは1024*1024にする

■アイコンファイルに落とす
App Icon Generator
https://www.appicon.co/

<pre>アプリのバージョン指定</pre>
pubspec.yamlに記述したものが反映される　
例
version: 1.0.1+2
pythonコードを暗号化(難読化)【pyarmor】

<iframe width="560" height="315" src="https://www.youtube.com/embed/dTe2_j1qIYc" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen></iframe>

pythonファイルを共有するときに見られたくない部分があるかと思います。

「pyarmor」を利用することで、それを可能にすることができます。

```
python -m venv test
.\test\Scripts\Activate
pip install pyarmor
```
今回暗号化するのはこの`armor.py`ファイル
```python
import tkinter
import tkinter.ttk as ttk

class Application(tkinter.Frame):
    def __init__(self, root):
        super().__init__(root)
        root.title('Sample')
        root.geometry('400x300')
        self.set_widgets(root)

    def set_widgets(self, root):
        select_list = ['SelectA', 'SelectB']
        combobox = ttk.Combobox(root, values=select_list)
        combobox['values'] = ['SelectA', 'SelectB']
        combobox.pack()
        button = tkinter.Button(text="表示",command=lambda:print(combobox.get()))
        button.pack()

def main():
    root = tkinter.Tk()
    app = Application(root)
    root.mainloop()

if __name__ == "__main__":
    main()
```
難読化してみます。
```
pyarmor obfuscate armor.py
```
作成できたファイルは、`dist`ディレクトリ内に格納されているので、開いてみます。
![](https://storage.googleapis.com/zenn-user-upload/0d5403f4c205-20230109.png)
問題ないく、難読化できていることが確認できました。
ただ、実行してみると日本語が文字化けしてしまいました。

![](https://storage.googleapis.com/zenn-user-upload/1bf76e880fa8-20230109.png)

ソースの最初に以下の文字コードを追加して再度難読化してみます。
```
# -*- coding: utf-8 -*-
```
次は問題なく、難読化することができました。
![](https://storage.googleapis.com/zenn-user-upload/7c2fa7227dfd-20230109.png)

使い方がわからなくなった。
そんな場合は、どのライブラリでも`--help`オプションが用意しているので、確認してみてね。
```
pyarmor --help
```
実行結果
```
usage: pyarmor [-h] [-v] [-q] [-d] [--home HOME] [--boot BOOT]  ...

PyArmor is a command line tool used to obfuscate python scripts,
bind obfuscated scripts to fixed machine or expire obfuscated scripts.

optional arguments:
  -h, --help     show this help message and exit
  -v, --version  show program's version number and exit
  -q, --silent   Suppress all normal output
  -d, --debug    Print exception traceback and debugging message
  --home HOME    Change pyarmor home path
  --boot BOOT    Change boot platform

The most commonly used pyarmor commands are:

    obfuscate (o)
                 Obfuscate python scripts
    licenses (l)
                 Generate new licenses for obfuscated scripts
    pack (p)     Pack obfuscated scripts to one bundle
    init (i)     Create a project to manage obfuscated scripts
    config (c)   Update project settings
    build (b)    Obfuscate all the scripts in the project
    info         Show project information
    check        Check consistency of project
    hdinfo       Show all available hardware information
    benchmark    Run benchmark test in current machine
    register     Make registration keyfile work
    download     Download platform-dependent dynamic libraries
    runtime      Generate runtime package separately
    help         Display online documentation

See "pyarmor <command> -h" for more information on a specific command.

More usage refer to https://pyarmor.readthedocs.io
```
t3-stack入門 (9) Todoフォームのリファクタリング


TodoEditコンポーネントがちょっとゴチャゴチャしてきたので整理します。

## カスタムフックの作成

TodoEditで利用しているHookをカスタムフックにして、src/hooks/todo.tsに追い出します。
```typescript
import { createTodoSchema } from "../schema/todo";
import { trpc } from "../utils/trpc";
import { useForm, zodResolver } from "@mantine/form";
import { useEffect } from "react";
import { type EditingTodo } from "../types/todo";

const useTodoEdit = (editingTodo: EditingTodo) => {
  const utils = trpc.useContext();
  const form = useForm({
    initialValues: {
      id: null as number | null,
      title: "",
      description: "",
    },
    validate: zodResolver(createTodoSchema),
  });
  useEffect(() => {
    form.setValues(editingTodo);
  }, [editingTodo]);

  const createTodo = trpc.todo.create.useMutation({
    onSettled: () => {
      utils.todo.getAll.invalidate();
    },
  });
  const updateTodo = trpc.todo.update.useMutation({
    onSettled: () => {
      utils.todo.getAll.invalidate();
    },
  });
  return { form, createTodo, updateTodo };
};

export default useTodoEdit;
```

## Updateに必要なTodoの情報をTodoEdit内部で取得する
Updateに必要なTodoの情報を、TodoEditにprops経由で伝えていますがちょっと微妙な気がします。
たまたま今回はTodo一覧にUpdateに必要なTodoの情報がすべてそろっていましたが、いつもそうとは限りません。
また、Updateに必要なTodoの情報が変化したとき、TodoEdit内部だけでなく、利用側も変更が必要です。
TodoEditに渡す情報は必要最低限(Todoのid)で、必要な情報はTodoEdit内部で取得したほうがよいでしょう。

というわけで、propsで渡されたidからTodoデータをtrpcでとってきて、そのデータが更新されたらsetValuesを呼び出すことにします。
```diff_typescript
@@ -14,9 +14,15 @@ const useTodoEdit = (editingTodo: EditingTodo) => {
     },
     validate: zodResolver(createTodoSchema),
   });
+  const { data } = trpc.todo.get.useQuery(
+    { id: editingTodoId as number },
+    { enabled: editingTodoId != null }
+  );
   useEffect(() => {
-    form.setValues(editingTodo);
-  }, [editingTodo]);
+    if (data) {
+      form.setValues(data);
+    }
+  }, [data?.id]);
```
最初、editingTodoIdがnullだったらuseQueryを実行してsetValueを実行しようとしていたのですが、hooksをif分内で使用してはいけないという制約があるので、うまくいきませんでした。最終的にTanstack queryにenableオプションというのが用意されていたので、editingTodoIdがnullでない時だけQueryを実行するように変更しました。

ここまでの変更は以下の通りです。

https://github.com/bioflowy/t3-todo-example/commit/27d60007a58c7d1f520e58de094a400eeed64553#diff-85f221b6360d085a7fb13ac43c3678f05970ca0c3ee8853b99268d8472c08569
エルガマル（ElGamal）暗号についての簡単な備忘録

# エルガマル暗号とは
離散対数問題の困難性をもとにした公開鍵暗号方式の一種です。Tsher ElGamalによって発表されました。この暗号方式はランダムに生成される数(乱数)、3つの公開鍵、1つの秘密鍵によって成立しています。
![ElGamal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3054254/83124818-8359-397e-84f7-ec6c37b031be.png)


# 秘密鍵と公開鍵について
ここで使用する秘密鍵と公開鍵は次のような条件を満たしているものとします。
```math
v = a^s\:(mod\: p)
```

# 暗号化
※これは送信者が行う処理
1. 乱数`r`を生成する。ただし自然数。
1. 受信者の公開鍵`p, a, v`を用いて次の2つの数を生成し、送信する。
```math
c_1 = a^r \:(mod\: p)\\
c_2 = wv^r \:(mod\: p)
```

# 復号
※これは受信者が行う処理
1. 秘密鍵`s`を用いて次のようにして平文`w`を生成する。
```math
w = (c_1^s)^{-1}c_2 \:(mod\: p)
```
【Rails,Docker】Zeitwerk::NameError: expected file

ローカルで動いたDocker+Railsアプリを本番環境で動かそうとしたところ、Webコンテナ(nginx)は立ち上がったが、appコンテナ(puma)のステータスがexitedになる状況が起こった。
docker logs で確認したところ、以下のようなエラー分が検出された。
```:log
Zeitwerk::NameError: expected file /app_name/app/controllers/function.rb  to define constant ... 
```
今回の場合、コントローラーに定義する関数が長くなり可読性を損なうため、ファイルを別のファイル(function.rb)で定義して、includeでコントローラに取り込んでいる。そのため、controllers配下に関数を定義するファイルがなく、Zeitwerk（Rails6.01から標準となっている定数の自動読み込み機能）がそれを検知してエラーを吐く。

# 対処法
config/application.rbに```config.autoloader = :classic```を追記

```ruby:config/application.rb
module App
  class Application < Rails::Application
    config.autoloader = :classic
  end
end
```
Zeitwerkモードを利用しないように設定を変更している。これで一応動くようになるが、そもそも関数をどこに、どのように定義すべきなのか、その辺の課題は依然残る。
npm ERR! code EACC発生時の対処法

- エラー内容
`npm install -g` コマンド実行時にエラーになる
```shell:エラー内容
$ npm install -g json-server
npm ERR! code EACCES
npm ERR! syscall mkdir
npm ERR! path /usr/local/lib/node_modules/json-server
npm ERR! errno -13
npm ERR! Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/json-server'
npm ERR!  [Error: EACCES: permission denied, mkdir '/usr/local/lib/node_modules/json-server'] {
npm ERR!   errno: -13,
npm ERR!   code: 'EACCES',
npm ERR!   syscall: 'mkdir',
npm ERR!   path: '/usr/local/lib/node_modules/json-server'
npm ERR! }
npm ERR!
npm ERR! The operation was rejected by your operating system.
npm ERR! It is likely you do not have the permissions to access this file as the current user
npm ERR!
npm ERR! If you believe this might be a permissions issue, please double-check the
npm ERR! permissions of the file and its containing directories, or try running
npm ERR! the command again as root/Administrator.

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/【ユーザ名】/.npm/_logs/2022-12-18T08_49_13_519Z-debug-0.log
```

- 対処法
管理者権限で実行する
```shell:エラー内容
$ sudo npm install -g json-servernotice
[sudo] password for 【ユーザ名】:

added 109 packages in 4s
```
ビューを使ってエラーメッセージを表示させる

# このエラーメッセージを真似してみる。
```html
<% if @article.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@article.errors.count, "error") %>が原因でこの記事を保存できませんでした</h2>

    <ul>
      <% @article.errors.each do |error| %>
        <li><%= error.full_message %></li>
      <% end %>
    </ul>
  </div>
<% end %>
```
### 出典
https://railsguides.jp/active_record_validations.html#%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3%E3%82%A8%E3%83%A9%E3%83%BC%E3%82%92%E3%83%93%E3%83%A5%E3%83%BC%E3%81%A7%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B:~:text=%3C%25%20if%20%40article.errors.any%3F%20%25%3E%0A%20%20%3Cdiv%20id%3D%22error_explanation%22%3E%0A%20%20%20%20%3Ch2%3E%3C%25%3D%20pluralize(%40article.errors.count%2C%20%22error%22)%20%25%3E%E3%81%8C%E5%8E%9F%E5%9B%A0%E3%81%A7%E3%81%93%E3%81%AE%E8%A8%98%E4%BA%8B%E3%82%92%E4%BF%9D%E5%AD%98%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%9B%E3%82%93%E3%81%A7%E3%81%97%E3%81%9F%3C/h2%3E%0A%0A%20%20%20%20%3Cul%3E%0A%20%20%20%20%20%20%3C%25%20%40article.errors.each%20do%20%7Cerror%7C%20%25%3E%0A%20%20%20%20%20%20%20%20%3Cli%3E%3C%25%3D%20error.full_message%20%25%3E%3C/li%3E%0A%20%20%20%20%20%20%3C%25%20end%20%25%3E%0A%20%20%20%20%3C/ul%3E%0A%20%20%3C/div%3E%0A%3C%25%20end%20%25%3E

# エラーが起きた
@userがnilになっているかららしい。
保存されていないからこれがnilになったのだろう。
```<% if @article.errors.any? %>```が原因だと思う。
@userが存在することを証明できなければいいから

これにした。
```html
<% if @user && @user.errors.any? %>
  <%= render("shared/error_form") %>
<% end %>
```
成功。

# rubymineの色を薄くできた。
スタイルシートのファイルで色の四角をクリックすると色の濃さを指定できた。
これは使って良かったかどうかはわからない。
が便利だ。

# その他
どこかでerrors.clearが使えそうだが、まだアイデアがこない。
リロードしたら、エラーメッセージを消したい。
これはjavascriptを使うのだろうか？

```rb
irb(main):035:0> user = User.new
=>
#<User:0x0000000115e6f4b8
...
.
.
.
irb(main):037:0> user.errors.empty?
=> true

irb(main):038:0> user.save
  TRANSACTION (0.2ms)  SAVEPOINT active_record_1
  User Exists? (0.4ms)  SELECT 1 AS one FROM `users` WHERE `users`.`email` IS NULL LIMIT 1
  TRANSACTION (0.2ms)  ROLLBACK TO SAVEPOINT active_record_1
=> false

irb(main):039:0> user.errors.empty?
=> false

irb(main):040:0> user.errors
=> #<ActiveModel::Errors [#<ActiveModel::Error attribute=password, type=blank, options={}>, #<ActiveModel::Error attribute=name, type=blank, options={}>, #<ActiveModel::Error attribute=name, type=too_short, options={:message=>"1文字以上から10文字以下で入力してください。", :count=>1}>, #<ActiveModel::Error attribute=email, type=blank, options={}>]>
irb(main):041:0>
```
Linux基礎（学習用）

●ファイルのコマンド
・cat・ファイルの中身を表示するコマンド、複数のファイルを指定して表示できる
(-n)・行番号の表示

・less・ファイルの中身をスクロール表示する、長いファイルを見たい時に有効

●ファイルには大きく分けるとテキストファイルとバイナルファイルの二種類がある

・テキストファイル・文字列が書かれたファイル、LinuxではOSに関わる情報のほとんどをテキストファイルで保存している
・バイナリファイル・画像ファイル、音声ファイル、実行ファイル(つまりテキスト以外）

・touch・空のファイルを作成するコマンド（間違って存在するファイルを指定しても上書きしない）
・rm・ファイル・ディレクトリの削除 *ゴミ箱ではなく本当に削除
（rm -r dir)ディレクトリも合わせて削除
（rm -i file)ファイルの削除前に確認する

・mv・ファイルを移動する,mv 移動元　移動先　移動先がディレクトリのときは物理的な移動
先がファイル名の時はファイル名の変更となる

・cp・cp　コピーもと　コピー先　＊コピー先のファイルが既にあると上書きする
(cp -r)ディレクトリのコピー,中身のファイルも一緒にコピーされる

●リンクを貼る・・Linuxではファイルに別名をつけることができ、そのことをリンクを貼るという
1,ハードリンク、1つのファイルに複数の名前をつける、元のファイルを削除しても消えない
２、シンボリックリンク・リンク先のファイルが書かれた特殊なファイル,リンク先のパス名を記載しただけ

・ln・リンクを貼る　ln リンク元の名前　リンク名 オプションを何もつけないとハードリンクになる
(-s)シンボリックリンクを貼る

・どのような時にリンクを用いるか・長いパス名を省略したいとき、複数バージョンを共存させて最新を区別したいとき

・find・ファイルを検索する　find ＜検索開始ディレクトリ＞＜検索条件＞＜アクション＞
>検索条件　
-name・ファイル名を検索してファイル名を検索、大文字小文字を区別
-iname・ファイル名の大文字小文字を区別しない
-type ファイルの種類で検索
-a 複数の検索条件を指定するため
AzureSQLでREST APIのパラメータ入力で沼った事

AzureSQLでREST APIを使ってみたいので下記のサイトでテスト接続を行ってみました。

https://learn.microsoft.com/ja-jp/rest/api/sql/2021-02-01-preview/databases/get?tabs=HTTP#code-try-0

しかしパラメータ入力の正解が分からず何時間も費やしてしまいました・・・

備忘録としてまとめてみます。


# GETのURL

GETメゾットを利用する際に使用するURLです。
```:GET
https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroupName}/providers/Microsoft.Sql/servers/{serverName}/databases/{databaseName}?api-version=2021-02-01-preview
```

# 必須パラメータ
その内に必須パラメータが5つあります。(公式サイトから引用しています)

<table border>
<tr>
<td>Name</td>
<td>In</td>
<td>Type</td>
<td>Description</td>
</tr>
<tr>
<td>databaseName</td>
<td>path</td>
<td>string</td>
<td>データベースの名前。</td>
</tr>
<tr>
<td>resourceGroupName</td>
<td>path</td>
<td>string</td>
<td>リソースが含まれているリソース グループの名前。 この値は、Azure リソース マネージャー API またはポータルから取得できます。</td>
</tr>
<tr>
<td>serverName</td>
<td>path</td>
<td>string</td>
<td>サーバーの名前。</td>
</tr>
<tr>
<td>subscriptionId</td>
<td>path</td>
<td>string</td>
<td>Azure サブスクリプションを識別するサブスクリプション ID。</td>
</tr>
<tr>
<td>api-version</td>
<td>path</td>
<td>string</td>
<td>要求で使用する API のバージョン。</td>
</tr>
</table>

# Azureの管理画面　

Azureの管理画面でどれに当てはまるのか・・・

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/32ef8dd6-086e-eed2-e09e-e12a3d6ec4ac.png)

画像を参考にして頂いたら早いと思います。

databaseNameはアイコン横に書いてあります。
resourceGroupNameはリソースグループでした。
serverNameが[windows.net]の前の名前です。（これが分からずに時間掛かった・・・）
subscriptionIdはサブスクリプションIDでした。


# REST APIを試す
実際にAPIを試してみました。

https://learn.microsoft.com/ja-jp/rest/api/sql/2021-02-01-preview/databases/get?tabs=HTTP#code-try-0

こちらのサイトのフォーカスモードを利用します。

使ってみるをクリック。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/57f5c681-737f-5dc3-ebf8-4a50f0487785.png)

Azureを利用しているアカウントでログインして下さい。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/0c5a04a3-99a7-a752-d20b-e6865df6bd51.png)


上手く入力できたら200番コードが返ってきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3028739/78b2590a-c2d4-a932-b90e-086cf64bd894.png)

これで必要なパラメータが理解できました！



# 関連記事

https://qiita.com/donnma777/items/15ab9dc4414cec70363b
SwiftUI WidgetKit ロック画面用、GaugeのLabelのfontサイズ適正を探す

![](https://kumonosu.cloudsquare.jp/wordpress/wp-content/uploads/2023/01/pcac.png)

 **bodyくらいということ**

```swift
Gauge(value: self.entry.pcwidgetmodel.clockDate.nowPercent() / 100) {
    Image(systemName: String(self.entry.pcwidgetmodel.selectClock) + ".square")
        .font(.body)
} currentValueLabel: {
    Text("\(Int(self.entry.pcwidgetmodel.clockDate.nowPercent()))")
}
.gaugeStyle(.accessoryCircular)
```
AWS、EC2のデータベース操作（RDSを使用していない場合）

## 初めに
AWSのEC2にデプロイしたアプリケーションのデータベース操作についてです。（AWSのRDSは使用していません）
Railsアプリのデータベース操作が調べてもなかなか見つからなかったので（かつ調べたの2回目なので・・・）自身の備忘のための記事です。

## 本記事の内容
- EC2にデプロイしたアプリケーションのデータベースの操作方法の紹介（2パターン）
　1. ターミナルからSSH接続
　2. Sequel ProからSSH接続

## 必要なもの
- インスタンスへログインするためのSSH秘密鍵の名前（〜.pem）
- EC2インスタンスのElasticIP
- データベースのrootのパスワード（設定していれば）

## ターミナルから操作する場合
### EC2へのSSH接続
```:ターミナル（ローカル）
// ディレクトリの変更
cd .ssh

// EC2インスタンスへSSH接続
ssh -i 秘密鍵の名前.pem ec2-user@Elastic IP

// 上記の実例（適当なキー名とIPです）
ssh -i aws_key.pem ec2-user@52.68.59.32
```

EC2ロゴが浮かび上がり（？）プロンプト（$マークや%マークの左側）が```[ec2-user@ip-172-31-45-212 ~]```のようになっていればEC2への接続成功です。

<br>
<br>
<br>
ちなみに浮かび上がるとは・・・

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

み、見える・・・
（余計な記述すみません。）

### DBへの接続
```:ターミナル（EC2）
// DB接続（mariaDBでも下記コマンドで接続できます）
mysql -u root -p
```

パスワードを設定していれば、以下のように求められるので入力してEnter（キーボードを叩いても表示されませんが入力されています）

```
Enter password: 
```
```
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 159
Server version: 5.5.68-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> 
```
となればOK！
あとは通常のSQL文（show databases;など）で操作できます。


## Sequel Proを利用する場合
GUIなツールですね。スクールで教えてもらいましたが、簡単にデータベースが確認できて便利です。
（慣れればターミナルから見る方が便利なのかも知れませんが...）

[Sequel Proの公式サイトはこちら](https://www.sequelpro.com/)


1. Sequel Proを起動し、左下の「＋」マークを選択し新規接続情報を作成（名前はEC2でもリポジトリ名でも適当に）
1. 項目を入力
    - MySQLホスト：ElasticIP
    - ユーザー名：root
    - パスワード：データベースのrootのパスワード（設定していれば）
    - ポート：3306
    - SSHホスト：ElasticIP
    - SSHユーザー：ec2-user
    - SSH鍵：右側の鍵マークをクリックするとファイル選択画面が開くので、.pemファイルを選択

    ↓入力・選択例です（ElasticIPなどは適当なものです）
    ![スクリーンショット 2023-01-09 16.08.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3097649/e2498527-aa65-dc19-334e-bf607a8e3e0b.png)


3. ```接続をテスト```をクリックして、```接続が成功しました```と表示されればOKです
4. ```お気に入りに追加```をクリックすると左上のお気に入りに追加され、Sequel Proを開き直してもすぐに接続可能となります

```接続```をクリックしたあとは通常のSequel Proと同様です！

## 参考にさせていただいたサイト・記事

https://techtechmedia.com/db-production-aws/

https://qiita.com/naginx/items/9b6fcad470474f8e09e9