OmniAICreator/Qiita-1.07M huggingface dataset:
【AWS】 EC2を起動してターミナルでSSH接続する。

## 環境
・MacOS Monterey
・AWS(無料版)

## 前提
今回は簡単にAWSでEC2を起動しSSH接続する方法を書いていきます。
なので用語や詳細などの説明は省き、既にAWSアカウントを登録してあることを前提にします。

## EC2を起動する
AWSのトップ画面から"EC2"を選択。
![スクリーンショット 2023-01-16 15.58.54.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005744/deb65ef9-a3e7-0a0c-998f-522dfab79ae7.png)



すると、色んな情報が表示されていますが、"インスタンスを起動"を選択。

![スクリーンショット 2023-01-16 16.04.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005744/03de183b-5110-3f5e-8330-c93adef76b88.png)
***

## インスタンス設定
この画面で起動するインスタンスの設定を行います。
今回はSSH接続することが目的なので設定は基本デフォルト(無料版）で行います。

**・名前**
インスタンスの名前です。分かりやすいのでOK。私は"test-EC2"で行います。

**・アプリケーションおよびOSイメージ**
インスタンスのOSを設定します。今回はAmazonLinux2(無料利用枠の対象)を選択。
![スクリーンショット 2023-01-16 16.37.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005744/6d20b964-ef63-a5e7-f4e0-7502176e1a10.png)


**・インスタンスタイプ**
インスタンスに必要なメモリなどの設定です。今回はt2.micro(無料利用枠の対象)を選択。

**・キーペア（ログイン）**
インスタンスに安全にログインする鍵です。既存又は新規作成した鍵を選択。


**・ネットワーク設定**
IPやHTTPSなどの設定です。今回はデフォルトで構いません。
![スクリーンショット 2023-01-16 16.43.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005744/fecf6828-bbc5-e64a-bcda-4ee86da7d496.png)



**・ストレージ設定**
インスタンスのストレージ設定です。これもデフォルトで構いません。

**・高度な詳細**
今回は触りません。



設定し終わったら、"インスタンスを起動"を選択しインスタンスを起動させてください。


***




`成功`と表示されたら青文字で表示されているインスタンスIDをクリックしてください。
![スクリーンショット 2023-01-16 17.48.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005744/989a3f88-fda3-ae6b-4fbf-b7325eb987be.png)

***

そしてインスタンス管理画面に行き、左上の`接続`を選択してください。
`この画面に記されている”パブリックIPv4アドレスを使用するのでコピーしといてください”`

![スクリーンショット 2023-01-16 17.53.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005744/b9fa966c-a6fe-7f47-4e85-aa189f39121d.png)


ここでEC2のユーザー名を設定できます。
今回はデフォルトの"ec2-user"を使用します。
![スクリーンショット 2023-01-16 18.03.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1005744/fd578d28-b173-f3c8-7fff-034f36018272.png)

## SSH接続

上記のEC2の設定が完了したらターミナルを起動してください。

EC2起動時に設定されたIPv4アドレスを[パブリックIP]に入力し、
指定したキーペアの鍵ファイル名を入力。









```
$ ssh ec2-user@[パブリックIP] -i ~/.ssh/[指定したキーペアのファイル名]
```

そしたら質問されるので"yes"を入力
```
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
 ```

鍵が認証されて上手くいけば下記の表示が出てログイン成功となります。

```
Warning: Permanently added 'xx.xx.xxx.xx' (ED25519) to the list of known hosts.

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

https://aws.amazon.com/amazon-linux-2/
[ec2-user@ip-172-xx-x-xxx~]$ 
```


以上がAWSでEC2を起動しSSHでログインする方法となります。

この後は各自Nginxを入れるなり煮るなり焼くなりしてください。

もし質問や間違い箇所などありましたらコメントよろしくお願いします。


##  注意事項

・大体同じだとは思いますがバージョンや環境によって違う箇所があるかもしれないのでその際は環境などを確認してください。

・今回は無料版を選んで無料でできていますが設定ミスればお金発生しちゃうので気をつけてください。
SQLSERVERで中央値を取得

:::note info
備忘録として記載していきます。
:::


```sql
SELECT
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY expr) OVER(partition by partition1,partition2,,,,) as 中央値
FROM 
[テーブル]
```

`expr：パーセンタイルをソートして計算するための数値または日付/時間値を指定します。`
麻雀で学ぶTypeScript 4 ポン

前回：[麻雀で学ぶTypeScript 3 鳴き](https://qiita.com/bonetaro/items/d515e07757a7ebdd02bc)
ソースコード：https://github.com/bonetaro/mahjong-ts

今回はポン（明刻）の実装をしました。
![スクリーンショット 2023-01-16 000941.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4989/ae711460-31a6-de03-e946-7bc9d1e98fcc.png)
鳴きアクションは、アクションによってどのプレイヤーのアクションなのか決定されます（できます）。

前回の記事からだいぶ経ってしまいましたが、その分UIの改善もしました。
![スクリーンショット 2023-01-16 001033.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/4989/552c9fd3-2683-2a8f-ac37-b7afe13a26bf.png)

これまでは、捨て牌を選択する時は手牌の左端からの位置（0から13の数値）を入力していましたが、それだと手牌の中ほどにある牌を捨てる時にパッとわかりませんでした。改善したUIでは、矢印キーの上下で牌を選択できるので、UXがよくなりました。その反面、手牌を縦に表示しているため表示行数が増えてしまっていますが、メリットの方が大きいので許容することにします。手牌を横に一覧表示して、カーソル選択できるかも調べたのですが、力不足でした。

牌を選択するUIは、[Prompts](https://github.com/terkelg/prompts)を使わせていただきました。
ターミナルアプリ（コンソールアプリケーション）を開発することはままありますが、凝ったUIのものはなかったので、割とお目にかかる便利なUIがどう作られているかをよい知る機会になりました。inquirer enquirer keypressなどほかの候補も結構あり、検討して学びもありましたし、その他調べている過程で、Stream APIやRxJS、cycle.jsなど普段触れることが少ない技術を知るとっかかりになりました。芋づる式に勉強になりますね。
　
明刻の表示は、通常鳴いた相手（上家、対面、下家）に応じて牌を横向きにしますが、ターミナル上で絵文字表示しているため、横向きにできない（方法があったら教えてください）、対面から鳴いた場合　🀉(🀉)🀉　のように()で表現しています。リーチ宣言牌の表示も同様になりそうですね。

ゲームをつくるのが目的ではないため、これでいいといえばいいのですが、Web技術なら可能でしょうから早くWebアプリなどにしたくなりますね。TypeScriptの応用範囲は広いので、今後どう発展させようかとモチベーションも掻き立てられますね。
scheduledexecutorservice interface

1秒後に実行
executorService#shutdown()することで
繰り返し処理が止まる

```java
public class Outer {
    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
        s.schedule(() -> {
           System.out.println("xxx");
           s.shutdown();
        },1,TimeUnit.SECONDS);
        int count = 1;
        while(true) {
            Thread.sleep(100);
            if(s.isShutdown()) break;
           System.out.println((count++)*100);
        }
    }
}
```
```
100
200
300
400
500
600
700
800
900
xxx
```
1秒後に実行、その後定期２秒実行
```java
public class Outer {
    public static void main(String[] args) throws InterruptedException {
        ScheduledExecutorService s = Executors.newSingleThreadScheduledExecutor();
        s.scheduleAtFixedRate(() -> {
           System.out.println("xxx");
//           s.shutdown();
        },1,2,TimeUnit.SECONDS);
        int count = 1;
        while(true) {
            Thread.sleep(100);
            //if(s.isShutdown()) break;
           System.out.println((count++)*100);
           if(count>100) {
               s.shutdown();
               break;
           }
        }
    }
}
```
```
100
200
300
400
500
600
700
800
900
xxx
1000
1100
1200
1300
1400
1500
1600
1700
1800
1900
2000
2100
2200
2300
2400
2500
2600
2700
xxx
2800
2900
3000
3100
3200
3300
3400
3500
3600
3700
3800
3900
4000
4100
4200
4300
4400
4500
xxx
4600
4700
4800
4900
5000
5100
5200
5300
5400
5500
5600
5700
5800
5900
6000
6100
6200
6300
xxx
6400
6500
6600
6700
6800
6900
7000
7100
7200
7300
7400
7500
7600
7700
7800
7900
8000
8100
8200
xxx
8300
8400
8500
8600
8700
8800
8900
9000
9100
9200
9300
9400
9500
9600
9700
9800
9900
10000
```
高卒エンジニアがkintoneのプラグイン開発を超～ラクにするソフト作った

# どんなん作ってん
AgeAgePluginというソフトを作りました

https://github.com/nishikawa-r/AgeAgePlugin

内容としては
- kintoneのプラグインを一発でパッケージ化&デプロイ
- カスタマイズファイルを一発でローカルからアップロードできる
# なぜ作ったのか
公式からとても優秀なパッケージやプラグインが輩出されていたのですが、案件で実際に開発を行っていて下記の点に不満があったため

- プラグインをパッケージ化/デプロイする際にコマンドを長く打つ必要があったため(ディレクトリの指定や監視オプションの指定/URL/ID/パスワード等)

- カスタマイズファイルをkintone上で修正できる「JSEdit」という神プラグインがあるが、Gitでソースコードの管理をする以上ローカルから変更しなければならず、そのたびにアップロードするのが大変なこと

2つ目のものは何とか耐えられたのですが1つ目のコマンドが長い部分に関しては、複数の環境の情報を覚えている必要があり自分の記憶力的にもこのまま開発していくのは無理だなと思った。

# ということで
GUIでボタン1クリックでこれらの作業が行えたらいいのでは!と考えソフトの製作を敢行した。
そしたら個人的にはとても満足なものが出来た

# 1クリックでパッケージ化/デプロイ完了!
必要な環境情報を入力することにより
「実行」ボタンを押下するだけでパッケージ化/デプロイを可能とした
また、監視モードで実行するのでプラグインで使用しているファイルが変更された瞬間にパッケージ化とデプロイが実行される。
![196067079-b3ef32af-61e3-484d-b950-144ee32b39f9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235105/ccc5a07f-0e32-3847-1980-070ceb651e5a.png)

# 1クリックアップロードで快適なソースコード管理!
こちらも「実行」ボタンを押下することによりカスタマイズファイル(JS/CSS)のアップロードが行えるので快適にソースコード管理が行えるようになった。
またローカルで開発が行えるので自分愛用のエディタを使用することができ、「JSEdit」よりも快適度は増したように思える。
![196067057-fb856965-6e7d-44c0-a9eb-911e2e770f10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235105/06fd74c5-57d2-821c-1306-b15f059803cd.png)
こちらも監視モードで実行するのでカスタマイズファイルに変更があった場合瞬時にアップロードが開始される

# 複数の環境情報が保存できる!
複数の環境情報を保存することができるので、すべて覚えなくてもコンボボックスを変更するだけで複数の開発をスムーズに行える

# おまけ機能
これだけでは寂しいので自分的に欲しい機能を追加した。

- プラグイン自動アップデート機能
![196067146-7082e1d6-79eb-4ad6-929b-5c8b72bf8f97.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235105/e18ded50-d270-11b1-98b3-0010dfbfd4ff.png)
「実行」ボタン押下時に任意のバージョン数だけプラグインのバージョンアップを自動で行います。(エラーが起きた際はバージョンアップ前のバージョン数に戻されます)

- 定義ファイルをGUIで修正
![196067173-26b1ff48-d139-4b41-8a8e-42847b47ea26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235105/7320d648-bef2-a07d-fdf3-ad287128a2ff.png)
これまで面倒だったJS/CSSファイルの指定をGUI上で行えるようにしました。
(ファイル/URLの存在チェックも行います)

- アップロード/デプロイ完了時通知で知らせる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235105/fc484145-26ab-a4f7-e349-5f7172f5e9ae.png)
監視モードで実行されるので自動でデプロイ/アップロードを行いますが反映されたのがいつなのか開発中不明になるため完了時に通知が届くようにしました。

# どきゅめんと

https://github.com/nishikawa-r/AgeAgePlugin/blob/main/documents/AgeAgePlugin/AgeAgePlugin-Document.pdf

# 読んでいただきありがとうございました
多くの方に使っていただければ幸いです....

使用させていただいた公式様の優秀なパッケージたち

- [create-plugin](https://github.com/kintone/js-sdk/tree/master/packages/create-plugin)(プラグインのひな型を作成してくれる)

- [plugin-packer](https://github.com/kintone/js-sdk/tree/master/packages/plugin-packer)(プラグインをパッケージ化してくれる)
- [plugin-uploader](https://github.com/kintone/js-sdk/tree/master/packages/plugin-uploader)(プラグインをデプロイしてくれる)
- [customize-uploader](https://github.com/kintone/js-sdk/tree/master/packages/customize-uploader)(カスタマイズファイルをアップロードしてくれる)
【jQuery】ラジオボタンのvalue値を取得して開閉するアコーディオンを実装

こんにちは。E-kan株式会社の岡田です。

先日、ラジオボタンのvalue値を取得して開閉するアコーディオンを実装したので備忘録。

#### やりたいこと
- すでにあるラジオボタンに項目「ラジオボタン03」を追加したい
- 「ラジオボタン03」を選択した場合はテキスト入力欄を表示したい
- テキスト入力欄は「ラジオボタン03」選択時のみ表示するようにしたい

↓出来上がったもの。必要な部分のみを書き出すと、こんな感じです。

```html
<ul>
  <li>
    <label>
      ラジオボタン01<input type="radio" name="radioButton" value="0">
    </label>
  </li>
  <li>
    <label>
      ラジオボタン02<input type="radio" name="radioButton" value="1">
    </label>
  </li>
  <li>
    <label>
      ラジオボタン03<input type="radio" name="radioButton" value="2">
    </label>
    <div class="textBox">
      <label>
        <input type="text" placeholder="テキスト入力欄">
      </label>
    </div>
  </li>
</ul>
```

## jQuery
```javascript
$(function(){
  //テキスト入力欄を非表示にしておく
  $('.textBox').hide();

  //input の　name="radioButton"　が、change　したら
  $( 'input[name="radioButton"]:radio' ).change( function() {
    var radioval = $(this).val(); //選択されている"value"を取得する
    if(radioval == 2){ //"value"が"2"なら
      $('.textBox').show(); //テキスト入力欄を表示
    } else { //"value"が"2"以外なら
      $('.textBox').hide(); //テキスト入力欄を非表示
    }
  });
});
```

作業対象のページ内に同じような仕組みが存在するからすぐに実装出来ますよねって工数0.5hで振られた作業でしたが、実際のページを見てみたらラジオボタンじゃなくてチェックボックスだったため「え、じゃあラジオボタンは？」ってなって急ぎ作ったもの。

基本、コピー＆ペーストで人生を乗り切って行きたいので、作ったものは忘れないうちにメモしていきます。
使用頻度の高いLinuxコマンドをまとめてみた

# Linuxコマンド
 
## 基礎編
(1)ディレクトリ移動(チェンジディレクトリ)
```
$ cd
```
(2)ディレクトリ参照(リストセグメント)
```
$ ls
$ ls -l(ファイルプロパティ表示)
$ ls -a(隠しファイル表示)
```
(3)現在のディレクトリ確認(プリントワーキングディレクトリ)
```
$ pwd
```
(4)ファイルのパーミッション変更(チェンジモード)
   4:読み、2:書き、1:実行 の和
   所有者、所有グループ、その他の順番
```
$ chmod　777(例)
```
(5)コピー
```
$ cp　コピー元　コピー先
```
(6)画面をきれいにする(クリア)
```
$ clear
```
(7)フォルダ作成(メイクディレクトリ)
```
$ mkdir　フォルダ名
```
(8)フォルダ削除(リムーブディレクトリ)
```
$ rmdir　フォルダ名
```
(9)フォルダやファイル削除(リムーブ)
```
$ rm　フォルダ名またはファイル名
```
(10)ファイル作成
```
$ touch　ファイル名
```
(11)ファイル内容表示
```
$ cat　ファイル名
```
(12)ファイルの比較(ディフェレント)
```
$ diff　比較元ファイル　比較先ファイル
```
(13)コマンド履歴表示
```
$ history
```
(14)コマンドマニュアル表示
```
$ man　コマンド
```
(15)ファイル検索
```
$ find　検索先　-name　検索ファイル名
```
(16)ファイル内文字列検索
```
$ grep　検索したい文字　ファイル名
```
(17)ssh接続
```
$ ssh　ユーザー名＠IPアドレス
```
(18)カーソルを先頭に
```
$ ctl　+　a
```
(19)カーソルを最後に
```
$ ctl　+　e
```
(20)指定ファイルをデフォルトアプリで開く
```
$ xdg-open　ファイル名
```

(21)zipファイルの解凍
```
$ unzip　zipファイル
```
(22)bashrcなどの設定反映
```
$ source　設定ファイルディレクトリ
```
(23)環境変数コマンド
```
$ export　環境変数=数字や文字(環境変数設定)
$ export　-n　環境変数名(環境変数削除)
$ printenv(環境変数表示)
```
## パッケージ管理編
(24)debianパッケージコマンド
```
$ dpkg　-i　パッケージ名(インストール)
$ dpkg　-r　パッケージ名(削除)
$ dpkg　-P　パッケージ名(設定ファイル含め完全削除)
```
(25)aptパッケージコマンド
```
$ sudo　apt　install　パッケージ名(インストール)
$ sudo　apt　remove　パッケージ名(削除)
$ sudo　apt　purge　パッケージ名(設定ファイル含め完全削除)
```
(26)pipパッケージコマンド
＊python3を使用ならpip3に変更する。
```
$ sudo　pip　install　パッケージ名(インストール)
$ sudo　pip　uninstall　パッケージ名(アンインストール)
```

## エデイタ編
(27)nanoエディタで開く(編集後はctl + xで閉じる)
```
$ nano　ファイル名
```
(28)viエディタで開く(初期はコマンドモード)
＊[i]:入力モード、[Esc]:コマンドモード、[:q!]:保存せず終了、[:wq]:保存して終了
＊[/検索文字]、[n]:検索次候補へ、[N]:検索前候補へ
```
$ vi　ファイル名
```
## ネットワーク編
(29)ネットワーク状態表示
```
$ ifconfig
```
(30)ネットワーク接続確認
＊8.8.8.8はgoogle、yahoo.co.jpでも確認可能
```
$ ping　IPアドレス
```
(31)同じネットワークにつながるデバイスのMacアドレス表示
```
$ arp　-a 
```
Microsoft Teamsミーティングにゲストとして参加する手順

# Microsoft Teamsミーティングにゲストとして参加する手順

普段はGoogle MeetやZoomで会議をすることが多いのですが、まれにMicrosoft Teamsを使う場面があります。

この度、オンライン会議をTeamsのゲスト参加でやることになったんですが、サインインにかなり手間取りました。

忘れない内に手順をまとめます。


# 結論

**組織にゲストとして招待された場合**

- **普段利用しているTeamsアカウントは使えません。**
  - 普段使いしているTeamsアカウントがある場合、ブラウザからサインアウトしておいた方が安全です。
- **PCアプリ版よりもブラウザ版の方が安定しています。**
  - PCアプリ版とゲスト機能の相性が悪いのか、サインインが高確率で失敗します。
  - ブラウザ版がオススメです。



# 手順

## 招待メールが届く

まず、以下のような招待メールが届きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/d30c1c3a-f173-f2f2-96ef-fbe08ef2dd4f.png)

`ここをクリックして会議に参加してください。` をクリックします。
すると、Webページが開きます。

## ブラウザでの操作

Microsoft TeamsアプリをPCにインストールしている場合、 `Microsoft Teams を開きますか？` と聞かれますが、 `キャンセル` をクリックします。
（手順がややこしくなるため）

そして、 `このブラウザーで続ける` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/e3c44d60-9ff5-b399-7c56-ac7d736238bb.png)

以下のような画面になるので、 `コードの送信` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/3db2b09c-46c0-6600-a167-e443062ba795.png)

数分以内に、メールが届きます。

## アカウント確認コードメールを確認する

メールが届くので、 `アカウント確認コード` をメモに控えます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/a5a5c612-7bed-6b27-3a05-91852aa2baf4.png)


## ブラウザ操作

再び、ブラウザ操作に戻ります。

メモしたコードを入力し、 `サインイン` をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/1bae4b1d-27eb-443d-793c-98d043059122.png)

以下のようなページに遷移したら、サインイン成功です！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/221845/f28809ed-39f2-95d6-e04a-9e7effb2dbc2.png)

