OmniAICreator/Qiita-1.07M huggingface dataset:
chrome拡張「MagicForm App」で遊んでみた（※課金が怖くて最後まで試してない

# はじめに
twitterのおすすめで紹介されたAIでGoogleフォームの質問を生成できるChrome拡張
「MagicForm App」が気になったので遊んでみる
※OpenAIアカウント必要

https://twitter.com/Yamkaz/status/1628538351132512257

URLはコチラ

https://www.gptforforms.app/

# インストール
https://www.gptforforms.app/

が説明URL。これの手順に沿って遊ぶ。

インストールページはこちら

https://workspace.google.com/marketplace/app/magicform_app/3882244700

インストール　クリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/2929461c-d554-a26d-df9d-afd0482b4fc8.png)

インストール完了
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/f04459eb-0af6-bc1a-eb5f-382b54c6f843.png)

# OpenAI アカウントを作成して API キーを取得する
ぐわ！有料のOpenAI APIキー必要なのか！？
うーん、、、ちょうどついこないだアカウントは手に入ったからそれを使いまわそう。
OpenAIのAPIキー取得のやり方は　https://www.gptforforms.app/　のページが詳しいのでそっちにゆずる。

# API キーを MagicForm にセットアップする
Formを開こう。google TOP画面右上の…からFormがみつかる
ちなみに　[forms.new](https://docs.google.com/forms/u/0/) でもいける

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/a772ee5b-ae80-d427-8191-69ac68033b6e.png)

アンケートを新規作成する、、、と。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/88c82a8b-581b-3357-0d40-8597a9e68136.png)

アドオンアイコンに”MagicForm App”ができてる！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/afd63016-93f3-bdbb-121a-b9f8d14c7300.png)

Launch クリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/03658df6-92db-48f5-416b-2da6eea55c06.png)

赤矢印部にOpenAIのAPIキーを入力して　Save クリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/8271c9a1-e66a-47ce-2c0d-d9afe1cff1ab.png)
Saveの場所はコチラ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/6a0d2df1-f824-46b7-7da5-c1fd5e119113.png)

# 試しにクイズをつくる
この"Enter question content here"の中に
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/b2d6f733-2a38-45b9-3934-6baaae573cb4.png)

例えば、wikipediaの↓↓の内容を適当にコピーして、、、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/2033644b-05f4-092b-1382-827eb6a707a6.png)

張り付けて generate をクリックしたら勝手に問題作ってくれる。
OpenAIは質問文と回答文の文字量（英語なら単語、日本語のような全角文字は文字単位）なので恐ろしく金かかりそうだ。
怖いので generate を押すのはやめよう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/416263/caceeea2-2b7b-ea1b-7d3d-9635c7ae4ae2.png)

# おわりに
「研修のおわりになんか理解度クイズつくってよ～」って言われたら「予算くれたら何問でも作ってやりますよー！OpenAIがね」と
言える日を夢見て、今日はここまでにしておこう。
Weibo に電話番号ログインできない時の対処法

weiboに電話番号で、ログインできない！

そんな時は、電話番号の入力を工夫する必要があります。

例えば自分の電話番号が、
(+81)080~
なら、

008180~
のように

・00を接頭につけること
・080で始まる場合は80からスタートすること

に気をつけてみてください。
Ruby: MariaDB のバージョンを表示

## プログラム

フォルダー構造

```tree
$ tree -a
.
├── .env
├── config_mariadb.rb
└── server_version.rb
```

```rb:server_version.rb
#! /usr/bin/ruby
#
#	server_version.rb
#
#					Feb/24/2023
#
require 'mysql2'
#
load 'config_mariadb.rb'
# ------------------------------------------------------------
STDERR.puts "*** 開始 ***"
#
host,user,password,data_base = config_mariadb_proc()
client = Mysql2::Client.new(host: host, username: user, password: password, database: data_base)
#
sql_str="SELECT VERSION ()"
result=client.query(sql_str)
#
result.each do |row|
	print "#{row["VERSION ()"]}\n"
end
client.close
#
STDERR.puts "*** 終了 ***"
# ------------------------------------------------------------
```

```rb:config_mariadb.rb
#
#	config_mariadb.rb
#
#					Feb/24/2023
#
require 'dotenv'
#
# ------------------------------------------------------------
def config_mariadb_proc()
	Dotenv.load
	host = ENV['host']
	user = ENV['user']
	password = ENV['password']
	data_base = ENV['data_base']
#
	return	host,user,password,data_base
end
# ------------------------------------------------------------
```

```text:.env
host = 'localhost'
user = 'scott'
password = 'tiger123'
data_base = 'city'
```

## 実行結果

```text
$ ./server_version.rb 
*** 開始 ***
10.11.2-MariaDB
*** 終了 ***
```
2023年にECS入門ワークショップをやる際の注意点

# はじめに
AWSは、いくつかのサービスにおいて、公式にハンズオンを提供しています。
詳しくは、[こちらの記事](https://dev.classmethod.jp/articles/aws-workshops-20190909/)などが参考になります。

その中で、ECSの基本を学びたかったので、[Introduction to Amazon ECS](https://catalog.us-east-1.prod.workshops.aws/workshops/a2b9971a-7a6e-40f3-96e7-5a04b46d1f98/ja-JP)をやってみました。
私のようにECSやFargateの基礎的な理解を深めたい人にとって、とてもいい教材だと思います。

しかし2023年2月現在、そのまま記載の通りに進めるといくつか詰まる箇所があります。
今回、私が詰まったポイントをまとめました。

# CloudFormationのRDS立ち上げで落ちる
[AWSリソース構築](https://catalog.us-east-1.prod.workshops.aws/workshops/a2b9971a-7a6e-40f3-96e7-5a04b46d1f98/ja-JP/1-setup/13-how-to-use-cloudformation)の項で　CloudFormationを使ってAWSリソースをまとめて構築するのですが、そのままだとRDSが落ちます。
![スクリーンショット 2023-02-24 8.27.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447035/f2c33f68-acdd-c9b6-ee4d-32fca1b9b10b.png)
エラーの箇所を見てみると、
![スクリーンショット 2023-02-24 8.28.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447035/61a490e0-2244-0fa5-df39-b609af6949ac.png)
```
Cannot find version 5.7.22 for mysql
```
MySQLの指定バージョンが取ってこれていないようです。
確かに、[公式ドキュメント](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/MySQL.Concepts.VersionMgmt.html)を見ると、一番古いものが```5.7.33```なので、サポートが切れています。
ということで、ダウンロードしたテンプレートjson中の該当箇所を、サポート対象になっているバージョンに変更します。
私は、```5.7.22```→```5.7.40```に変えて通りました。
```diff_json
    "DbInstance": {
      "Type": "AWS::RDS::DBInstance",
      "Properties": {
        "DBInstanceIdentifier": "simplechat-ecs-db",
        "Engine": "MySQL",
-       "EngineVersion": "5.7.22",
+       "EngineVersion": "5.7.40",
        "AllocatedStorage": "5",
        "MasterUsername": { "Ref": "MasterUserName" },
        "MasterUserPassword": { "Ref": "MasterUserPassword" },
        "DBInstanceClass": "db.t2.micro",
        "DBSubnetGroupName": { "Ref": "DbSubnetGroup" },
        "DBParameterGroupName": { "Ref": "DBParameterGroup" },
        "VPCSecurityGroups": [ { "Ref": "RDSSecurityGroup"} ]
      }
    },
```

# ECSのマネジメントコンソールのUIが変わっている
これはAWSあるあるかもしれませんが、UIが変わっていて混乱してしまいました。
クラスターを作成する際、現在はデフォルトで下記のUIになっています。
![スクリーンショット 2023-02-24 8.57.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447035/6435c603-bd95-02e9-ef12-fecb8aefdc62.png)
左上の「新しい ECS エクスペリエンス」をOFFにすると下記の画面になり、ハンズオンに記載されているのと同じUIで操作ができます。
![スクリーンショット 2023-02-24 8.58.56.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1447035/c4ab5cee-213f-5cd2-6760-0933d6e27614.png)
理解が浅いうちは、UIの違いは学習の大きな壁です。
できるだけ、ハンズオンと同じ環境で操作できるようにした方がいいと思います。

# 終わりに
今からECSを学習される方の参考になれば幸いです。
USBキーボードの抜き差しで、キーボードの設定がリセットされてしまう

PCとraspiで１つのキーボードを共有して使っていると、切り替えるたびにキーボード設定がリセットされてしまう件の対策です。

Raspi上の下のファイルを書き換えます。
```bash
sudo vi /etc/X11/xinit/xserverrc
```

例）
```bash
exec /usr/bin/X -nolisten tcp "$@"
```

初めて開いたとき上のような感じだったら、
-ardelay 300 -arinterval 25
を、下のように追記いたします

```bash
exec /usr/bin/X -nolisten tcp -ardelay 300 -arinterval 25 "$@"
```

-ardelay 300 -arinterval 25
の値はお好みに設定してください。
dotnetコマンドのタブ補完を有効にする


dotnet コマンドのタブ補完を有効にするには、次のコードを .bashrc に追加します。

## Bash

```bash:.bashrc
function _dotnet_bash_complete()
{
  local cur="${COMP_WORDS[COMP_CWORD]}" IFS=$'\n'
  local candidates

  read -d '' -ra candidates < <(dotnet complete --position "${COMP_POINT}" "${COMP_LINE}" 2>/dev/null)

  read -d '' -ra COMPREPLY < <(compgen -W "${candidates[*]:-}" -- "$cur")
}

complete -f -F _dotnet_bash_complete dotnet
```

## 参考
https://learn.microsoft.com/ja-jp/dotnet/core/tools/enable-tab-autocomplete
az cliでいろんなパターンでVM作る

# はじめに
いろんなパターンで作るケースが増えたのでここにまとめとく

# VM作る前の共通準備
VM作る前に必須のものをおいていく

## Azureログイン
これしないと何も始められない

```powershell
az login
```

## リソースグループを作成する

```powershell
$resource_group_name = "pro-nabehiro-001"
$location = "japaneast"

# Create a resource group
az group create --name $resource_group_name --location $location

```

## 仮想ネットワークとサブネット作る
仮想ネットワークとサブネットは必須。
一般的な構成として、「APGW用のサブネット」「フロント用サブネット」「バックエンド用サブネット」の３つを作っておこう
通常は「フロント用サブネット」だけで十分だけども。
for文で回すかぁ～とも思ったけど、このくらいならベタ書きの方がわかりやすいと思ったからそのまま書くことにした。

```powershell
$resource_group_name = "pro-nabehiro-001"
$vnet_name = "nabehiro-vnet"
$subnet_name1 = "nabehiro-apgw-subnet"
$subnet_name2 = "nabehiro-web-subnet"
$subnet_name3 = "nabehiro-db-subnet"

# Create a virtual network and subnet
Write-Host "# Create a "$vnet_name
az network vnet create --name $vnet_name --resource-group $resource_group_name --location $location --address-prefix 10.0.0.0/16
Write-Host "# Create a "$subnet_name1
az network vnet subnet create --resource-group $resource_group_name --vnet-name $vnet_name --name $subnet_name1 --address-prefixes 10.0.0.0/24
az network vnet subnet create --resource-group $resource_group_name --vnet-name $vnet_name --name $subnet_name2 --address-prefixes 10.0.1.0/24
az network vnet subnet create --resource-group $resource_group_name --vnet-name $vnet_name --name $subnet_name3 --address-prefixes 10.0.2.0/24
```

## VM作る
リソースグループと仮想ネットワークさえ先に作っておけばあとは名前を決めるだけで作れる。
こだわりたいなら、NSG、可用性セット、NICなども名前や設定決めることもできるけど、
やりたいこと以外はなるべくデフォルトに任せる方針だとこれでなんとかなる。っていう記述をしてるつもり。

### ssh鍵認証でVM作る

```powershell
$resource_group_name = "pro-nabehiro-001"
$vnet_name = "nabehiro-vnet"
$subnet_name2 = "nabehiro-web-subnet"
$vm_name = "nbfr151v"
$vm_size = "Standard_B1ls"
$image_name = "CentOS"
$admin_name = "nabehiro_admin"
$ssh_key_name = "nabehiro-sshkeys"

# Create a ssh-key
Write-Host "# Create a "$ssh_key_name
az sshkey create --name $ssh_key_name --resource-group $resource_group_name

Write-Host "# Create virtual machines"
# Create virtual machines
az vm create --name $vm_name --resource-group $resource_group_name --location $location --vnet-name $vnet_name --subnet $subnet_name2 --size $vm_size --admin-username $admin_name --ssh-key-name $ssh_key_name --image $image_name
```

### パスワード認証でVM作る
ssh鍵認証と違ってssh鍵を作る必要はない。
代わりに--admin_passwordと--authentication-typeの設定が必要になる。

```powershell
$resource_group_name = "pro-nabehiro-001"
$vnet_name = "nabehiro-vnet"
$subnet_name2 = "nabehiro-web-subnet"
$vm_name = "nbfr151v"
$vm_size = "Standard_B1ls"
$image_name = "CentOS"
$admin_name = "nabehiro_admin"
$admin_password = "nabehiro_ADMIN!"

# Create a ssh-key
Write-Host "# Create a "$ssh_key_name
az sshkey create --name $ssh_key_name --resource-group $resource_group_name

Write-Host "# Create virtual machines"
# Create virtual machines
az vm create --name $vm_name --resource-group $resource_group_name --location $location --vnet-name $vnet_name --subnet $subnet_name2 --size $vm_size --admin-username $admin_name  --admin-password $admin_password --authentication-type password --image $image_name
```
【TypeScript】typeとinterfaceの違い

# はじめに

実務で使っているコードで、typeとinterfaceがどちらも使われているのですが、どういう使い分けがされているんだろうと疑問を持ったのが調査のきっかけです。

# typeの場合

```typescript
type Human = {
  name: string;
  age: number;
};

let human1: Human = {
  name: "yamada",
  age: 20,
};

human1.age = "21" // これは型エラーとなる
```

型に名前をつけるみたいな感じですね。

# interfaceの場合

```typescript
interface Human {
  name: string;
  age: number;
}

let human1: Human = {
  name: "yamada",
  age: 20,
};

human1.age = "21" // 型エラーとなる
```

書き方がちょっと変わっただけで、typeとやっていることは一緒です。

# じゃあ違いは何だ？

### 定義できる型の種類

interfaceだとオブジェクトとクラスの型だけ定義できるけど、typeでは他の型も定義できます。

```typescript
type Animal = "トラ" | "ライオン" | "犬" | "猫";

let animal: Animal = "トラ";
animal = "ゾウ"; // ゾウはAnimal型には無いよと怒られます
```

ユニオン型みたいな形で定義もできます。

### 拡張できるかどうか

interfaceは拡張ができます。

```typescript
interface Human {
  name: string;
}

interface Human {
  age: number;
}

const human: Human = {
  name: "tanaka",
  age: 20
};

const human2: Human = {
  name: "yamamoto"
}; // これだとageも指定しろと怒られます
```

再宣言ではなく、新しいプロパティの型定義を追加した形となっています。
ただ、typeでも&を用いることで、拡張のようなことはできるみたいです。

# どちらを使うのが良いのか

interfaceは拡張性があるので、使いやすい気もしますが注意しないといけない点があります。

```typescript
interface Person {
  tall: number;
  weight: number;
}

// 大量のコード

const person: Person = {
  tall: 170,
  weight: 60
}; // Property 'name' is missing in type '{ tall: number; weight: number; }' but required in type 'Person'
```

あれ、nameが必要だけどPersonにない…？と思ってコードを見てみると、

```typescript
interface Person {
  name: string;
}
```

このようなコードが書かれていました。つまり、知らず知らずのうちに拡張されていたのです。

interfaceでできることはtypeでもできるようになったし、typeの方が定義できる型の範囲も広いので、とりあえずtype使っておけば良いのではと個人的には感じました。

# 参考記事
https://zenn.dev/luvmini511/articles/6c6f69481c2d17

https://www.wakuwakubank.com/posts/753-typescript-type-aliases/
DiffusersでNSFW警告からの黒画像を無効にする方法 [Potential NSFW content was detected in one or more images. A black image will be returned instead. Try again with a different prompt and/or seed.]

# はじめに

diffusersを使って画像を生成しようとするとモデルによってはNSFW検出されてしまい黒く塗りつぶされてしまう。
今回はそれの回避方法

探してみると、モジュールのPythonを書き換える方法が見当たるが、pipが使えなくなってしまうので無し。

公式的な方法もなく、いろいろ探していると、まともなやつが出てきたので備忘録

# コード
以下のコードでパイプライン生成後に`safety_checker()`を上書きする

```python
pipe = StableDiffusionPipeline.from_pretrained(MODEL_PATH).to("cuda")
if pipe.safety_checker is not None:
    pipe.safety_checker = lambda images, **kwargs: (images, False)
```

そうすることでセーフティチェッカがダミー関数に置き換わって、そのまま出してくれる。


# 参考

https://www.reddit.com/r/StableDiffusion/comments/wv28i1/how_do_we_disable_the_nsfw_classifier/
Web API（RESTful API）設計時の基礎的なポイント

## はじめに
今更感MAXですが、Web API設計のポイントについて、基礎的なところを聞かれることがあったので雑にメモとしてまとめます。

## Web APIに関する仕様
HTTPステータスコードやJSONなど、Web APIに関する技術は、RFC等で標準化されているので、何か迷うことがあれば立ち返りましょう。

https://developer.mozilla.org/ja/docs/Web/HTTP/Resources_and_specifications
https://standards.rest/

## エンドポイントの名称が名詞かつ複数形になっているか
基本的にエンドポイントの名称は名詞かつ複数形です。

``` .例
https://hoge.co.jp/users
```

個人的には以下の記事が一番しっくりきていますので引用させていただきました。

>WebAPI におけるエンドポイントはリソースを示しているからです。

>「リクエストメソッドと URI の組み合わせ」で「自分が何を要求（リクエスト）しているのか」を示します。

https://qiita.com/ryo88c/items/0a3c7861015861026e00

非リソースURLの場合、動詞を使うテクニックもあるみたいです。

https://qiita.com/baby-degu/items/6f516189445d98ddbb7d#6-%E9%9D%9E%E3%83%AA%E3%82%BD%E3%83%BC%E3%82%B9url%E3%81%AB%E3%81%AF%E5%8B%95%E8%A9%9E%E3%82%92%E4%BD%BF%E3%81%86

## パスパラメータとクエリパラメータとの使い分けができているか
リソースの集合体から一意に特定するような場合はパスパラメータを、リソースの集合体から何かを絞り込むような場合はクエリパラメータを使用します。

Webメディアの記事とかが分かりやすいですが、特定のこの記事ってことを表したいのでパスパラメータを使っていたりすると思います。

``` .例
https://hoge.co.jp/items/hoge
```

クエリパラメータは以下のように使います。

``` .例
https://hoge.co.jp/search?id=fuga
```

## 流れるデータ量を意識した設計になっているか
オーバーフェッチングやリクエストするデータ量が多すぎてパフォーマンスの問題が発生しそうな場合は、クエリパラメタで対象のデータだけ取得できるような設計を考えましょう。

前者の問題に対しては、```fields```で取得する項目名を指定するケースが多い気がします。

後者では、SQLにそのまま当て嵌められるので```offset```と```limit```で指定してあげると使いやすいです。必要に応じてページ番号方式やカーソル方式を検討します。

``` .例
https://hoge.co.jp/search?fields=name,adress&offset=50&limit=50
```

## HTTPステータスコードは適切なものになっているか
500エラーでまとめてしまったりすると、障害時の切り分けで困りますので、適切なものをセットしましょう。

https://developer.mozilla.org/ja/docs/Web/HTTP/Status

## 単語が連なる場合、ケバブケース（ハイフン区切り）になっているか
どっちでも良いみたいな記事もありますが、Google検索セントラルが推奨していたり、有名どころのWebサービスはケバブケース（ハイフン）になっているので、こちらを推奨。

``` .例
https://hoge.co.jp/fuga-piyo
```

https://developers.google.com/search/docs/crawling-indexing/url-structure?hl=ja#:~:text=%E6%8E%A8%E5%A5%A8%E3%81%95%E3%82%8C%E3%82%8B%3A%20%E3%83%8F%E3%82%A4%E3%83%95%E3%83%B3%EF%BC%88%2D%EF%BC%89%E3%82%92%E4%BD%BF%E7%94%A8%E3%81%99%E3%82%8B%E3%80%82

## 参考
https://www.oreilly.co.jp/books/9784873116860/
【Unity】ランタイムで指定したフォルダをファイラーで開く（Mac/Windows）


# TL;DR

```.cs
// MyPicturesフォルダを開く場合
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
System.Diagnostics.Process.Start(path);
```

# 経緯

Windows/Mac向けに開発している『[Vフレット](https://nkjzm.jp/vfret)』というアプリには、スクリーンショットを撮影する機能があります。
![20230224-020432.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/94ee83f8-fa5c-2ace-2546-1ba9f4fbcedb.png)

スクリーンショットは直接PCの指定フォルダ上に保存される仕組みなのですが、撮影後に保存先のフォルダを開くことができると便利かなと思い方法を調べてみました。

まずはこちらで紹介されている方法を試したところ、Windows版では問題なかったのですが、Mac版でうまく動作しない問題に遭遇しました。

https://masakami.com/archives/2020/05/22/663/

そこで Twitterや[Unityゲーム開発者ギルド](https://unity-game-dev-guild.github.io/)で質問をしたところ、Processクラスを使えばいいのではないかとアドバイスをいただきました（皆さんありがとうございました…！）

https://twitter.com/shiena/status/1628730086966071297

Processクラスは通常対象のプロセス名を指定することが多いのですが

```.cs
// プロセス名を指定する方法
System.Diagnostics.Process.Start("EXPLORER.EXE", @"C:\My Documents\My Pictures");
```

[こちらの記事](https://dobon.net/vb/dotnet/process/openexplore.html)によると、

> 「ファイルを関連付けられたソフトで開く」と同じように、フォルダも関連付けで開くことができます。フォルダは通常エクスプローラに関連付けられていますので、関連付けが変更されていない限り、エクスプローラでフォルダが開きます。

とありました。今回はWindowsとMacの両方に対応するアプリなので、プロセス名の指定を省略できる方が同じ記述で要件を満たしテストもシンプルになります。

```.cs
// MyPicturesフォルダを開く場合
var path = Environment.GetFolderPath(Environment.SpecialFolder.MyPictures);
System.Diagnostics.Process.Start(path);
```

そこで上記のようなコードで試してみたところ、Windows/Macそれぞれで意図通りの動作となりました！！

![scren2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55365/98441783-2cf4-417d-1967-dfaa3e552d3a.gif)

# 最後に

Twitterやってるので良かったらフォローお願いします！→ [@nkjzm](https://twitter.com/nkjzm)

また、VRMアバターで"それっぽく"弾き語りができる『Vフレット』というアプリを開発しています。こちらも興味があれば良かったらぜひ見てみてくれると嬉しいです！

https://nkjzm.jp/vfret
Remixでコンポーネントをテストしたときに直面した面倒なエラー

Remixを使って開発しているプロジェクトにて、`@remix-run/react`から公開されている`<Form />`を内部で使用しているコンポーネントをテストしようとしました。

```Item.tsx
import { Form } from "@remix-run/react";

export function Item() {
  return (
    <div>
      <Form method="post">
        <input type="hidden" name="id" value={id} />
        ...
        <button type="submit" />
      </Form>
    </div>
  );
}
```

これを`vitest`と`@testing-library/react`を使ってテストしようとしたところ、次のようなエラーが発生しました。

```shell
The above error occurred in the <FormImpl> component:
...
Error: useNavigate() may be used only in the context of a <Router> component.
```

この`<Item />`コンポーネントでは直接`useNavigate()`は呼び出していませんが、おそらく`<Form />`の内部で呼び出しているために、このようなエラーが発生するのだと推測されます。

これを回避するために、`<BrowserRouter />`でラップすれば良いと思うかもしれませんが、そう簡単にはいきません。

もし仮に`<BrowserRouter />`でラップしてみても`Error: You must render this element in a remix route element`というエラーが発生します。

なので、ここは大人しくVitestの機能を使ってモックを行うことにします。

**vitest.config.ts**にて`test.setupFiles`にセットアップファイルのパスを設定します。

```vitest.config.ts
/// <reference types="vitest" />
/// <reference types="vite/client" />
...
export default defineConfig({
  ...
  test: {
    ...
    setupFiles: ["./test/setup-test-env.ts"],
    ...
  },
});
```

指定したセットアップファイルにて、`@remix-run/react`から公開されている`useNavigate()`と`<Form />`をモックします。

```setup-test-env.ts
import { installGlobals } from "@remix-run/node";
// import { useNavigate } from "@remix-run/react";
import "@testing-library/jest-dom/extend-expect";
import type React from "react";

installGlobals();

vi.mock("@remix-run/react", () => {
  const useNavigate = vi.fn();
  const form = vi.fn().mockImplementation(({ children }: { children: React.ReactElement, }) => {
    return children
  });
  return {
    useNavigate,
    Form: form,
  }
})
```

特徴としては、このセットアップファイルは`tsx`ではないので、`<Form />`をモックするときは`children`を引数に取る関数を渡す必要があります。そしてその関数の中で`children`を返すようにします。

もう一度テストをしてみたところ、無事にテストが通りました。

```shell
Test Files  1 passed (1)
     Tests  1 passed (1)
  Start at  13:05:23
  Duration  2.33s (transform 631ms, setup 669ms, collect 458ms, tests 14ms)


PASS  Waiting for file changes...
```

あまり同じようなエラーに遭遇した人がいないためか、これの問題に正面から解説されている記事がありませんでした。

僕が費やした数時間が、誰かの助けにでもなれば幸いです。

# 参照記事

https://bobbyhadz.com/blog/react-usenavigate-may-be-used-only-in-context-of-router

https://stackoverflow.com/questions/70491774/usenavigate-may-be-used-only-in-the-context-of-a-router-component

https://github.com/remix-run/react-router/blob/dev/examples/basic/src/App.tsx

https://vitest.dev/guide/mocking.html
AWS Hands-on for BeginnersAWS Serverless #1 サーバーレスアーキテクチャで翻訳Web APIを構築する：学習メモ

## はじめに

AWSハンズオン for Beginnersシリーズとして提供されている「[Serverless #1 サーバーレスアーキテクチャで翻訳 Web APIを構築する](https://pages.awscloud.com/event_JAPAN_Hands-on-for-Beginners-Serverless-2019_LP.html?trk=aws_blog)」を実施した際のメモです。
AWSが提供する代表的なサーバーレスサービスであるAWS Lambdaを主に使用して簡単な翻訳APIを作成してみます。
API GatewayからLambdaを呼び出し、翻訳サービスであるAmazon Translateへ翻訳を依頼します。
依頼結果の翻訳文をNo SQLサービスであるAmazon DynamoDBに格納し、翻訳文をレスポンスとして返却します。

## アジェンダ

1. サーバーレスアーキテクチャの概要
2. AWS Lambda の概要
3. AWS Lambda ハンズオン① - AWS Lambda を単体で利用する
4. AWS Lambda ハンズオン② - AWS Lambda から他の AWS サービスを呼び出す
5. Amazon API Gateway の概要
6. Amazon API Gateway ハンズオン① - Amazon API Gateway を単体で利用する
7. Amazon API Gateway ハンズオン② - Amazon API Gateway と AWS Lambda を連携する
8. Amazon DynamoDB の概要
9. Amazon DynamoDB ハンズオン① - Amazon DynamoDB テーブルを作成する
10. Amazon DynamoDB ハンズオン② - AWS Lambda から Amazon DynamoDB に Item を Put する
11. まとめ & 落ち穂拾い & 今後のラーニングパスについて

## メモ

### なぜサーバーレスを使うか？

開発者はお客さまに価値を届けることが本来の目的です。しかし、その目的を果たすために開発者は様々な作業をしなければなりません。
例えば、サーバの発注、サーバにミドルウェアのインストール、耐障害性を考慮したアーキテクチャの設計などです。
このようなことは開発者は本来やりたくないことです。開発者はコーディングやテストに集中したいのです。
サーバーレスサービスを使用することで、これらを意識することがなくなります。そして、本来やるべき開発に集中することができます。

### AWS Lambdaとは？

サーバーのプロビジョニング、管理なしでコードを実行することができるサービスです。
コードの実行やスケーリングに必要なことはLambda側でやってくれるので、コードを書くことに集中できます。

#### その他雑記

- 現在指定できる**メモリ最大量は10GB**です。
- Lambdaの呼び出し元によって起動が非同期または同期になります。
- Lambdaのライフサイクルは以下です。
  - コンテナ生成＝＞デプロイ＝＞ランタイム初期化・起動＝＞メソッド実行
  - ウォームスタートの場合、コンテナを使い回し、最後の部分（メソッド実行）のみ実行します。そのため、実行は速くなります。（このときグローバル変数は使いまわされるため注意）
- Lambdaのタイムアウト時間の**最大は15分**です。申請などで伸ばすことはできません。実装しようとしている処理が15分を超える可能性がある場合、LambdaではなくECSやEC2の使用を検討しましょう。
  - ただ、タイムアウトを許容し、タイムアウト後のリカバリができるような設計ができるのであれば、その限りではないと思っています。

### API Gatewayとは?

サーバーのプロビジョニング、管理することなくAPIの作成管理ができるマネージドサービスです。
Lambdaと同様に、これを使うことで開発者が本来力を入れたいことに集中することができます。

#### 作成の流れ

1. リソースとメソッドタイプの定義
2. メソッドリクエストの設定
3. 統合タイプの設定
4. リクエストレスポンスの変換の定義
5. デプロイ

#### その他雑記

- Lambda プロキシ統合を使用することで、APIのリクエストパラメタを規定のJsonにマッピングし、Lambdaに渡すことができます。
  - これによりマッピングテンプレートでパラメタをどのように渡すか考えなくて良くなります。
  - なお、Lambdaが返却する形式も決まっており、以下の形で返却しなければなりません。
- Lambdaのテスト設定にAPI Gateway Proxy統合のEventテンプレートが提供されています。一度見てみると良いでしょう。

### DynamoDBとは?

フルマネージドなKey-Value型のNo SQLデータベースサービスです。

#### その他雑記

- プライマリキーは項目を一意に識別する項目です。
- ソートキーがある場合、プライマリキーとの組み合わせで項目が一意になります。
- プライマリキー、ソートキー以外は自由に列を定義できます。不揃いでも問題ありません。
- マネジメントコンソールから項目の追加する時、プライマリキーの入力欄は事前にありますが、それ以外の項目は自由に追加できる形になっています。

## ハンズオンの感想

AWSのサーバーレスサービスを使用をLambdaで組み合わせ翻訳APIを簡単に作成することができました。
Lambdaについては仕事で開発しているので抵抗はありませんでしたが、
API Gateway、DynamoDBはちょっとしか触れておらず、詳細まで把握していませんでした。
今回のハンズオンで基礎的なところを再学習できたのでよかったです。
超簡単なアルゴリズムによる素因数分解　in bash,zsh,sh,C++,C,Python,GAME言語,Perl

超簡単なアルゴリズムによる素因数分解です。
与えられた数を2から一つずつインクリメントする変数で片っ端から割っていき、余りが出なかったらその数を因数として登録するという、最も原始的なアルゴリズムです。多分、一番簡単なのではないでしょうか。
nには自然数を与えて下さい。
shとC言語とpythonとGAME言語とC++とperlで書かれています。
GAME言語のバージョンはおまけです。いらないでしょうけど、古のGAME言語を懐かしむ人がいたら見て下さい。

# sh

```factor.sh
#!/bin/bash
function PrimeFactorization() {
  i=2
  j=0
  num=$1
  arr=()
  if test $num -eq 0; then
     return
  fi
  if test $num -eq 1; then
     return
  fi
  while test $num -ne 1
  do
     if test $((num % i)) -eq 0; then
         arr+="$i "
         num=$((num/i))
         j=$((j+1))
     else
         i=$((i+1))
     fi
  done
  return
}

PrimeFactorization $1
echo "$1 : ${arr[@]}"
```

chmod +x factor.bash
./factor.bash <n>
として動かして下さい。

# C

```factor.c
#include  <stdio.h>
#include  <stdlib.h>
int PrimeFactorization(uint num,uint *arr)
{
  int i=2,j=0;
  if (num==0)
    return(0);
  else if (num==1) {
    return(0);
    }
  while(num!=1) {
    if (num%i==0) {
      arr[j]=i;
      num/=i;
      j++;
      }
    else i++;
    }
  return(j);
}

int main(int argc,char *argv[]) {
    uint arr[10000],n=atoi(argv[1]),nop;
    nop=PrimeFactorization(n,arr);
    printf("%d : ",n);
    for(int i=0;i<nop;i++)
      printf("%d ",arr[i]);
    printf("\n");
    return(0);
}
```

cc factor.c -o factor としてコンパイルして下さい。
その後、
factor \<n\>
として動かして下さい。


# python

```factor.py
#!/usr/bin/python3
import sys
def PrimeFactorization(n):
  i=2
  j=0
  f=[]
  if n==0:
    return []
  elif n==1:
    return []
  while(n!=1):
    if n%i==0:
      f+=[i]
      n=n/i
      j=j+1
    else:
      i=i+1
  return f

n=int(sys.argv[1])
f=PrimeFactorization(n)
print(n,":",f)
```

chmod +x factor.py
./factor.py \<n\>
として動かして下さい

# GAME言語

```factor.gm
#!/usr/bin/gamelinux
1000 "Input natural number : " N=?
1010 Z=$0000 !=1100
1020 ?=N ":"
1030 ;=J I=0,J-1 ?=Z(I) " " @=I+1
1040 /
1050 #=-1
1100#
1101# Sub routine of PrimeFactorization
1103#
1105 I=2 J=0 M=N
1110 ;=M=0 J=0 ]
1130 ;=M=1 ]
1135   H=M/I
1136   ;=%1=0 Z(J)=I M=H J=J+1 #=1130
1140     I=I+1 #=1130
```

gamelinux factor.gm
として動かして下さい。

# C++


```factor.cpp
#include  <iostream>
using namespace std;
int PrimeFactorization(int num,int arr[])
{
  int i=2,j=0;
  if (num==0)
    return(0);
  else if (num==1) {
    return(0);
    }
  while(num!=1) {
    if (num%i==0) {
      arr[j]=i;
      num/=i;
      j++;
      }
    else i++;
    }
  return(j);
}

int main(int argc,char *argv[]) {
    int arr[10000],n=atoi(argv[1]),nop;
    nop=PrimeFactorization(n,arr);
    cout << n << " : ";
    for(int i=0;i<nop;i++)
      cout << arr[i] << " ";
    cout << endl;
    return(0);
}
```

g++ factor.cpp -o factorcpp
としてコンパイルし、
factorcpp \<n\>
として動かして下さい。

# perl

```factor.pl
#!/usr/bin/perl
sub primefactorization {
  local($n,$i,$j,@f);
  $n=$_[0];
  $i=2;
  $j=0;
  @f=();
  if ($n==0) {
    return @f;
    }
  while($n!=1) {
    if ($n%$i==0) {
      push(@f,$i);
      $n=$n/$i;
      $j=$j+1;
      }
    else {
      $i=$i+1;
      }
    }
  return @f;
}

$n=$ARGV[0];
@l=&primefactorization($n);
$,=',';
print "$n:@l\n";
```
`./factor.pl <n>`として動かしてください。
Circle CIでnmakeビルドを動かす方法


Circle CIでは[dotnet.exeやMSBuildでのビルド例はあるようなのですが](https://github.com/CircleCI-Public/circleci-demo-windows)、nmakeでのビルドは、探してもなかなか見つかりませんでした。

msbuildとは異なり、nmakeは、そのままの状態だとコマンドにパスが通っていないため、呼び出せません。手動ビルドの時は、vcvarsall.batなどで開発者コマンドプロンプトに入ってからビルドしてましたが、Circle CIでそれをやると、バッチ実行以降の処理が、実行ログに全く記載されなくなります。call等で呼び出すと、次の行では環境変数が元に戻ってしまいます。GitHub Actionでは、vcvarsall.batで設定される全部の環境変数を引き継ぐ[msvc-dev-cmd](https://github.com/ilammy/msvc-dev-cmd)というものがあるので、それを呼び出すだけなのですけどね。

## 対処

powershell.exe (windows executorのデフォルト)で実行し、開発者用PowerShellの起動ショートカットの中身を直接実行するような感じで実装しました。

```yaml
      - run:
          name: compile
          command: | 
            $vswhere = "C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe"
            $instanceId = & $vswhere -property instanceId -format value
            $installationPath = & $vswhere -property installationPath -format value
            Import-Module (Join-Path $installationPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll")
            Enter-VsDevShell $instanceId -SkipAutomaticLocation -Arch amd64
            nmake /F NMakefile
```

※ 32ビットの場合は`-Arch x86`です。

vcvarsall.batの環境変数を全部取り出して引き継ぐ方法よりも、こちらのほうが短く書けて、すっきりしました。

参考：

* [Developer Powershell for VS 2019をWindows Terminalから開く](https://zenn.dev/shiena/articles/developer-pwsh-terminal)
* [Visual Studio 開発者コマンド プロンプトと開発者用 PowerShell](https://learn.microsoft.com/ja-jp/visualstudio/ide/reference/command-prompt-powershell?view=vs-2022#developer-powershell)

## おまけ

今回、3つのプロジェクトで、Circle CIのワークフローを書きました。Circle CIの存在を知ってからわずか数日で、それぞれの更新をリリースできるまでになりました。ご参考までに。

* [lslint](https://github.com/Makopo/lslint/blob/master/.circleci/config.yml): LSLの構文チェックバイナリ。Win/OSX/Linuxのそれぞれのビルド処理あり。
* [sublime-text-lsl](https://github.com/Makopo/sublime-text-lsl/blob/master/.circleci/config.yml): SublimeTextのLSL(SecondLifeのスクリプト言語)のプラグインです。
* [sublime-text-tooltip-lsl](https://github.com/Makopo/sublime-text-tooltip-lsl/blob/master/.circleci/config.yml): こちらもSublimeTextのプラグインです。ちょっと短め。

※ リンクは、config.ymlへの直リンです。

全て、kwdbという、LSLの定数や関数の一覧を提供しているリポジトリから、データをダウンロードしてきています。lslintでは、ダウンロードしたデータを、makeでソースに変換して、リポジトリにコミットしています。下2つは、[kwdb_to_sublime](https://github.com/Makopo/kwdb_to_sublime)という、変換処理だけを入れてあるリポジトリをクローンして、それを使って定義ファイル類に変換し、コミットしています。
JavaScirptの基礎まとめ 基礎編1～これは絶対に覚えておくべき～

# JavaScript 基礎編1
最近、js(JavaScript)を復習しているのですが、学んだことを忘れないために何かできないかと考え記事を書くことにしました。
参考書の内容を自分で復習しやすいようにまとめています。
(記事に間違いがあれば指摘お願いします)

## JavaScriptとは
jsはweb上での動きをつけることができる。webサイトの処理はクライアント側とサーバ側があるが、jsはクライアント側でのweb上の見た目の動きを処理する役割がある。
jsとjavaは名前が似ているが、まったく違うもの。

## 変数名のつけ方
変数をつけるときに変数宣言をする必要がある。
変数宣言をする際につけるキーワードは3つ。

var,let,const。letは再代入可能な宣言、constは再代入不可の宣言。

値を変更したくないときはconstを使う。
varとletはほとんど同じだが、varは特殊で、宣言した変数をもう一度宣言できてしまうのでletを使うのが良い。

```javascript
let 変数名 = 値;
const 変数名 = 値;

let tmp = 0;
const tmp = 0;
```

## データ型
データ型には数値型、文字列型、論理型、Null型、Undefined型がある。

- 数値型（Number）：数値を表すデータ型
ex) let number = 0;（クォーテーションで囲むと文字列として認識されてしまう）
- 文字列型（string）：文字列を表すデータ型
ex) let name = "sample";
- 論理型（Boolean）：trueとfalseを表す型
- Null型：値としては存在するが空であることを表す型
- Undefined型：存在しない型

変数宣言時にはデータ型は考えなくてよい。（C++のようにint,stringなどの特別なコード記述はしなくてよい。）
下記のようにtype of 調べたい値とすることで値の型を調べることができる。
```javascript
type of 値;
type of 'abc';
```

## 配列
配列を定義、アクセス
アクセスする要素のインデックスを変数に代入
```javascript
const samples = ['値1','値2','値3']; //定義
const element0 = sample[0]; //アクセス
```

要素の上書き
上書きの際は上書きしたい要素のインデックスを指定
```javascript
const samples = ['値1','値2','値3'];
samples[0] = '値0';
```

要素の数
lengthで要素の個数を調べることができる。
```javascript
配列.length;
```

最後尾に要素を追加する
```javascript
配列.push（追加したい要素）;
```

最後尾から要素を取り出す
```javascript
配列.pop();
```

特定の要素が配列に含まれるか調べる
```javascript
配列.includes（要素）;
```

配列要素の結合と文字列の分割
```javascript
配列.join(区切り文字)
const samples = ['値1','値2','値3'];
const a = samples.join('と');
console.log(a); //値1と値2と値3
```

文字列から配列を生成する
```javascript
文字列.split(区切り文字)
const string = '友情&勇気&努力';
const a = string.split('&');
console.log(a); //['友情','勇気','努力']
```

## 条件分岐

もし～ならば、～である。そうでないならば～の処理はif文を使う。
```javascript
if(条件式){
条件式がtrueの場合の処理;
}else{
条件式がfalseの場合の処理;
}
```

もし～ならば、そうでなくて、もし～ならば～である。そうでないならば～の処理。
```javascript
if(条件式1){
条件式1がtrueの場合の処理;
}else if(条件式2){
条件式2がtrueの場合の処理;
}
else{
どの条件式もtrueにならない場合の処理;
}
```

三項演算子
if文を簡潔なコードで書く
```javascript
(条件式) ? trueのときに返す値 : falseのときに返す値;
```

論理積と論理和
```javascript
条件式A && 条件式B //論理積　AとBの両方がtrueならture。そうでないならfalse
条件式A || 条件式B //論理和　AとBのどちらか1つがtrueなら、true。両方falseならfalse
```

swich文
if文より簡潔に書ける場合がある。
```javascript
switch(変数){
  case 値1:
    変数が値1となるときの処理;
    break;
  case 値2:
    変数が値2となるときの処理;
    break;
  case 値3:
    変数が値3となるときの処理;
    break;
  default:
    その他の処理;
}
```

## 繰り返し処理
for文の書き方
繰り返し表示する
バックティック``で囲まれた中で${変数}と書くと変数の中身を文字列に入れることができる
```javascript
for(初期化式; 条件式; 加算式){
  処理;
}

for(let i = 1; i <= 6; i++){
console.log(`${i}回目の処理`);
}
```

while文の書き方
回数を指定せずに繰り返し処理を行う
条件式がfalseなら処理を終了、trueなら処理を実行
```javascript
while(条件式){
  処理;
}
```

配列の繰り返し処理を書く方法
```javascript
for (変数 of 配列){
  処理;
}

const samples = ['値1','値2','値3'];
for (const sample of samples){
  console.log(sample);
}
```


## 次回
基礎編2は[こちら](https://qiita.com/shinry/items/0a5ba30676e3b72cdc01)
Information of KatMovie

 The only thing that comes to mind is how to view a recently released movie, according to KatmovieHD Movies. The majority of people use browsers to open any website and search for and download movies online.
 
Today, I'm going to discuss the Katmovie movie download website in this article.
 
These days, there are many websites on the internet where you may download movies. The popular website <a href="https://katmoviehdonline.com/">katmovie</a> is one of them.
 
Even though many consumers are aware that 90% of movie-downloading websites offer pirated movies, many nevertheless choose to download from these sites.
 
What is Katmoviehd?
 
Online movie downloader KatmovieHD offers free access to practically all movies and television shows that have been stolen.
 
A fairly well-known website for downloading movies is KatmovieHD. Many people download it from this website. 
Information about KatMovieHD
 
A website for downloading pirated movies that is remarkably similar to other sites for downloading movies is called <a href="https://katmoviehdonline.com/">katmoviehd</a>. Here, you may download a wide range of movie genres, including Hindi-dubbed, Bollywood, Punjabi, South Indian, Hollywood, and MB-wise movies.
 
In addition to this, you may download a lot of TV shows and online series from it.
 
The finest part is that you can download them in accordance with various qualities. That is to say, If your internet connection is sluggish, you can download a low-resolution copy of the print.
 
The print quality of movies is available in a variety of formats, including 360p, 480p, and 720p. It also offers dual audio movies in 1080p resolution.
ChatGPTを駆使して自らを廃業に追い込んでみる試み（過去の投稿ネタをChatGPTに振ってみた）

自分の記事

https://qiita.com/kob58im/items/fd5ba48244bf66192603

に対抗させてみた。

# C#の文字列操作でよく使うメソッドやプロパティの逆引きリファレンスを作ってください。

> 以下は、C#の文字列操作でよく使うメソッドやプロパティの逆引きリファレンスです。
<b>メソッド
文字列の分割・結合</b>
Split(char[], StringSplitOptions) : 指定した文字で文字列を分割します。
Join(string, IEnumerable<string>) : 指定した区切り文字で文字列を連結します。
<b>文字列の検索・置換</b>
Contains(string) : 指定した文字列が含まれているかどうかを調べます。
IndexOf(string) : 指定した文字列が最初に出現するインデックスを返します。
LastIndexOf(string) : 指定した文字列が最後に出現するインデックスを返します。
Replace(string, string) : 指定した文字列を別の文字列に置換します。
<b>文字列のトリミング・パディング</b>
Trim() : 文字列の先頭と末尾にある空白文字を削除します。
TrimStart() : 文字列の先頭にある空白文字を削除します。
TrimEnd() : 文字列の末尾にある空白文字を削除します。
PadLeft(int) : 文字列を指定した長さになるように左側にスペースを追加します。
PadRight(int) : 文字列を指定した長さになるように右側にスペースを追加します。
<b>大文字・小文字の変換</b>
ToLower() : 文字列をすべて小文字に変換します。
ToUpper() : 文字列をすべて大文字に変換します。
<b>文字列の比較</b>
Equals(string) : 指定した文字列と等しいかどうかを調べます。
Compare(string, string) : 2つの文字列を比較します。
CompareTo(string) : 指定した文字列と自身を比較し、大小関係を返します。
<b>プロパティ
文字列の長さ</b>
Length : 文字列の長さを取得します。
<b>文字列の形式</b>
ToLower() : 文字列をすべて小文字に変換します。
ToUpper() : 文字列をすべて大文字に変換します。
IsNullOrWhiteSpace : 文字列がnull、空白文字、または空白文字のみで構成されているかどうかを調べます。
<b>文字列の構成</b>
Chars[int] : 指定したインデックスにある文字を取得します。
Substring(int) : 指定した位置から末尾までの文字列を取得します。
Substring(int, int) :

日本語だと途中で力尽きがちですが、だいぶそれっぽいのが出てきました・・

↓さらにその上を行かせてみる

# pythonと上記を対比させてください。

> 以下は、Pythonの文字列操作でよく使うメソッドやプロパティと、C#のそれらとの対比です。
<b>文字列の分割・結合</b>
Python：split(sep=None, maxsplit=-1)
C#：Split(char[], StringSplitOptions) / Join(string, IEnumerable<string>)

以下略

やばいわコレ。
ChatGPTの使い方はChatGPTに聞けばいい ～ 行列計算させてみた（失敗）

# How to input a matrix of mathematics to you.

> To input a matrix of mathematics to me, you can use the following format:

(中略)

> For example, the following is a 3x3 matrix:

```
[ 1, 2, 3 ]
[ 4, 5, 6 ]
[ 7, 8, 9 ]
```

> You can copy and paste this format when inputting a matrix to me. Alternatively, you can use a math typesetting tool or software, such as LaTeX or MathJax, to format your matrix and then input the resulting code to me.

なんか教えてくれました。
というわけで試しに逆行列を計算させてみます。

# Calculate the invert of below matrix:
[ 1, 2, 3 ]
[ 4, 5, 6 ]
[ 7, 8, 9 ]

※invertじゃなくてinverseが正のようだが、通じた模様

（中略）

> Therefore, the inverse of the matrix A does not exist.

適当にコピペして逆行列を計算させようとしましたが、「この行列の逆行列は存在しません」とのことで、参りました。。
たしかに、第２行と第３行から第１行を減算すると、第２行と第３行がスカラー倍の関係になるので、行列式が0になって逆行列は存在しない。

# Calculate the invert of below matrix:
[ 1, 1 ]
[ 0, 1 ]

> A^-1 = [ 1, 0 ]
[ 0, 1 ]

「この逆行列が単位行列なわけあるかいっ」と心の中で突っ込みつつ

# i think it's incorrect.

> I apologize for the mistake in my previous response. The inverse of the matrix

(中略)

> A^-1 = [ 1, 0 ]
       [ -1, 1 ]

なんかそれっぽく返って来ましたが、検算（行列の乗算）してみると単位行列にならない・・・


A^-1を転置してみるとあってそうなので(日本語で)突っ込んでみたが以下のように会話がかみ合わず断念。。

# あなたは行列の掛け算をするときに、右オペランドの行列を転置行列にしていませんか？
>いいえ、私は行列の掛け算をする際に、右オペランドの行列を転置行列にすることはありません。もし私の前の回答で誤解を招くような表現があった場合、お詫び申し上げます。
例えば、先程の問題について、以下のように計算しています：

```text
A = [ 1, 1 ]
    [ 0, 1 ]

A^-1 = [ 1, 0 ]
       [ -1, 1 ]

A * A^-1 = [ 1, 1 ] * [ 1, 0 ]    =  [ 1, 0 ]
          [ 0, 1 ]   [ -1, 1 ]       [ 0, 1 ]
```

謎仕様・・・こういう表記法ということなのか（？）
Rubyで絵文字を判定する正規表現

# 前置き

Ruby on RailsでWebアプリを作っている途中で正規表現で絵文字を引っ掛けることはできないかと考え、たどり着いた答えを自分用に残しておきます。

結論から述べると絵文字がunicodeのutf-8の中の4byteの文字であることを利用しました。

[UTF-8の文字コード表](https://orange-factory.com/dnf/utf-8.html)
ここでまとめてくださっている情報によると、現在わたしたちが絵文字と呼んでいる文字たちはコードポイントでいうと主に「U+1F300」から始まっています。

[Unicodeがどんな風にUTF-8に割当てられているか](https://orange-factory.com/dnf/unicode.html)
さらに、同サイトの中で4byte文字はコードポイントでいうと「U+10000〜U+1FFFFF」であることが述べられています。


:::note info
ざっくりメモ
Unicode→あらゆる文字を16進数の数字に変換したもの、コードポイントの集合体
<コードポイントの例>
あ→U+3042
い→U+3044
🌱→U+1F331

UTF-8→Unicodeをさらに符号に変換する方式の一つ
<変換した例>
あ→E38182
い→E38183
🌱→F09F8CB1

>Unicodeのコードポイントをそのままパソコンに理解させるよりもUTF-8などによる符号を使う方がバイト削減できるため、UTF-8で符号化している。
>[【図解】【3分解説】UnicodeとUTF-8の違い！【今さら聞けない】](https://qiita.com/omiita/items/50814037af2fd8b2b21e)
>@omiita 様より引用
:::


# バリデーション方法

具体的にどのようにバリデーションしたかというと、コードポイントで4byteの文字を指定しました。


#### 正規表現でのコードポイント記法

>[はじめての正規表現とベストプラクティス#7: Unicode文字ポイントとUnicode文字クラスのプロパティ](https://techracho.bpsinc.jp/hachi8833/2019_02_20/69831)
><img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3024706/f60544a1-833f-9005-17a5-87d61c5f5a2c.png">
>hachi8833様より

#### 具体的な文字範囲

>[UTF-8の4バイト文字のバリデーション](https://www.pistolfly.com/weblog/2020/04/utf-8%E3%81%AE4%E3%83%90%E3%82%A4%E3%83%88%E6%96%87%E5%AD%97%E3%81%AE%E3%83%90%E3%83%AA%E3%83%87%E3%83%BC%E3%82%B7%E3%83%A7%E3%83%B3.html)
>UTF-8にエンコードすると4バイトになるUnicode文字の範囲は、U+10000からU+10FFFFである。
>Pistolfly様より



上記の記事により、Rubyでコードポイントを用いて、絵文字(4byte文字)をバリデーションする正規表現を書く時は
```
/[\u{10000}-\u{10FFFF}]/
```
となります。
実際にRubularで確認してみると、、、
<img width="700", src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3024706/09a113f1-d9e9-2db0-cf1b-446647f3d66b.png">
うまくいきました。
[Rubular](https://rubular.com/)
【備忘録】Laravelルーティングエラー

# この記事の内容
Youtubeで「ReactRouterでページを分ける：React.js + LaravelでSPA開発講座」見た時にルーティングでエラー出たので、その解消について記載。
同じような人がいてその参考になれば

## 状況
routes/api.php 内で TaskController を呼び出した際に、下記のようなエラーが表示されてしまった。
```
Class "TaskController" does not exist
```
![ルートエラー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/462658/c88964d0-8fb0-89bf-945e-566863dc64f4.png)

## 原因
TaskControllerなんか存在しないって言われているので、探し出せていない。
TaskControllerを呼び出している該当箇所は下記になります。

```routes/api.php
Route::get('/tasks', 'TaskController@index');
```

## 解決策
コントローラー名の前に、完全な名前空間を追加してみる。

```routes/api.php
Route::get('/tasks', 'App\Http\Controllers\TaskController');
```

これで画面表示ができた。
【VSCode】保存時にMarkdownの一覧表を整形する

## 拡張機能をインストール

テーブルを整形するために以下の拡張機能をインストールします。

https://marketplace.visualstudio.com/items?itemName=yzhang.markdown-all-in-one

`Markdown All in One`はテーブルの整形以外にも以下のような機能があります。

- 目次作成
- 見出しナンバリング
- リスト編集補完
- MarkdownをHTMLに変換
- 数式
- 自動補完
- リンク貼り付け支援

## 保存時に整形されるよう設定する

`cmd + shif + p`でコマンドパレットを開きます。  
`Preferences: Open User Settings (JSON)`を実行し`setting.json`を開きます。  
`setting.json`に以下を追記します。  

```setting.json
  "[markdown]": {
    "editor.defaultFormatter": "yzhang.markdown-all-in-one",
    "editor.formatOnSave": true
  },
```

すると`.md`ファイルを保存した際にテーブルが整形されるようになります。
QC検定 ー　検定と推定

# 流れ

1. 仮説を立てる
1. 有意水準を決める（基本は５％）
1. 検定統計量を計算
1. 検定し有意性を判定
1. 点推定
1. 区間推定（基本は１００－５＝９５％）

# 仮説を立てる

まず、帰無仮説(H0)をたてる。内容は証明したい仮説と逆の内容。
つぎに対立仮説(H1)をたてる。内容はH0と逆。つまり証明したい内容

# 有意水準を決める

基本は5%、たまーに1%。小さいほど誤りが少ない。

片側検定：片側に5％ ○○が大きくなった。小さくなった。というときに使う
両側検定：両側に2.5％づつ。併せて5％　○○が変化した。というときに使う

判定の誤り
| 種別 | 記号 | 内容 |
|:-:|:-:|:-:|
|  第1種の誤り | α | 帰無仮説が真にもかかわらず、棄却する誤り。あわて者の誤り  |
| 第2種の誤り  | β |　帰無仮説が偽にもかかわらず、採択する誤り。ぼんやり者の誤り  |

# 有意性の判定

| 名前 | 範囲 | 判定 |
|:-:|:-:|:-:|
|  採択域 | \|検定統計量\| < 棄却限界値  | 帰無仮説が成り立つ  |
|  棄却域 | \|検定統計量\| ≧ 棄却限界値  | 帰無仮説が成り立たない  |

# 検定統計量を計算～区間推定

| 種別 | 検定統計量 | 分布表 | 点推定 | 区間推定 |
|:-:|:-:|:-:|:-:|:-:|
| 平均値<BR>（母分散が既知）  | $ Z=\frac{\bar{x}-\mu_0}{\sqrt{\frac{\sigma^2}{n}}} $  | 正規分布  | $ \bar{x}  $ | $ \bar{x} \pm Z(\frac{\alpha}{2})\frac{\sigma}{\sqrt{n}}  $ <br>$Z(\frac{\alpha}{2})$は正規分布表から求める|
|  平均値<BR>（母分散が未知） | $ t=\frac{\bar{x}-\mu_0}{\sqrt{\frac{V}{n}}} $  | t分布<br>$\phi=n-1$  | $\bar{x}$  |$\bar{x} \pm t(\phi,\alpha)\sqrt{\frac{V}{n}}$ |
| 母平均の差<br>（対応あり）  |  $ t=\frac{\bar{d}}{\sqrt{\frac{V_d}{n}}} $ |  t分布<br>$\phi=n-1$ | $\bar{d}$  | $\bar{d} \pm t(\phi,\alpha)\sqrt{\frac{V_d}{n}}$ |
|  母平均の差<br>（対応なし、等分散） |  $ t=\frac{\bar{x_A}-\bar{x_B}}{\sqrt{V(\frac{1}{n_A}+\frac{1}{n_B})}} $ | t分布<br>$\phi=(n_A-1)+(n_B-1)$  | $\bar{x_A}-\bar{x_B}$  | $(\bar{x_A}-\bar{x_B})\pm t(\phi,\alpha)\sqrt{V(\frac{1}{n_A}+\frac{1}{n_B})}$|
| 母分散の変化  |  $ X^2 = \frac{S}{\sigma^2_0} $  |  $ X^2$分布 <br>$\phi=n-1$ | $ V = \hat{\sigma^2} $  | 上限：$\frac{S}{X^2(\phi,1-\frac{\alpha}{2})}$ <br> 下限：$\frac{S}{X^2(\phi,\frac{\alpha}{2})}$ |
|  2つの母分散の違い | $ F = \frac{V_A}{V_B} $  |  F分布<BR>$\phi_1=n_B-1$ <br>$\phi_2=n_A-1$| ―  |―|
| 不良率の差<br>(正規分布で近似)  | $ u=\frac{p_A-p_B}{\sqrt{\bar{p}(1-\bar{p})(\frac{1}{n_A}+\frac{1}{n_B})}} $  |  正規分布 | $ p_A-p_B $ | $(p_A-p_B) \pm K_p \sqrt{\frac{p_A(1-p_A)}{n_A}+\frac{p_B(1-p_B)}{n_B}}$ |

# 記号の説明

| 記号 | 説明 | 記号 | 説明 | 記号 | 説明 |
|:-:|:-:|:-:|:-:|:-:|:-:|
| $\bar{x} $ | 標本平均値  | $ V $ | 不偏分散 |$ \hat{X} $ | Xの推定値 |
|  $ \mu_0 $ |  母平均 | $ S $ | 偏差平方和 | $ \bar{p} $ | 不良率の平均値 | 
| $ \sigma^2 $  |  母分散 | $ \sigma^2_0 $ | 分散 |$\bar{d}$|ペアごとの差の平均|
| $ n $  |  標本数 | $ \phi $ | 自由度 |$V_d$|ペアごとの差の分散|
MS-DOS バッチをChatGPTに書かせてみた

人類にはMS-DOSプロンプトはつらすぎたので、AIに書かせればいいんじゃない？　と思ってやってみた。

(日本語だと処理が重いのでテキトウな英語で指示してみた。)

# Write a MS-DOS batch script that checks file extension of 1st command line argument. (コマンドライン引数の拡張子をチェックするMS-DOSバッチを書いて)

(略)

# Check the extension is ".xml" or not, ignore case. (大文字小文字を区別せずに拡張子が.xmlかチェックして)

(略)

# Please translate above chat to Japanese. (日本語に翻訳して)

```bat
@echo off
setlocal enabledelayedexpansion
set "ext=%~x1"
if /i "!ext!"==".xml" (
    echo %1のファイル拡張子は.xmlです。
) else (
    echo %1のファイル拡張子は.xmlではありません。
)
```

> この更新されたスクリプトは、以下のようなことを行います。
>1. `setlocal enabledelayedexpansion` は、変数を`if`文の中で使用できるようにするための遅延展開を有効にします。
>2. `set "ext=%~x1"` は、前述のスクリプトと同じように、最初の引数のファイル拡張子を `ext` 変数に設定します。
>3. `if /i "!ext!"==".xml"` は、`ext` 変数が `".xml"` と等しいかどうかをチェックします。`/i` オプションは、大文字と小文字を区別しないようにします。
>4. `ext` が `".xml"` と等しい場合、スクリプトはメッセージを表示して、

途中で出力がとまりました。。。日本語だと負荷が高い模様・・

たぶん合ってると思います。（テキトウ）

# 参考サイト

https://qiita.com/yz2cm/items/8058d503a1b84688af09
PHP：関数：可変長引数：引数を可変させたい時に利用。受け取っただけで自動的に配列化する。

非常に便利。なんと、関数で取得する仮引数がいくつかわからなくてもよい記法。
さらに便利なのが、仮引数は配列じゃないなずなのにforeachを使って加工できる。
なぜできるか？というと、仮引数の前に「…」と、ドットを三つ書く（...トークン）と、配列として受け取る仕様になっているから。

公式：https://www.php.net/manual/ja/functions.arguments.php#functions.variable-arg-list

> 引数リストに ... トークンを含めることで、 その関数が可変長の引数を受け取ることを示せます。 引数は、指定した変数に配列として渡されます

気をつけねばならないのは、あくまでも非配列として仮引数には入ってくるが、受け取り方が配列になっていると思われる点。なぜなら、仮引数の型をarrayと指定するとエラーになった。
従って、型の指定に注意する。

これは有用。いきなりforeachが使えて非常に便利。

```php
function changeNum(string ...$cards): array {
    foreach ($cards as $card) {
       // 処理
    }
}
```
Python全く分からん自分のアウトプット　その4

4日目：今日もはりきって進めていくぞい！！！


◎以下調べたこと、疑問に思ったこととかのメモ◎

for文・・・繰り返し処理

while文・・・ある条件に当てはまる間、処理を繰り返す。「while x<=100:」これは100までtrue。最後の変数の値を更新し忘れると無限ループになる。

無限ループ・・・コンピュータに大きな負荷がかかるから必ず阻止。

break・・・繰り返し処理を無理やり終わらせられる。※ここけっこうミスった

continue・・・その周の処理だけスキップできる。インデント忘れないように。


ｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰｰ

Pythonコース2が終了。最後の11〜14まで答え見まくった。
見ても「あれ？」ってなるところが多かった。コロンのつけ忘れやインデントがない箇所が目立った。ケアレスミスに注意。
今回学習した章の途中になんか脳内で、レジってこんな感じで動いてるのかなって思った。
これできるようになったらレジとかつくれるってこと！？夢が広がるZE☆
Pythonコース1を復習がてら軽く進めていたら思ったよりサクサク進められたから手応えはあるように感じた。
次はPythonコース3行くぞ！！！！うおおおおおおおおお！！！！！
Webサービスに使用する技術 (SPA化)

現在ポートフォリオ作成のためにテーマの検討や使用技術の選定をしています。
近年のWebサービス開発ではSPA化することが増えているようで、私のポートフォリオでも導入しようと考えているので今回は「SPA化するメリット」についてまとめました。
(2023年2月23日時点でざっと調べてわかったことをメモしています。誤った情報があるかもしれませんのでご了承ください。調査を加え次第随時更新します。)

# SPA化のメリット
* UXの向上
* 高速なページ遷移を実現可能
    * 表示速度が1秒遅れることでコンバージョンが7%低下する（出典は[こちら](https://blog.kissmetrics.com/loading-time/?wide=1)）という調査結果がある
* ネイティブアプリの代わりとして提供可能

# 参考サイト
* [シングルページアプリケーション（SPA）の導入メリット＆デメリット](https://www.oro.com/ja/technology/001/)
[Oracle] Reconfigurationの長時間化

## 前提
本事象が発生した環境は以下です。
・Oracle 19c
・Oracle RAC構成(DataGuard構成)

## Reconfigurationとは
RAC構成の場合、インスタンス障害が発生すると、
各インスタンスの整合性を確保するためにreconfigurationという動作を内部的に実行します。
reconfiguration中は全ての処理が待ち状態となり、実質DBへの全断が発生してしまいます。

## 背景
金融系のシステム開発案件にて、障害試験を実施中にORA-01013が発生。
ORA-01013はタイムアウト発生に関するエラーで、reconfigurationによる待機が約150秒ほど発生していました。
アプリケーションのタイムアウト値を10秒に設定していたため、10秒以内に抑える必要がありました。
業務影響がかなり大きいため、緊急度/重要度がMAXでした。

## 解決方法
oracleサポートからの回答も頼りに、実施した解決策は2つあります。
(1) 隠しパラメータ _lm_ticketsを5000に変更
(2)インターコネクトで使用しているMTUを9000に変更

(1)
LMSという、キャッシュフュージョンに関するバックグラウンドプロセスが使用するパラメータ。
デフォルト設定は1000です。
トレースファイルから、このlm_ticketsが足りていないというメッセージが出ているとのことで、5000に値を変更しました。

(2)
インスタンス間で同期を取るために使用してるネットワーク線の帯域が小さい値(1500)だったことが原因だったので、9000に変更しました。

今回の事象はこちらが大きな原因だったと思いますが、、、
アラートログやトレースファイルから、UDPのパケットロスが発生していることが確認できていました。
ただしネットワーク機器(L3スイッチ)からのエラーは確認できていなかったと記憶しています。
MTUの値が小さすぎると、UDPパケットはMTUサイズに合うよう細かくパケットを分割して再送する動きをします。
このUDPパケット送付にかなりの時間がかかっていたようです。
ちなみに、Oracleの推奨値は9000のようでした。(それなら構築の段階で反映しておいてほしかった・・・)

## まとめ
reconfigurationが長時間化してしまう場合は、
(1)Oracle隠しパラメータである_lm_ticketsの値を見直してみる
(2)インターコネクトで使用しているMTUサイズを大きくしてみる
を試してみると解消されるかもしれません。

振り返ってみると当たり前だな、と思えるのですが、当時はかなり難航していました。
とても苦い思い出です。
いろんなブログを漁っても情報があまり出てこなかったので、もし同じような事象に困っている人がいたら参考にしてみてください。
Vue.jsのライフサイクルフック一覧

Vue.jsのライフサイクルフック
Vue.jsには、コンポーネントが生成される際に自動的に実行されるライフサイクルフックがあります。以下に、Vue.jsのライフサイクルフックの種類と、それぞれが実行されるタイミングを紹介します。

beforeCreate

Vueインスタンスが生成される前に呼び出されます。

created

Vueインスタンスが生成された後に呼び出されます。このフックでは、データの初期化やコンポーネントの設定などが行われます。

beforeMount

Vueインスタンスがマウントされる前に呼び出されます。このフックでは、テンプレートがコンパイルされ、DOMツリーに挿入される前の処理が行われます。

mounted

Vueインスタンスがマウントされた後に呼び出されます。このフックでは、DOMにアクセスできるようになり、DOM要素を変更することができます。

beforeUpdate

Vueインスタンスが更新される前に呼び出されます。このフックでは、データの変更前の処理を行うことができます。

updated

Vueインスタンスが更新された後に呼び出されます。このフックでは、DOMが更新された後に行いたい処理を行うことができます。

beforeDestroy

Vueインスタンスが破棄される前に呼び出されます。このフックでは、インスタンスを破棄する前の処理を行うことができます。

destroyed

Vueインスタンスが破棄された後に呼び出されます。このフックでは、インスタンスが破棄された後の処理を行うことができます。

これらのライフサイクルフックを使用することで、Vue.jsコンポーネントの生成、更新、削除のタイミングでカスタムの処理を実行することができます。
相手に質問や相談の内容が伝わるチャットテンプレート


こんにちは。

今回も読んでいただきありがとうございます。

社会人になって当たり前のようにリモートワークをするなか、
なければ死活問題となるものがあります。

それがチャットツールです。
ChatWorkやslackが主なチャットツールでしょうか。

人によっては毎秒チャットに文字を打ち込んでいる方もいるかと思います。
それほどチャットの仕事への影響力は高く、チャットの文章がへたくそだと
仕事が出来ない人間だと思われても仕方ありません。

私が入社したての頃は文章の作り方がへたくそで、
全く相手に伝わる文章が作れませんでした。

そのせいで上司からは質問を質問で返されてしまったり、
もっとわかりやすく伝えてくださいと言われる始末。

「これなら伝わると思って書いているんだけどなぁ。。。」

そう思う日々でした。


そんなモヤモヤした日々を過ごす中、
質問や相談時にあるテンプレートを使うようになってから
今まで質問に質問で返されていた文章が
「はい、それでお願いします」や「こちらの方が良いと思います。」と
いったようにすぐに回答をいただけるようになりました。

そのおかげで仕事の効率もあがり、
質問や相談が億劫でなくなりました。


そんなテンプレートを下記に記載しますので、
普段の業務に使ってみてくださいね。


# 相手に質問や相談の内容が伝わるチャットテンプレート

お疲れ様です。
○○の件について××です。(○○は仕事の具体的内容など)

{質問や相談を記載}

{質問や相談に関して、自分で調べたこと。自分の現状報告。自分の考え}

{締めの言葉。お手数をおかけしますがご回答よろしくお願いいたします。など}


# 少し解説します
たったこれだけです。
簡単そうに見えませんか？
実状は報告内容を考えたり質問を端的に述べることが難しいことが多いのですが、今回はそこまで深堀りしません。


## ××について
××の中に入るのは4つです。
- 質問
- 相談
- 提案
- 共有(報告)

××に入る言葉によって、自分の調べたことや現状報告、自分の考えをどのように記載するかどうかも変わってきます。

- 質問：「～でしょうか？」
- 相談：「～○○の方法についてどうしていきましょうか？」
- 提案：「～○○で進めるのが良いと考えておりますが、いかがでしょうか？」
- 共有(報告)：「現状は以下のようになっております。{以降現状記載}」

## 現状報告について
よくあるビジネス情報発信では短い文章を送れ！と言われがちですが、
現状報告についてはその限りでないと考えています。

短い文章で伝わるならそれに越したことはないですが、
ずっとモヤモヤを抱えながら何十分も調べたことを一言二言で話せるもんなら話してみてほしいです。

出来るだけ状況が伝わるように、事実のみを報告してください。
調べた経緯とか絶対に入れないでください。
質問を受けた人は経緯とかどうでもいいです。
必要なのは分からないことや分かっていること、前提条件です。

次からはそれぞれの一例を挙げていきますので、より具体的なイメージをもって普段の業務に活かしていただければと思います。

# 質問の例

お疲れ様です。
要素2について質問がございます。

要素2の実装でエラーとならないためにはどうすればよろしいでしょうか。

要素1についてこういった仕様だと理解しております。
また、要素2については要素1を踏まえるとこういった仕様だと考えておりますが、
エラーとなってしまいます。

お手数をおかけしますがご教示いただけますと幸いです。


# 相談の例
お疲れ様です。
要素2の実装時間の見積もりについて相談がございます。

過去の経験から、2人日かかると考えております。
ただ見通しのつかない部分があり、そのあたりを重点的に相談させてください。

差し支えなければVCでの相談をお願いいたします。

# 提案の例
お疲れ様です。
要素2の実装方法について提案がございます。

要素2に使われる関数は以下の仕様がございます。
- 仕様1
- 仕様2
- 仕様3

以上の仕様を考えると、実装方法は○○と××の2つが候補に挙がります。
そのうち○○はより保守性があるため、私は○○が良いと考えております。
○○での実装で進めてよろしいでしょうか？

ご検討よろしくお願いいたします。

# 共有(報告)の例
お疲れ様です。
仕事1の進捗について共有です。

仕事1は50%ほど進んでおります。
また、後の業務内容は以前やったことがあり要領をわかっているため、
予定よりも少し前倒しで完了できる見込みです。

ご了承ください。

# おわりに
以上相手に質問や相談の内容が伝わるチャットテンプレートでした。

私自身このテンプレートの一端を知ったのは
YouTubeでよくビジネス情報を発信されている[マコなり社長](https://www.youtube.com/channel/UC7I3QTra4_kC4TSu8f7rHkA)がきっかけです。

どの動画でおっしゃっていたのかまでは覚えていませんが、
よく期待値調整という言葉を使われます。

今回のテンプレートも期待値調整をしています。

質問なのか、相談なのか、共有なのかで聞く人のやるべきことが変わってきます。
質問なら答えなきゃいけないし、相談なら話をより深掘って聞く必要があります。
共有ならリアクションスタンプを送るだけでも良いかもしれませんね。

相手に心づもりをさせるんです。
心づもりをさせるだけでまず驚かれることはほとんどなくなります。

このテンプレートを使って期待値調整をし、
必要最低限の事実を共有することでより正確な行動をしてもらえるようになります。

そうすれば質問された側は返事が楽ですし、質問した人へも正確な解答を出しやすいです。
また、質問した側は改めて自分が認識している状況を俯瞰でき、自分自身で解決策を見出すきっかけになる可能性があります。
そして両方のメリットはお互いの無駄な時間が短縮されることです。

質問する側が少し気を付けるだけでいいことづくめなんです。
これはテンプレートを使うしかありませんよね。

もし現状のままでいいとか、少しでも時間短縮したいと思っていないだとか、
そう思っているのであれば使わない方が良いです。

ただもし現状を変えたいと思っているのであれば、
明日から使ってみるともしかしたらそこから徐々に変わっていくかもしれませんね。
RustのGetメソッドでJSONレスポンスが返ってこなくなった

# はじめに

Rustの学習のために簡単なAPIを作成しているのですが、本を読みながら必要な箇所をコーディングしているなんちゃってで理解を勧めているので、リファクタリングをかけたときに問題が発生したのでまとめます

# 問題

以下のようなコントローラーを作成し、ユーザー一覧を返すAPIを作成しました

```rs:user_controller.rs
pub async fn all_users() -> impl IntoResponse {
	let pool = establish_connection();
	let usecase = UserUseCase::new(UserRepositoryForDb::new(pool));
	let users = usecase.all().await.unwrap();
	(Json(users), StatusCode::OK)
}
```

このメソッドは以前動いておりリファクタリングをかけた(クリーンアーキテクチャにした)ものになります
以下のリクエストをすると本来ならユーザー一覧が返ってきます

```
$ curl localhost:8080/users
```

しかし、なぜか返ってきませんでした。どこかで実装がまちがっているのかとも思いましたが、デバックしたところユーザーは取得できていました

# 解決方法

原因は返却値の順番が逆でした

```rs:user_controller.rs
pub async fn all_users() -> impl IntoResponse {
	let pool = establish_connection();
	let usecase = UserUseCase::new(UserRepositoryForDb::new(pool));
	let users = usecase.all().await.unwrap();
	(StatusCode::OK, Json(users))
}
```

```
$ curl localhost:8080/users

[{"id":1,"name":"test","email":"test@example.com","password":"password"}]
```

IntoResponseは(ステータスコード, レスポンス)の順にする必要があったようです

# 最後に

すごく初歩的なところで躓いているので地道に頑張りたいです