後は、ビデオやマイクの設定をするだけです！

おつかれさまでした！！

# さいごに

本記事作成にあたり、以下のページを参考にさせていただきました。ありがとうございました。

- [Microsoft Teams でのゲスト アクセス](https://learn.microsoft.com/ja-jp/microsoftteams/guest-access)
- [Teams でチームにゲストを追加する](https://support.microsoft.com/ja-jp/office/teams-%E3%81%A7%E3%83%81%E3%83%BC%E3%83%A0%E3%81%AB%E3%82%B2%E3%82%B9%E3%83%88%E3%82%92%E8%BF%BD%E5%8A%A0%E3%81%99%E3%82%8B-fccb4fa6-f864-4508-bdde-256e7384a14f)
paizaラーニング レベルアップ問題集 スタック・キューメニュー JavaScript 括弧列

括弧列 (paizaランク C 相当)

https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step4

# 解答例
stackに"("をためる。")"が来たら、正しい括弧か判定する。スタックの末尾が"("なら正しい括弧列になるので、stackから末尾の"("を取り除く。最後にstackが空なら正しい括弧列。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [N] = lines[0].split(" ").map(Number);
const S = lines[1].split("");//記号があるので文字列

let stack = [];
//Sを調べていく
for (let i = 0; i < N; i++) {
  if (S[i] === "(") {
    stack.push("(");
  } else {
    if (stack[stack.length - 1] === "(") { //正しい括弧列か判定
      stack.pop();
    }
  }
}

//スタックが空ならば正しい括弧
console.log(stack.length === 0 ? "Yes" : "No");
```
ロスをSSIMした時の畳み込みオートエンコーダの出力

# SSIM について

ここで、MVtecの論文を見るとSSIMオートエンコーダとある。
よく理解していなかったが、mseよりもいい感じにロスが出せるものらしい、通常であれば、同じ位置（同画素位置）で計算されるが、データによってばらつきがある場合、
[0000010000011]
[0000001000011]
こんな感じの時、ずれがあることが分かる。もしこれのどちらも正常だとするならば、mse等の同じ位置等で評価するものだとずれていてうまくいかない。って認識だと思われる。

SSIMでは、平均画素値、標準偏差、共分散とかから求めるので微細なずれがあっても正しく判別できるらしい

？マハラノビス距離に似ている気がする。

というのを以下のサイトで見つけた。
https://qiita.com/kotai2003/items/2d6ab5771fdc57c05507

## 実行してみる
```
def custom_loss(y_true, y_pred):
    loss= 1-tf.reduce_mean(tf.image.ssim(y_true, y_pred, 
                                          max_val = 1.0,filter_size=11,
                                        filter_sigma=1.5, k1=0.01, k2=0.03 ))
    
    return loss
```
として、
```
model.compile(optimizer='adam', loss=custom_loss)
```
とする。


:::note warn
## やりがちなミス？
自分が陥ったミスとして、いつものMSEとかbinarycrossentropyのノリで
loss="custom_loss"
としてしまった。
:::
その結果、
unknown loss function カスタムオブジェクトを指定してくれというエラーが出た。
検証時に使用する記事が多く、学習時にエラーが出たという記事が見られなかったためにこのような問題が発生した。

自作関数（def）とかしたやつはそのまま、loss=custom_lossとする。

読み込む系のは"mse"みたいにする。


## 実行結果
今回は畳み込みオートエンコーダを構築し自前の画像データで検証を行った。
ついでにMSEとの比較も行う

条件
学習枚数７００枚
テスト枚数１００枚
画像サイズ３２０＊２５６
エポック６００
早期終了20回
ロス　SSIM mse
学習率0.01

### mse
ロスが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/19aa87b5-7f3d-4cf4-c521-0fde439671cb.png)


で
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/7daa2615-6007-0c7b-890c-f54a97d85656.png)





### SSIM

ロスが
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/010c400c-d111-5a69-9735-89fd55b5aae4.png)
で
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3079535/bca53809-a1df-7de6-9771-fdbf808fee94.png)

見た感じ復元は滑らか



具体的な数値？画素数とかカウントすれば差が出てくるかもしれないので試してみる。
開発経験が全くない30代マーケティング担当者が3週間でAZ-900に895点で合格した勉強法

:::note info
<dl>
 <dt>目次 <dt>
<dd>・はじめに<dd>
<dd>・なんで受験しようと思ったか<dd>
<dd>・どうやって勉強したか<dd>
<dd>・受験結果<dd>
<dd>・受験してみてどうだったか<dd>
<dd>・最後に<dd>
<dl>
:::

# はじめに
タイトルの通り一切開発経験のない私がMicrosoft認定試験のAZ-900に合格した話になります。
今後受験を検討されている非エンジニアの方の参考になれば幸いです。

https://learn.microsoft.com/ja-jp/certifications/exams/az-900

# なんで受験しようと思ったか
会社として今後Azure開発に注力する方針となったためです。
それまで自分は別事業に従事していましたが、いくらエンジニアではないとはいえ全く知識のないままAzure関連のマーケティング活動はできないという危機感からです汗
決して会社から強要されたわけではありません笑

# どうやって勉強したか
これは3つあります。
**①参考書を読む**
**②「Microsoft Virtual Training Days」に参加する**
**③問題集を解く**

詳しく解説します。


## ①参考書を読む
まず最初に着手したのはこちらです。

![参考書.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743452/5b01fc71-591f-5894-493c-725cc9e2dd0b.png)


クラウド知識がど素人なので、どのくらい受験の難易度があるのかまずは参考書を買いました。
とりあえず1回最後まで読んだものの、第2章からすでについていけない感じでした。
所感として「基礎とは聞いていたけど結構むずい...」という印象でした。

## ②「Microsoft Virtual Training Days」に参加する
こちらに参加した目的は単純に**受験費が無料になるから**です。

2日間渡り午前中のオンライン研修を受けるのですが、自分はエンジニアではなく本業があるため後ろで流しながら別の作業を行っていました。
試験勉強という意味ではあまり活用できていないと思います。
ただ配布される資料はわかりやすくとても役に立ちました。

完全予約制＆先着順なので**予約だけ**は早めにやったほうがいいと思います。

## ③問題集を解く
**これが一番役に立ったと思います。**
選んだ問題集はこちらです。

https://www.udemy.com/course/az-900-microsoft-azure-fundamentals4176/



本を読むだけではなかなか頭に入ってことないことも問題集であれば本番を想定して効率よく覚えることができました。

ただこの問題集はちょっと癖がありまして、演習テスト1は比較簡単なのですが**徐々に難易度が上がり**演習テスト6以降は激むずです。

ですので**演習テスト1～4をひたすら100点近くなるまで繰り返し解く**のがお勧めのやり方かと思いました。
(と言いつつ自分は100点を取れたことがありません...)

**3週間の工程は下記の通りです。**

![工程表.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743452/5668e77c-ba6e-d30b-bafc-76dd43ada4cd.png)

※2週目の参考書2回目は1回目よりも理解が深まってとても参考になりました

**演習テストの結果**（新しい順）
![演習テスト.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743452/5f2baa36-d7f4-07d5-97f6-0b14c54475e6.png)


## 受験結果

![AZ900.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2743452/76cbbeb8-9f52-8814-53aa-c5825e87efd5.jpeg)



## 受験してみてどうだったか
**≪テスト会場≫**
試験会場の方は親切丁寧かつ静かでしたのでリラックスして受験することができました。
テスト会場受験の場合、受付して荷物を全部ロッカーに預けるなどの準備に時間がかかるため、試験開始時間の15分前に会場に到着することをお勧めします。

**≪苦労したこと≫**
クラウドの基礎知識がないところからのスタートでしたのでエンジニアの方よりも大変だったと思います。
また本業と並行して勉強を進めるため時間的に圧迫されます。

**≪やって良かったこと≫**
エンジニアの方々のAzure関連のお話が理解できるようになります。
クラウドに関する未知の恐怖心がなくなります。

## 最後に
今回「開発経験が全くない30代マーケティング担当者が3週間でAZ-900に895点で合格した勉強法」というお題で投稿させていただきました。

もっと効率よく勉強される方もいらっしゃるかと思いますが、資格といえば運転免許くらいしか持っていない自分にとっては丁度いい勉強期間だったと思います。

また最初はわからなくても**来週わかるようになるから今は大丈夫**と悲観しないで、なぞに割り切りながら進めていくことも重要だと思いました。

これから受験される方に本記事が参考になれば幸いです。
Javascript

```js
// returnがなくても返るケース
const hoge = () => ({a:1, b:2});

// returnが必要なケース
const fuga = () => {
  const obj = {a:1, b:2};
  return obj;
}
```
この違いは、式の返り値がどうなっているかの違いです！
iTerm上だと、

```js
> {a:1, b:2}
{a:1, b:2}
> const obj = {a:1, b:2}
undefined
```

こんな感じになると思うのですが、変数定義の返り値はundefinedなので2文以上の場合は基本returnが必要になる。


参考：https://iwb.jp/javascript-arrow-function-omits-return-tips/
paiza.ioでelixir その173

# 概要
paiza.ioでelixirやってみた。
task使ってみた。

# 参考にしたページ

https://qiita.com/pojiro/items/050da725dde4d05fed9e

# サンプルコード

```
defmodule CommandExecutor do
	use GenServer
	def start_link(state), do: GenServer.start_link(__MODULE__, state, name: __MODULE__)
	def init(state), do: {:ok, state}
	def handle_cast({:commands, commands, :async}, state) when is_list(commands) do
		do_async(commands)
		{:noreply, state}
	end
	def handle_call({:commands, commands, :async}, _from, state) when is_list(commands) do
		{:reply, do_async(commands), state}
	end
	def do_async(commands) when is_list(commands) do
		commands
		|> Enum.map(fn {m, f, a} ->
			try do
				Task.async(m, f, a)
			rescue
				error in [UndefinedFunctionError] -> 
					error
				other_error -> 
					reraise("あちゃー", System.stacktrace)
			end
		end)
		|> Enum.map(fn task -> 
			Task.await(task) 
		end)
	end
end
defmodule CommandExecutorSupervisor do
	use Supervisor
	def start_link(start_state) do
		Supervisor.start_link(__MODULE__, start_state, name: __MODULE__)
	end
	def init(_start_state) do
		children = [{CommandExecutor, nil}]
		Supervisor.init(children, strategy: :one_for_one)
	end
end
CommandExecutorSupervisor.start_link([])
c = [{IO, :puts, ["hello"]}, {IO, :puts, ["world"]}]
CommandExecutor.do_async(c)



```

# 実行結果

```
hello
world
```

# 成果物

https://paiza.io/projects/iN7JRC6OxbEnkyjZkc309Q

以上。
executorservice interface

newSingleThreadExecutor 1つのみ
newFixedThreadPool 指定した数のthreadpool
newCachedThreadPool 60秒経つと廃棄されるthreadpool

newCachedThreadPool sample
```java
public class Outer {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService e = Executors.newCachedThreadPool();
        for(int i=0;i<5;i++) {
            e.submit(() -> {
                System.out.println("a:" + Thread.currentThread().getId());
            }); 
        }
        Thread.sleep(5000);
        for(int i=0;i<5;i++) {
            e.submit(() -> {
                System.out.println("a:" + Thread.currentThread().getId());
            }); 
        }
        Thread.sleep(70000);
        for(int i=0;i<5;i++) {
            e.submit(() -> {
                System.out.println("a:" + Thread.currentThread().getId());
            }); 
        }
    }
}
```
```
a:17
a:14
a:15
a:13
a:16
a:15
a:13
a:13
a:13
a:13
a:19
a:18
a:20
a:21
a:22
```
paizaラーニング レベルアップ問題集 スタック・キューメニュー JavaScript 逆ポーランド記法

逆ポーランド記法 (paizaランク B 相当)

https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step3

# 解答例
数字はスタックにためます。記号が来たら、スタックの末尾c2と末尾の隣c1の計算をします。計算はc1-c2の形式です。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [N] = lines[0].split(" ").map(Number);
const A = lines[1].split(" ");//記号があるので文字列

let stack = [];
//Aの先頭から計算する
for (let i = 0; i < N; i++) {
  if (A[i] === "+") {
    let c2 = Number(stack.pop());
    let c1 = Number(stack.pop());
    stack.push(c1 + c2);
  } else if (A[i] === "-") {
    let c2 = Number(stack.pop());
    let c1 = Number(stack.pop());
    stack.push(c1 - c2);
  } else {
    stack.push(A[i]);
  }
}
console.log(stack[0]);
```
ネットワーク構成

# ネットワーク構成図
ネットワーク構成図には、```物理ネットワークに関するもの（物理構成図）```と、```論理ネットワークに関するもの（論理構成図）```の2つがあります。

「物理構成図」とは、```機器の物理的な配置を把握```するために用いるものです。
実際の状況を俯瞰的に示した図になります。
たとえば、物理構成図には以下の情報を含める管理者が多いです。

* 実際のフロアやラック
* スイッチ、ルーターなどの物理配線や接続ポート
* 物理サーバー

「論理構成図」とは、```通信の流れや相互接続関係を把握```するために用いるものです。
人目ではわからないものも視覚化した図になります。
たとえば、論理構成図には以下の情報を含める管理者が多いです。

* IPアドレス、サブネット
* スイッチ、ルーター
* 物理、仮想サーバー
* サーバーのホスト名
* サーバーの役割
# 出典
https://www.manageengine.jp/products/OpManager/solution_network-map.html#:~:text=%E7%89%A9%E7%90%86%E6%A7%8B%E6%88%90%E5%9B%B3,%E3%82%B5%E3%83%BC%E3%83%90%E3%83%BC%E3%81%AE%E5%BD%B9%E5%89%B2

# ハブ/スイッチの役割と機能
### ハブ/スイッチの外観
* ```LANケーブルを繋ぐポートがたくさん並んでいる```。
* ```ポートにコンピュータを繋いで、ネットワークを形成します```。

#### ハブ/ポートの説明図
https://wa3.i-3-i.info/word12504.html

### ハブとスイッチの違い
ハブとスイッチは```本来同じもの```を指す言葉。

#### 昨今では
```データ転送機能だけを持つ単機能```のものものをハブ
```各種管理機能やVLAN機能などを持つ```ものをスイッチ

### データリンク層より下を拡張するハブ/スイッチ
```物理層（レイヤー1）およびデータリンク層(レイヤー２）```のプロトコルのイーサネットにおいて```イーサネットフレームを転送```する働きを持つ。

ハブ/スイッチは```イーサネットの新設や拡張に使用するもの```です。
```ネットワークを作るとき```或いは、```ポートが足りなくなった時```に、ハブ/スイッチを用意して```必要なポートを確保```する。
これは、```イーサネットの新設や拡張に相当```します。

# ルータの役割と機能
ネットワーク層（レイヤー３）のプロトコルであるIPにおいて```IPパケットを転送```する働きをします。
```相互に独立しているイーサネットネットワークの間に入って```、両者の間でパケット（情報）を```中継```するもの。

### 気づき
イーサネットから違うイーサネットへ転送する際の中継役がルータなのか。

# 出典
https://www.sbcr.jp/product/4797386677/
Flutterを基本からまとめてみた【環境構築】

## Flutterとは

公式サイト：[Flutter](https://flutter.dev/?gclid=Cj0KCQiAiJSeBhCCARIsAHnAzT-IjUrxdNlwicantNWctv2RH4Jrgs_38tnlHQOwpExRvZOtekl6Tk0aAh-WEALw_wcB&gclsrc=aw.ds)


Googleが開発したiPhone/Androidアプリを同時に制作できるフレームワーク
安定してIOSとAndroidアプリの両方を開発できる技術

## Flutterのメリット

①開発期間を大幅に短縮できる

互換性の不具合がほとんどない

②開発期間を大幅に削減できる

１つ作成したらいろんなOSに対応できる
１回プログラムを書けば、どのプラットフォームでも動く

③ホットリロードでさくさく開発ができる

即座に変更を確認することができる ＝ この技術をホットリロードと呼ぶ

※ ビルドとは ⇨ プログラムを実行可能な状態にすること

④使いやすいUIを設計しやすい

マテリアルデザインをベースとしたUIを作成する

従来よりも簡単に直感的に操作が出来るアプリを作ることが出来る


※マテリアルデザイン　⇨  Googleが2014年に提唱したデザインシステムのこと


## Flutterのデメリット

①扱える優秀な技術者が少ない

②開発言語が『Dart』という言語

③機能によってはOSごとに開発が必要

④FlutterWebは、まだまだ使えない

⑤IOSのアップデートに即座に対応ができない可能性がある

## 環境構築

#### 1.Flutterのインストール

①インストールしたものを入れるファイルを作成する
```
mkdir <ファイル名>
```
②そのファイルの中にFlutterをインストールする

下記の公式サイトに手順通りに行う


公式サイト：[macOS install](https://docs.flutter.dev/get-started/install/macos)

#### 2. パスを通す

①『echo $SHELL』とターミナルに入力　(zsh か bash の確認)

② zshなら『vim .zxhrc』bashなら『vim.bash_profile』

③『i』を押して、INSERTモードにする //戻す場合は、『esc』を押す

④ export PATH="$PATH:[インストールしたもの]/bin"

⑤『esc』を押して、INSERTモード終了

⑥ ターミナルの一番下で、『:wq』にて上書き保存

⑦ 『which flutter』でパスが入っているか確認出来る


## 参考サイト
　[【アプリ開発歴10年】Flutterとは？Flutterの特徴・メリット・デメリットを徹底解説](https://pentagon.tokyo/app/1948/)
[WebエンジニアのためのFlutter入門#1 〜Flutterの特徴・環境構築を分かりやすく解説〜](https://www.youtube.com/watch?v=vhjErSLXGw8)
[【Flutter】超わかりやすい環境構築【Mac】](https://www.youtube.com/watch?v=RtSOU0oY4DY)
正規表現(マッチ、抽出)

自分メモ。
```
final String  regex = "^(ねこ|いぬ)は(唐揚げ|魚)好き$";
final String text = "ねこは唐揚げが好き";
if (text.matches(regex)) {
    final Pattern p = Pattern.compile(regex);
    if (m.find()) {
        m.group(); // ねこは唐揚げが好き
        m.group(0); // ねこは唐揚げが好き
        m.group(1); // ねこ
        m.group(2); // 唐揚げ 
    }
}
```

or条件で空文字判定をする場合は(|唐揚げ|魚)とすればよい。
設計の目的

1. 要件定義の内容をシステムでどのように実現するかを検討
1. 要件定義で明確になっていない外部仕様を検討
1. 開発の関係者間で情報を共有する
1. システムの品質を高める
1. メンテナンスのために設計情報を残す
paizaラーニング レベルアップ問題集 スタック・キューメニュー JavaScript 最大の区間和

最大の区間和 (paizaランク B 相当)

https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step2

# 解答例
タイムオーバーにならないように、区間をキューとして考えます。まず、先頭の区間和を求めます。次の区間和を計算するときに、先頭の区間から、先頭の要素をキューから出して、X+1目の要素をキューに入れてから、区間和を求めます。すなわち、`次の区間和＝前の区間和ー前の区間の先頭の要素＋次の区間の末尾の要素`です。すると、計算の手間が、通常ならばX回足すところ、２回で済みます。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [N, X] = lines[0].split(" ").map(Number);
const A = lines[1].split(" ").map(Number);

//初期値は左端からX個の区間
let left_num = A[0];//左端
//A に含まれる連続した X 個の要素の和
let sum_a = A.slice(0, X).reduce((a, b) => a + b);
let max_sum = sum_a;//最大値

//Aの中の区間X個を1要素ずつずらして計算する
for (let i = 1; i <= N - X; i++) {
  sum_a -= A[i - 1];//前区間の先頭要素
  sum_a += A[i + X - 1];//次区間の末尾要素
  //最大値更新
  if (sum_a > max_sum) {
    left_num = A[i];//左端
    max_sum = sum_a;//合計    
  }
}
console.log(max_sum, left_num);
```
【BizRobo!】曜日から日付変換出来るの知ってた？

## はじめに
みなさんはじめまして。
今回はBizRobo!で曜日から日付を取得する方法をご紹介したいと思います。

**※今回は日曜日の日付を取得したいと思います。**

## 設定方法
**※名前はご自身で決めて頂いて結構ですので、変数を作成してください。**
名前：なんでも結構です。
変数の型：Short Text
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/4f79db28-c981-b81d-c33f-9ec287645711.png)



①「ステップの挿入」→「アクションステップ」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/32521e22-c67a-63b5-0a27-2c21bf4d2e5a.png)

②「変数の割当/変換」→「変数の割当」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/25ec33dd-4177-f9b6-53b0-833bb1b6eb63.png)

③先に変数に、１番初めに作成した変数を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/8acc25f6-dfdd-0940-bcf5-4f3b6fe84630.png)

**＊ここから曜日で日付を取得するやり方になります＊**

④値の部分を「コンバータ」にします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/51f54205-b067-7367-fc6a-4a5260f10318.png)

⑤デフォルトで設定されている「変数を取得」を消します。
　※下にある「ー」で消えます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/89224a9d-39c3-d1a7-d581-2b446d9f54c2.png)

⑥「＋」を押して、「テキストフォーマット」→「テキストの追加」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/301aef69-d57c-82e2-5f8a-f8d8f4a16f5e.png)

⑦テキストに**取得したい曜日**を入力し、OKをクリックします。
（今回は日曜日の日付を取得したいので「日」と入力します。）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/1e4b85c1-b67f-9f7e-1c42-64e2dc0a1cce.png)

⑧「＋」を押して、「日付処理」→「日付抽出」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/b01d929b-1917-d38a-2428-b6bfe05ec37d.png)

⑨フォーマットの「＋」をクリックし、「フォーマットパターン」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/ac9320cc-eae4-6ff8-a2d2-20d6e0e6a992.png)

⑩パターンに「E」と入力してください。
　「E」は曜日を変換する文字です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/ebf0f5d9-bb8c-247f-c044-dac8bed57ebb.png)

⑪そしてロケールを日本語に設定すると、、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/fd050d71-95f5-ad64-606e-7a61e6aef43a.png)

⑫このように曜日から日付が取得できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1902544/23c118c4-06ba-03ea-b29c-34853388d933.png)

⑬あとは、使いやすいように日付の形式を変えて使用してみてください。
（日付の形式変換は省きます）

## さいごに
ぜひ使用してみる機会があれば使用してみてください。
【データ抽出/BigQuery】CROSS JOINを使って不足しているデータを補足した

# 今回の課題
下記の2種類のテーブルを使って、
titleテーブルの`title_name`に対応する`series_name`を抽出できるようにしたい。
（業務で行った処理を分かりやすいテーブルに書き換えて記載していく。）

**【titleテーブル】**
|title_id|title_name|
|:-:|:-:|
|1|トイ・ストーリー|
|2|トイ・ストーリー2|
|3|トイ・ストーリー3|
|4|バイオハザード|
|5|バイオハザード2|
|6|バイオハザード3|
|7|バイオハザード4|
|8|バイオハザード5|
|9|バイオハザード6|



**【seriesテーブル】**
|series_id|title_name|series_name|
|:-:|:-:|:-:|
|1|トイ・ストーリー|トイ・ストーリー|
|1|トイ・ストーリー2|トイ・ストーリー|
|1|トイ・ストーリー3|トイ・ストーリー|
|2|バイオハザード|バイオハザード|
|2|バイオハザード2|バイオハザード|

**【欲しいデータ】**
|title_name|series_name|
|:-:|:-:|
|トイ・ストーリー|トイ・ストーリー|
|トイ・ストーリー2|トイ・ストーリー|
|トイ・ストーリー3|トイ・ストーリー|
|バイオハザード|バイオハザード|
|バイオハザード2|バイオハザード|
|バイオハザード3|バイオハザード|
|バイオハザード4|バイオハザード|
|バイオハザード5|バイオハザード|
|バイオハザード6|バイオハザード|

# 失敗例
最初２つのテーブルを左外部結合や完全外部結合で結合していた。
```sql
select
    t.title_name
    , s.series_name
from
    `title` as t
    left join `series` as s
        on t.title_name = s.title_name
```
**出力結果**
|title_name|series_name|
|:-:|:-:|
|トイ・ストーリー|トイ・ストーリー|
|トイ・ストーリー2|トイ・ストーリー|
|トイ・ストーリー3|トイ・ストーリー|
|バイオハザード|バイオハザード|
|バイオハザード2|バイオハザード|
|バイオハザード3|null|
|バイオハザード4|null|
|バイオハザード5|null|
|バイオハザード6|null|

このように、完全外部結合や左外部結合を行うと`null`が複数発生してしまうので使えない。

# 成功例
```sql
/* seriesをユニークな値に絞り込んでおく */
with series_mst as (
    select
        distinct series_name
    from
        `series`
)
/* series_mstとtitleテーブルをcross joinする＆余計な組み合わせをWHERE句で除去する */
select
    t.title_name
    , s.series_name
from
    `title` as t
    cross join series_mst as s
where
    t.title_name like "%"||s.series_name||"%" -- title_nameの中にseries_nameの文字列が入っているものの組み合わせに絞り込む（cross joinによってtitle×seriesのすべての組み合わせが生成されているから）
```
**出力結果**
|title_name|series_name|
|:-:|:-:|
|トイ・ストーリー|トイ・ストーリー|
|トイ・ストーリー2|トイ・ストーリー|
|トイ・ストーリー3|トイ・ストーリー|
|バイオハザード|バイオハザード|
|バイオハザード2|バイオハザード|
|バイオハザード3|バイオハザード|
|バイオハザード4|バイオハザード|
|バイオハザード5|バイオハザード|
|バイオハザード6|バイオハザード|

cross joinを使えば、外部結合の時のNULLを取り除いてデータを抽出できた。
railsのコンポーネントを構成する

疑問に思っているところは、
* デフォルトのロケールを変更するのに```config/application.rb```をなぜ使うのか？

# config/application.rbとは
<h5>3 Railsコンポーネントを構成する

一般に、Railsの設定作業には、```Rails自身の設定```と、```Railsのコンポーネントの設定```があります。```config/application.rb```および
```環境固有の設定ファイル```（config/environments/production.rbなど）に設定を記入すると、
Railsの```すべてのコンポーネントにそれらの設定が反映```されます。

たとえば、config/application.rbファイルに以下の設定を追加できます。
```rb
config.time_zone = 'Central Time (US & Canada)'
```
```上はRails自身のための設定```ですが、個別のRailsコンポーネントに設定を反映するときにも、
以下のようにconfig/application.rb内の同じconfigオブジェクトを利用できます。
```rb
config.active_record.schema_format = :ruby
```
この設定は、```Active Record固有の設定```に使われます。

### 出典
https://railsguides.jp/configuring.html#rails%E5%85%A8%E8%88%AC%E3%81%AE%E8%A8%AD%E5%AE%9A:~:text=3%20Rails%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88,%E8%BF%BD%E5%8A%A0%E3%81%A7%E3%81%8D%E3%81%BE%E3%81%99%E3%80%82

### ```config.time_zone```
アプリケーションのデフォルトタイムゾーンを設定し、Active Recordで認識できるようにします。
#### 出典
https://railsguides.jp/configuring.html#rails%E5%85%A8%E8%88%AC%E3%81%AE%E8%A8%AD%E5%AE%9A:~:text=3.1.37%20config.time_zone,%E3%82%88%E3%81%86%E3%81%AB%E3%81%97%E3%81%BE%E3%81%99%E3%80%82

### ```config.i18n.default_locale```
アプリケーションのi18nで使われるデフォルトのロケールを設定します。デフォルト値は:enです。
#### 出典
https://railsguides.jp/configuring.html#rails%E5%85%A8%E8%88%AC%E3%81%AE%E8%A8%AD%E5%AE%9A:~:text=3.5.2%20config.i18n,%3Aen%E3%81%A7%E3%81%99%E3%80%82

### 気づき
railsのアプリ全体の設定を各ファイルなのか。
```rb
    config.time_zone = "Tokyo"
    config.i18n.default_locale = :ja
```
タイムゾーンとロケールは全体に影響を及ぼすからここのファイルに書くのか。
しかし
いろいろな言語に対応していくと日本語以外が良いだろうか？（それはずっと先に考えることだろう）

### コンポーネントとは？
* コンポーネントとは、ザックリいうと```「ファイルやプログラムの構成要素」```です。

    基本的に単体で何かするようなものではなく、```何かと組み合わせて使用```します。
    後述するモジュールと同じ意味ですが、コンポーネントは「モジュールより広義な意味での部品」です。

    コンポーネントには、他のコンポーネントがないと機能しないものもあり用途が少し限定的です。
#### 出典
https://exture-ri.com/2019/10/23/%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%80%81%E3%83%A2%E3%82%B8%E3%83%A5%E3%83%BC%E3%83%AB%E3%80%81%E3%83%A9%E3%82%A4%E3%83%96%E3%83%A9%E3%83%AA%E3%81%A3%E3%81%A6%E4%BD%95/#:~:text=%E3%82%B3%E3%83%B3%E3%83%9D%E3%83%BC%E3%83%8D%E3%83%B3%E3%83%88%E3%81%A8%E3%81%AF,%E9%99%90%E5%AE%9A%E7%9A%84%E3%81%A7%E3%81%99%E3%80%82

* IT用語としては何らかの機能を持った```プログラム部品```のことをいう。
#### 出典
https://www.r-agent.com/it_engineer/glossary/glossaryList/glo_component.html#:~:text=IT%E7%94%A8%E8%AA%9E%E3%81%A8%E3%81%97%E3%81%A6%E3%81%AF%E4%BD%95%E3%82%89%E3%81%8B%E3%81%AE%E6%A9%9F%E8%83%BD%E3%82%92%E6%8C%81%E3%81%A3%E3%81%9F%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0%E9%83%A8%E5%93%81%E3%81%AE%E3%81%93%E3%81%A8%E3%82%92%E3%81%84%E3%81%86%E3%80%82

### 気づき
いろいろ見たが何らかの部品らしい。

# 関連記事
https://qiita.com/masatom86650860/items/edb95c9271d88e67016a#%E3%83%87%E3%83%95%E3%82%A9%E3%83%AB%E3%83%88%E3%81%AE%E3%83%AD%E3%82%B1%E3%83%BC%E3%83%AB%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%95%E3%81%9B%E3%82%8B
paizaラーニング レベルアップ問題集 スタック・キューメニュー JavaScript 2 つのキュー

2 つのキュー (paizaランク C 相当)

https://paiza.jp/works/mondai/stack_queue/stack_queue__practice_step1

# 解答例
query,K,Xを文字列のまま処理していることに注意。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [Q] = lines[0].split(" ").map(Number);

//2 つのキューを用意
let [queue1, queue2] = [[], []];

//クエリを順に処理
for (let i = 1; i <= Q; i++) {
  const [query, K, X] = lines[i].split(" ");//文字列のまま
  if (query === "1") {//文字列
    if (K === "1") {//文字列
      queue1.push(X);
    } else {
      queue2.push(X);
    }
  } else if (query === "2") {//文字列
    if (K === "1") {//文字列
      console.log(queue1.shift());//削除と返却を同時に
    } else {
      console.log(queue2.shift());
    }
  } else {
    console.log(queue1.length, queue2.length);
  }
 console.log(queue1,queue2);
}
```
WingetでNode.jsインストール

## Windows11のノートPCにNode.jsをインストールした時のメモ

超簡単な自分用の備忘録メモです。

## 環境

OS:Windows11 Pro

## パッケージマネージャ何使うか

Windowsのパッケージマネージャーは、scoopとかchocolateyとか有名だが、本家が一番良いのでは？ということで、後発ですが、wingetを利用。

* chocolatey うーん。以下２つに対してメリット感じられず。（個人的に触ったことがあったscoopかwin標準のwingetか）
* scoop 以前はこっちをつかっていたこともあるが、Powershellで実行していた
* winget コマンドプロンプトで実行できた

## 目的はnode.jsのインストールとnpmの利用

### 以下wingetコマンド実行してあるかなチェック

~~~
winget search nodejs
~~~

でこんな結果が返ってくる。（2023/01/16現在）
~~~
名前                  ID                        バージョン   一致            ソース
-----------------------------------------------------------------------------------
Node.js               OpenJS.NodeJS             19.4.0       Moniker: nodejs winget
Volta                 Volta.Volta               1.1.0        Tag: nodejs     winget
QQ小程序开发者工具    Tencent.qq-devtool        0.70.2209190 Tag: nodejs     winget
pnpm                  pnpm.pnpm                 7.24.2       Tag: nodejs     winget
Node.js Nightly       OpenJS.NodeJS.Nightly     20.0.0       Tag: nodejs     winget
Node.js LTS           OpenJS.NodeJS.LTS         18.13.0      Tag: nodejs     winget
RunJS                 lukehaas.RunJS            2.7.4        Tag: nodejs     winget
Laragon               LeNgocKhoa.Laragon        5.0.0.210523 Tag: nodejs     winget
Open Video Downloader jely2002.youtube-dl-gui   2.4.0        Tag: nodejs     winget
CodeLite              CodeLite.CodeLite         15.0.0       Tag: nodejs     winget
NVM for Windows       CoreyButler.NVMforWindows 1.1.10       Tag: nodejs     winget
~~~

### winget installを実行してインストール

LTS(Long Term Support)が良いと思うので、そちらをインストールする。

~~~
winget install "Node.js LTS" -v 18.13.0
~~~
実行すると以下のように処理が実行される。
~~~
見つかりました Node.js LTS [OpenJS.NodeJS.LTS] バージョン 18.13.0
このアプリケーションは所有者からライセンス供与されます。
Microsoft はサードパーティのパッケージに対して責任を負わず、ライセンスも付与しません。
Downloading https://nodejs.org/dist/v18.13.0/node-v18.13.0-x64.msi
  ██████████████████████████████  29.5 MB / 29.5 MB
インストーラーハッシュが正常に検証されました
パッケージのインストールを開始しています...
インストールが完了しました
~~~

### 確認時の注意点

さてこれでインストールできたかなと、同一プロンプト上で、以下のようにコマンド実行してみても、、

~~~
npm -v
~~~

~~~
'npm' は、内部コマンドまたは外部コマンド、
操作可能なプログラムまたはバッチ ファイルとして認識されていません。
~~~

と出て、あれ？と思いますが、コンソール開いた時のパスにnpm通っていないだけなので、新しくプロンプトを開いてあげて実行すればOK。

~~~
8.19.3
~~~

とバージョンが表示されればOK。

以上超簡単、備忘録でした。
PHPにおける名前空間について改めて学習する

## PHPにおける名前空間について改めて学習する
PHPやLaravelを扱っているとほぼ必ず目にするのが名前空間。
なんとなくだった理解をもう少し深くするために今回まとめていきます。

### 名前空間とは
PHPにおける名前空間とは一言でいうと、`プログラム内で同じクラス名や関数名を使用しても競合しないように区分けをすること`。

プログラムにおいて、同じ名前のクラスや関数を定義するとエラーが起こります。
競合しないためには、名前が被らないようにする必要があり、被らない長い名前にする必要がありますがそれだとソースコードの可読性が低くなってしまいます。
そこで名前空間を用いてあげます。

名前空間を用いることで、それぞれが独立した空間となり、
自由に名前をつけてあげることが可能となります。

別の空間に同じ名前のクラスや関数があったとしても競合することがありません。


### 名前空間の作り方
名前空間では、ソースコードの一番上部分に`namespace`というキーワードを使って指定してあげることができます。
このように記載をすると、TestGroupという名前空間を指定することになります。
```test.php
<? php 

namespace TestGroup
```

名前空間を指定してあげたあとに下記のように関数を書いてあげることがほとんどですが
この場合testという関数はTestGroupに帰属することとなります。

どこにでもありそうなtestという関数ですが、
TestGroupという名前空間内に属し定義しているため他と競合することがなく使うことができます。

```A.php
<? php 
namespace TestGroup

function test() {
    echo "Hello World";
}
```


### 名前空間の使い方
別ファイルなどから先程のファイル(A.php)を呼び出す場合以下のように記述します。
```B.php
<? php 
require_once 'A.php';

TestGroup\test();
```

- `require_once`を使用してファイルを指定し読み込むことができる
- `名前空間名\関数名;`と指定することで、その名前空間の中にある関数を呼び出すことができます。

### サブ名前空間
名前空間には`サブ名前空間`というものもあります。

サブ名前空間は先程までの名前空間とは違い、階層を区切って細かく指定することができます。

```C.php
<? php 
namespace TestGroup\Kokugo\bunpou;
```

実際の使い方は先程までの名前空間と変わりありません。

``` D.php
<? php 
require_once 'C.php';

TestGroup\Kokugo\bunpou;
```
### useについて
サブ名前空間を使って名前空間の指定が長くなりすぎてしまうと、毎回の記述が面倒になってしまいます。
そんなときに使えるのが`use`キーワードです。

この`use`キーワードを使ってあげることでエイリアスを作成することができ、短い文で記述することが可能となります。

``` D.php
<? php 
require_once 'C.php';

use TestGroup\Kokugo\bunpou as bunpou;

bunpou\test();
```
エイリアスを使用することでつまり
`TestGroup\Kokugo\bunpou\test()` と `bunpou\test()` は同じ意味となります。



### Laravelでの名前空間について
Laravelではコントローラを作成すると自動で名前空間が作成されます。
``` TestController.php
<?php

namespace App\Http\Controllers;
```

つまり、APP配下にあるHttpディレクトリ内にあるControllersディレクトリにあるTestController.phpだよということになります。
ただなんとなくnamespaceという記述があるなーという認識ではなく、これがどういう意味のものなのか理解することが重要ですね。

以上
paizaラーニング レベルアップ問題集 スタック・キューメニュー JavaScript キュー実装編

# STEP: 1 キュー実装編 step 1
キューから要素を削除するプログラムを実装します。

https://paiza.jp/works/mondai/stack_queue/stack_queue__stack_step1

## 解答例
キューは先出しですので、shift()と使います。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [Q] = lines[0].split(" ").map(Number);

//空の配列A
let A = [];

//クエリを順に処理
for (let i = 1; i <= Q; i++) {
  const [query, X] = lines[i].split(" ");
  if (query === "1") {
    A.push(X);
  } else {
    A.shift();
  }
  //各クエリの処理が終わったあと、配列 A の各要素の値を半角スペース区切りで出力
  console.log(A.join(" "));
}
```

# FINAL問題 キュー実装編 step 2
キューを完成させます。

https://paiza.jp/works/mondai/stack_queue/stack_queue__queue_step2

## 解答例
shiftは先頭の要素を返します。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [Q] = lines[0].split(" ").map(Number);

//空の配列A
let A = [];

//クエリを順に処理
for (let i = 1; i <= Q; i++) {
  const [query, X] = lines[i].split(" ");
  if (query === "1") {
    A.push(X);
  } else {
    console.log(A.shift());//先頭を削除して出力
  }
  //各クエリの処理が終わったあと、配列 A の各要素の値を半角スペース区切りで出力
  console.log(A.join(" "));
}
```
paizaラーニング レベルアップ問題集 スタック・キューメニュー JavaScript スタック実装編 

# スタック実装編 step 1 (paizaランク C 相当)
スタックから要素を削除するプログラムを実装します。

https://paiza.jp/works/mondai/stack_queue/stack_queue__stack_step1

## 解答例
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [Q] = lines[0].split(" ").map(Number);

//空の配列A
let A = [];

//クエリを順に処理
for (let i = 1; i <= Q; i++) {
  const [query, X] = lines[i].split(" ");
  if (query === "1") {
    A.push(X);
  } else {
    A.pop();
  }
  //各クエリの処理が終わったあと、配列 A の各要素の値を半角スペース区切りで出力
  console.log(A.join(" "));
}
```
# FINAL問題 スタック実装編 step 2(paizaランク C 相当)
スタックを完成させます。

https://paiza.jp/works/mondai/stack_queue/stack_queue__stack_step2


## 解答例
pop()は配列の末尾にある要素を返します。
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [Q] = lines[0].split(" ").map(Number);

//空の配列A
let A = [];

//クエリを順に処理
for (let i = 1; i <= Q; i++) {
  const [query, X] = lines[i].split(" ");
  if (query === "1") {
    A.push(X);
  } else {
    console.log(A.pop());//末尾を削除して出力
  }
  //各クエリの処理が終わったあと、配列 A の各要素の値を半角スペース区切りで出力
  console.log(A.join(" "));
}
```
GitHub ActionsでBaseline Profilesを生成する

[android-emulator-runner](https://github.com/ReactiveCircus/android-emulator-runner) のような Android Emulator の Actions を使うパターンもあるのですが、今回は Gradle Managed Device を使っての Baseline Profiles を生成する Actions を作ってみます。

## 実装

```build.gradle
dependencies {
    implementation 'androidx.benchmark:benchmark-macro-junit4:1.1.1'
    ...
}
```


~~benchmark-macro-junit4 は 1.2.0 の alpha 版を使用します。~~ 1.1.0 から入っていました。  
これは benchmark モジュールのテスト実行時に Baseline Profiles の生成以外のテストが走ってしまうのを防ぐ機能が ~~1.2.0~~ 1.1.0-rc02 以降に入っているためです。

```benchmark/build.gradle
android {
    ...
    testOptions {
        managedDevices {
            devices {
                pixel2Api31(com.android.build.api.dsl.ManagedVirtualDevice) {
                    device = "Pixel 2"
                    apiLevel = 31
                    systemImageSource = "aosp"
                }
            }
        }
    }
}
```

benchmark モジュールに Gradle Managed Device の設定を追加します。


```yml
name: Generate Baseline Profiles

on: workflow_dispatch

jobs:
  generate-baseline-profiles:
    runs-on: macos-latest
    steps:
      - uses: actions/checkout@v3

      - name: Setup Android SDK
        uses: android-actions/setup-android@v2

      - name: set up JDK
        uses: actions/setup-java@v3
        with:
          java-version: 11
          distribution: zulu
          cache: gradle

      - name: Generate baseline profile
        run: |
          ./gradlew :benchmark:cleanManagedDevices --unused-only
          ./gradlew :benchmark:pixel2Api31BenchmarkAndroidTest -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile
          mv benchmark/build/outputs/managed_device_android_test_additional_output/pixel2Api31/BaselineProfileGenerator_generate-baseline-prof.txt app/src/main/baseline-prof.txt

      - name: Create pull request
        uses: peter-evans/create-pull-request@v4
        with:
          commit-message: Updated baseline profiles
          title: Updated baseline profiles
          body: ""
          branch: update-baseline-profiles
```

## 解説

```shell
./gradlew :benchmark:pixel2Api31BenchmarkAndroidTest -Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect" -Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile
```
で Baseline Profiles を生成するテストを Gradle Managed Device で動かします。
`Pandroid.testoptions.manageddevices.emulator.gpu="swiftshader_indirect"` の設定は、GitHub Actions などのハードウェアレンダリングをサポートしていない環境で Gradle Managed Device を使うために必要な設定です。
`Pandroid.testInstrumentationRunnerArguments.androidx.benchmark.enabledRules=BaselineProfile` の設定は、上記で話に出した`benchmark-macro-junit4` の 1.1.0 以降に追加された benchmark モジュールのテスト実行時に Baseline Profiles の生成だけをフィルタリングして動かすための設定です。


<hr />

上記の例では Baseline Profiles を生成して PR にする Actions になりますが、Baseline Profiles のファイルサイズは大きくほぼ毎回差分が発生するものになります。
そのためアプリのリリースのワークフローにのみ Baseline Profiles の生成を組み込んで git 上で管理させない手段も取ることも考えるといいでしょう。



## リンク

- https://developer.android.com/studio/test/gradle-managed-devices
- https://developer.android.com/topic/performance/baselineprofiles/overview
paizaラーニング レベルアップ問題集 スタック・キューメニュー  JavaScript スタック・キュー実装編( 共通問題 )


# STEP: 1 スタック・キュー実装編( 共通問題 ) step 1
スタック・キューの実装において共通で使用する、値を配列へ入力する部分を作成します。

https://paiza.jp/works/mondai/stack_queue/stack_queue__common_step1

## 解答例
問題文より、次の問題のために、与えられた数値は配列Aに入れ、配列の中に入っている要素数を変数Nで管理しておきます。

```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [N] = lines[0].split(" ").map(Number);

//空の配列A
let A = [];
//与えられた数値は配列に入れる
for (let i = 1; i <= Q; i++) {
  const A_i = lines[i];
  A.push(A_i);
}
//1 行目に N を、 2 行目以降に A の各要素を改行区切りで出力
console.log(N);
console.log(A.join("\n"));
```

# FINAL問題 スタック・キュー実装編( 共通問題 ) step 2
スタック・キューの実装において共通で使用する、クエリの入力部分を作成します。

## 解答例
```javascript
const fs = require("fs");
const input = fs.readFileSync("/dev/stdin", "utf-8").trim();
const lines = input.split("\n");

const [Q] = lines[0].split(" ").map(Number);

//空の配列A
let A = [];

//クエリを順に処理
for (let i = 1; i <= Q; i++) {
  const [query, X] = lines[i].split(" ");
  if (query === "1") {
    A.push(X);
  }
}

//配列 A の要素数 N と値をそれぞれ改行区切りで出力
const N = A.length;
console.log(N);
console.log(A.join("\n"));
```
エラーメッセージを日本語化する

# 日本語化の方法
* ```rails-i18n```gemを使って日本語にするらしい。
### 出典
https://zenn.dev/machamp/articles/rails-validation-message#2.rails-i18n-%E3%82%92%E4%BD%BF%E3%81%A3%E3%81%A6%E6%97%A5%E6%9C%AC%E8%AA%9E%E5%8C%96%E3%81%99%E3%82%8B

https://qiita.com/shimadama/items/7e5c3d75c9a9f51abdd5

* p313 Railsでよく利用する辞書データは```rails-i18n```というgemで利用できます。
### 出典
https://gihyo.jp/book/2020/978-4-297-11462-6

### 気づき
このgemをインストールをしないと翻訳できないのだろうか？

# I18nの属性
```rb
rb(main):049:0> I18n.load_path
# カスタム訳文ファイルの場所を示す
=>
["/*****************/active_support/locale/en.yml",
 "/*****************/active_support/locale/en.rb",
 "/*****************/active_model/locale/en.yml",
 "/*****************/active_record/locale/en.yml",
 "/*****************/action_view/locale/en.yml",
 "*****************/config/locales/en.yml",
 "*****************/web_console/locales/en.yml"]
irb(main):050:0> I18n.default_locale
# デフォルトロケールの取得と設定
=> :en
irb(main):051:0> I18n.available_locales
# アプリケーションでの利用が許されるロケールの許可リスト
=> [:en]
irb(main):055:0> I18n.locale
# 現在のロケールの取得と設定
=> :en
```
### 出典
https://railsguides.jp/i18n.html#:~:text=load_path%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%A0%E8%A8%B3%E6%96%87,%E3%82%A8%E3%83%B3%E3%83%89%E3%82%92%E4%BD%BF%E3%81%86


# エラー文を日本に設定
### デフォルトのロケールを変更させる
```config/application.rb
module app
  class Application < Rails::Application
    config.load_defaults 7.0
    config.time_zone = "Tokyo"
    config.i18n.default_locale = :ja
    # 上2行を追加しました。
    config.generators.system_tests = nil
  end
end
```
p313 ```config/application.rb```で```config.i18n.default_locale = :ja```を追加することでロケールを設定できる。

### 出典
https://gihyo.jp/book/2020/978-4-297-11462-6

https://railsguides.jp/i18n.html#:~:text=config/application.rb%E3%81%A7%E3%81%AF,default_locale%20%3D%20%3Ade

#### さっきの属性を使っている。
```rb
irb(main):050:0> I18n.default_locale
# デフォルトロケールの取得と設定
=> :en
```

### 日本語の辞書ファイルを書く
https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/ja.yml

これをコピペした。

### 気づき
```rails s```を一回閉じたら成功した。
しかしモデルの属性名が英語になっている。

### ja.ymlにモデルの属性名をつけて翻訳させる
```ja.yml
ja:
  activerecord:
    models:
      user: "ユーザー"
    attributes:
      user:
        name: "名前"
        email: "eメール"
        password: "パスワード"
.
.
.
```
### 出典
https://railsguides.jp/i18n.html#active-record%E3%83%A2%E3%83%87%E3%83%AB%E3%81%A7%E7%BF%BB%E8%A8%B3%E3%82%92%E8%A1%8C%E3%81%AA%E3%81%86

### 感想
頭ごなしに```rails-i18n```のgemをインストールすればいいと思っていたが、
自分なりにエラー文を翻訳できてよかった。

次はこの翻訳で使ったソースコードの中身を勉強する。
初投稿＆自己紹介

はじめまして！そしてこんにちは！！

この度、Qiitaで投稿を始めることにしました！
現在高校二年でAWS使いの端くれとして開発・運用業務などを行っています。
まだまだ駆け出しで日々勉強中ですが、その中で学んだことのアウトプットや製作物や運用の記録を残していこうと思っています

どうぞよろしくお願いします！！！