OmniAICreator/Qiita-1.07M huggingface dataset:
PID制御のゲインチューニングについて【初心者向け】

# はじめに
PID制御のゲインの合わせ方について、いくつか種類があるらしいので雑にまとめる。


# ジーグラ・ニコルスの限界感度法

大昔からあるやり方。手順としては以下のような感じ。

**①P制御のみ有効にした状態で、一定の入力をシステムに与える。**

**②Pゲインを小さい値から徐々に大きくしていくと、ある時点で振動が減衰しなくなる。そのときのPゲインをKuとする。そのときの振動周期をTuとする。**

**③あとは以下の表に従って、DゲインとかIゲインを算出する**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/e41facec-3bbf-1ee8-305b-28e10e21d210.png)

ものすごく雑なやり方なので精度は期待できないが、チャチャっとテキトーにゲインを合わせたいときに使用するには丁度いい。


# ジーグラ・ニコルスのステップ応答法
ステップ応答法では以下のような手順でゲイン値を決定する。

①まず、調整器を介さずに制御対象単体にステップ入力を加える。

②↑により得られたステップ応答曲線から、曲線の勾配が最も急なところに接線を引き、その勾配をR=K/T（ここでKは定常ゲイン、Tは時定数）とする。

③この接線が横軸（時間軸）と交わる時刻と入力を加えた時刻との差を取り、この時間をLとする。

④これらの値から調節器の各パラメータを下の表のように決める。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3700895/a31586bb-1ad3-3ada-8317-51e36ff3767d.png)


# 一般的なPID制御ゲインチューニング
そもそも一般的にPID制御のゲインのチューニングをどうやっているかというと、以下のような感じ。

**①制御器の構造を決める**
P,I,Dのどの項を使用するかを決める。

**②制御ゲインの適切な大きさを求める**
システムの能力を過不足なく引き出すために、制御ゲインの適切な大きさを逆算する。

**③ステップ目標値に対してゲインチューニングする**
基本となるPゲインを設定し、Dゲインで振動を抑制し、Iゲインで定常偏差を抑制する。

**④目標軌道があれば、それに対してゲインを微調整する**
制御性能を確認しながら、ゲインを微調整していきます。

【ゲインを微調整する際の観点】
　・システムの安定性
　・追従精度
　・応答速度
　・オーバーシュート・アンダーシュートの有無
　・外乱への感度
　・特性変動への感度



# おわりに
今回は、PIDの制御ゲインのチューニング方法について、初心者向けにまとめてみた。
ステップ応答法とかは、正直自分もあんまり分かってなかったので、勉強になりました。
他にもいろいろゲインチューニング法があるらしい（CHR法とか）。そのうち調べてまとめたい。


# 参考文献

https://controlabo.com/pid-gain-tuning/#toc8

https://controlabo.com/ultimate-sensitivity-method/#toc12

https://ja.wikipedia.org/wiki/PID%E5%88%B6%E5%BE%A1

https://controlabo.com/control-performance/
XMLHttpRequest・Fetchを使用し、API通信する際での詰まった事＋解決策

# エラー内容
- CORS(ブラウザのポリシーで異なるオリジンへのアクセスを許可するもの)

# 解決策
- アクセスを受ける側(サーバ)に、レスポンスへのAccess-Control-Allow-Originヘッダを付与する設定

# 具体的に
- PHPのクロスオリジンリソース(CORS)制約を緩和するHTTPヘッダー
  - 異なるオリジンからHTTPリクエスト受取りが出来る

# 注意点
- 本番などでは""は一般的では無い(セキュリティを確保するには後者)
  - header("Access-Control-Allow-Origin:"); // すべてのオリジンからのリクエストを許可
  - header("Access-Control-Allow-Origin: {特定のオリジン}"); //ドメインやIPアドレスなど
ヤコビ行列やヘッセ行列と Python

# はじめに

ヤコビ行列やヘッセ行列を計算してくれるライブラリを紹介します。

今回は以下の関数を議論します。
$$ f(x_0,x_1) = \frac{\log x_0}{x_0^2} + \frac{x_1^2}{37} - \frac{x_1}{7}
,x_0=2,x_1=2$$

# SciPy

SciPy にはヤコビ行列を求める関数はありましたが、ヘッセ行列を計算する関数はありませんでした。

```py: scipy.optimize
import numpy as np
from scipy.optimize import approx_fprime

def f(x):
    return np.log(x[0])/(x[0]**2) + (x[1]**2)/37 - x[1]/7

x = np.array([2.0, 2.0])
jac = approx_fprime(x, f)
print(jac)
```

https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.approx_fprime.html

# SymPy

SymPy ではヤコビ行列やヘッセ行列を関数の形で出力できるので検算などには便利です。（今回はしませんが。）

```py: sympy
import sympy as sp

x0, x1 = sp.symbols('x0 x1')
f = sp.log(x0)/(x0**2) + (x1**2)/37 - x1/7

jac_expr = sp.Matrix([f]).jacobian([x0, x1])
jac_func = sp.lambdify((x0, x1), jac_expr)
jac = jac_func(2.0, 2.0)
print(jac)

hess_expr = sp.hessian(f, [x0, x1])
hess_func = sp.lambdify((x0, x1), hess_expr)
hess = hess_func(2.0, 2.0)
print(hess)
```

# PyTorch

`jacfwd` の代わりに `jacrev` を使っても構いません。

```py: torch.func
import torch
from torch.func import hessian, jacfwd

def f(x):
    return torch.log(x[0])/(x[0]**2) + (x[1]**2)/37 - x[1]/7

x = torch.tensor([2.0, 2.0])

jac_func = jacfwd(f)
jac = jac_func(x)
print(jac)

hess_func = hessian(f)
hess = hess_func(x)
print(hess)
```

https://pytorch.org/docs/stable/generated/torch.func.jacrev.html#torch.func.jacrev

https://pytorch.org/docs/stable/generated/torch.func.jacfwd.html#torch.func.jacfwd

https://pytorch.org/docs/stable/generated/torch.func.hessian.html

```py: torch.autograd.functional
import torch
from torch.autograd.functional import hessian, jacobian

def f(x):
    return torch.log(x[0])/(x[0]**2) + (x[1]**2)/37 - x[1]/7

x = torch.tensor([2.0, 2.0])

jac = jacobian(f, x)
print(jac)

hess = hessian(f, x)
print(hess)
```

https://pytorch.org/docs/stable/generated/torch.autograd.functional.jacobian.html#torch.autograd.functional.jacobian

https://pytorch.org/docs/stable/generated/torch.autograd.functional.hessian.html

# AutoGrade

今はあまり開発は活発ではないようです。

```py: autograd
import autograd.numpy as np
from autograd import jacobian, hessian

def f(x):
    return np.log(x[0])/(x[0]**2) + (x[1]**2)/37 - x[1]/7

x = np.array([2.0, 2.0])

jac_func = jacobian(f)
jac = jac_func(x)
print(jac)

hess_func = hessian(f)
hess = hess_func(x)
print(hess)
```
ABC350回答メモ

# 0.はじめに
　AtCoderJobsの名前を冠したコンテスト。
 とはいえ普通の内容でしたが、若干難易度が高く感じました。
 調子が悪かったためかもしれませんが・・。
　結局A~Cまでしか解けず、レートも-19で905にダウン。
 最近は安泰と思ってた900台も危うくなってきました。
 

# 1.A - Past ABCs
　ABC316が開催されなかったことを使った、ちょっとだけひねった問題。
 作り終わった後に前半部分はABCであるチェックが不要なことに気づきましたが
 まぁいっかとそのまま提出してACでした。

　https://atcoder.jp/contests/abc350/submissions/52551354


# 2.B - Dentist Aoki
　たまに見かける猟奇的な設定の問題。
  歯の場所ごとにフラグリストを持って置き
  最初はON、リストに現れたらON、OFFを切替
  最後にフラグリストを集計して表示すればOKでした。

　https://atcoder.jp/contests/abc350/submissions/52559135


# 3.C - Sort
　C問題にしては難しく感じた問題。
 解答方針はすぐに決まりましたが、実装時にこんがらがってしまい
 時間がかかりました。
 【考え方】
 　・N-1回までの操作は許されているので、Aの1個目の値と
  A内の1の場所を交換、Aの2個目の値とA内の2の場所を交換・・・
  としていけば整う。
 　・高速化するために、Aのリストと別に、キーにリストA内の値
  値にリストA内の位置を持った辞書を用意し、交換すべき位置を
  高速で求めるとともに、交換後の値で辞書を書き換えN-1回の操作を
  軽くする。

　一回実装してしまえば、後はすんなりいきました。

　https://atcoder.jp/contests/abc350/submissions/52593619


以上
今日のQiitaError: 502 Bad Gateway and 404 Not Found

https://qiita.com/official-events/06e1e6af790c81a75b7f?page=2

に参加しようとした。

<この項は書きかけです。順次追記します。>
This article is not completed. I will add some words in order.

# 今日のQiitaError

![2024-04-21 8.01の画像.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/73a1307b-aa42-a373-bd53-f535fb71c5bf.jpeg)

が出て表示しない。

メールしたら、URLを送れという。

自分のHomeを表示しようとしても、件数の多いタグを表示しようとしても出る。

Safariで接続しようとしても、Chromeで接続しようとしても出る。

URLを送れって、QiitaのLogに残っていないの？ってなる。
どこか、ログが見えない会社に仕事丸投げしてるのか？ってなる。

Qiita に　loginせずに表示すれば表示する。URL送ってもいみないじゃんってなる。

![2024-04-21 8.02の画像.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/75e06eb6-683c-1462-720b-e35ab888cae4.jpeg)

そこで、このページのソースを見てみる。

```browser:html
<div class="style-1kkt86i">
<button class="style-cpmm81">参加する</button>
<p class="style-hl9vr4">参加ボタンを押されたら、<a href='https://qiita.com/official-event-terms/post-event' target='_blank'>利用規約</a>に同意したものとみなします。</p>
<p class="style-lbcigw">参加するためにはログインする必要があります</p></div>
```

参加する　ボタンを押すと、

```browser:html
https://qiita.com/official-event-terms/post-event' target='_blank
```
を送ることがわかった。

そこで、ログインしているブラウザのURL欄に切りはりすると、

![2024-04-21 8.00の画像.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/57ac8320-cef5-2431-b555-48dbecbbba3f.jpeg)

が出る。あれ？って思って、URL欄を見ると、


```browser:html
https://qiita.com/official-event-terms/post-event'%20target='_blank
```

「%20」を「 」に変えても同じだった。残念

＜この記事は個人の過去の経験に基づく個人の感想です。現在所属する組織、業務とは関係がありません。＞
This article is an individual impression based on the individual's experience. It has nothing to do with the organization or business to which I currently belong.


# 文書履歴(document history)
ver. 0.01 初稿 　20240421
### 最後までおよみいただきありがとうございました。
いいね　💚、フォローをお願いします。
#### Thank you very much for reading to the last sentence.
Please press the like icon 💚　and follow me for your happy life.
Fedora39でminikube - LoadBalancerをDeployする(1)

[Fedora39でminikube - ServiceをDeployする(1)](https://qiita.com/intrajp/items/a284f4fb87fb990e520c)からの続きです。

```BASH
@fedora:~$ kubectl create deployment balanced --image=kicbase/echo-server:1.0
deployment.apps/balanced created

@fedora:~$ kubectl expose deployment balanced --type=LoadBalancer --port=8080
service/balanced exposed
```

別のターミナルで、minikube tunnel コマンドを実行する必要があります。

```BASH
@fedora:~$ minikube tunnel
Status:	
	machine: minikube
	pid: 12380
	route: 10.96.0.0/12 -> 192.168.59.100
	minikube: Running
	services: [balanced]
    errors: 
		minikube: no errors
		router: no errors
		loadbalancer emulator: no errors
```

```BASH
@fedora:~$ kubectl get services balanced
NAME       TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
balanced   LoadBalancer   10.103.205.63   10.103.205.63   8080:31218/TCP   5m10s
```

ブラウザで、10.103.205.63:8080 にアクセスします。

```
Request served by balanced-dc9897bb7-nj2x4

HTTP/1.1 GET /

Host: 10.103.205.63:8080
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: ja,en-US;q=0.7,en;q=0.3
Connection: keep-alive
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:125.0) Gecko/20100101 Firefox/125.0
```

(参考)[minikube start](https://minikube.sigs.k8s.io/docs/start/)

[Fedora39でminikube - IngressをDeployする(1)](https://qiita.com/intrajp/items/89eeacddf0a62ac1baf1)につづく。
waymo open datasetのdownload

# 概要
waymo open datasetのDownloadのしかたのメモ


# gcloudのsetup
```
sudo apt-get install apt-transport-https ca-certificates gnupg curl
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /usr/share/keyrings/cloud.google.gpg
echo "deb [signed-by=/usr/share/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main" | sudo tee -a /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt-get update && sudo apt-get install google-cloud-cli
gcloud init
```

# Download Data
trainingとevaluationのデータが大き過ぎたので、取り敢えずtest data(9.6 GiB)をDownload
```
gsutil -m cp -r \
  "gs://waymo_open_dataset_v_2_0_1/testing" \
  .
```

# Reference
[waymo open dataset gloud](https://console.cloud.google.com/storage/browser/waymo_open_dataset_v_2_0_1?pageState=(%22StorageObjectListTable%22:(%22f%22:%22%255B%255D%22))&prefix=&forceOnObjectsSortingFiltering=false
)

[waymo open dataset website](https://waymo.com/open/download/)
【R】library関数に変数を渡すときの注意点

※`install.packages()`は普通に変数参照で実行できることが判明したため記載見直しました。申し訳ありません。（2024.05.03）

# TL;DR
~~`install.packages()`~~, `library()`の引数に変数を渡したい場合、`character.only=TRUE`オプションが必要

# 経緯
- インストール済のパッケージに対して`install.packages()`したときに例外吐くのがなんか嫌なので、インストール済のパッケージはインストールを飛ばすようにしたい
- パッケージ名のベクトルを作って、`install.packages()`に変数でパッケージ名を渡してやればいいはず
- ついでに`library()`で読み込む関数もベクトルで管理できるとイケてるよね
- 以下で実装
```R:hoge.R
# インストールしたいパッケージのベクトルを作る
required_packages <- c("dplyr", "jsonlite")
installed_packages <- rownames(installed.packages())
missing_packages <- required_packages[!(required_packages %in% installed_packages)]

# インストール
sapply(missing_packages, function(p){
  install.packages(p)
})
sapply(required_packages, function(p){
  library(p)
})
```
# 問題
以下の例外が発生。
変数の中身じゃなくて変数名が解釈されてる！？！？！？
```R:Console
> library(p)
library(p) でエラー:  ‘p’ という名前のパッケージはありません
```

# 対策
`library`関数に`character.only=TRUE`オプションが必要
```R:hoge.R
library(p, character.only = TRUE)
```
# 原因
こういう仕様です、としか言いようがない…

実装も読みつつ諸々調べたが、渡された引数`p`はデフォルトだと解析はされるが式として評価されない実装になっている模様。

この実装だと何が嬉しいのかは全く理解できてない。今後の課題ですね。。。

※参考：[library()関数の該当箇所実装](https://github.com/SurajGupta/r-source/blob/a28e609e72ed7c47f6ddfbb86c85279a0750f0b7/src/library/base/R/library.R#L238-L239)

# 余談
`install.packages()`関数のお話。

これ書くためにドキュメント読んでて初めて知ったこと。
**`install.packages()`に限り**、引数にはベクトルを渡せるらしい。
つまり`apply`なんか嚙ませなくても以下の一発でいける。マジかよ。。。
```R:hoge.R
install.packages(missing_packages)

```

# 感想
Rのこういう他言語の常識を平気で裏切ってくるところ結構好きだったりはします。

# 参考資料
- RDocumentation
  - https://www.rdocumentation.org/packages/utils/versions/3.6.2/topics/install.packages
  - https://www.rdocumentation.org/packages/base/versions/3.6.2/topics/library
cscの作法 その496

# 概要
cscの作法、調べてみた。
Tetris&Breakoutを、見つけたので、コンパイルしてみた。

# 参考にしたページ

https://github.com/hunya11/Tetris-Breakout

# 写真

![スクリーンショット 2024-04-21 055232.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/edf36d6c-319f-6a4c-9e0d-ae983b1495f3.png)
![スクリーンショット 2024-04-21 055209.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/18104/e8c8ea7b-7e99-0d2a-fb92-95e4f1d01749.png)

# 環境
windows11

# コンパイル手順

```
>set PATH=C:\Windows\Microsoft.NET\Framework\v4.0.30319;%PATH%

>cd csc\Tetris-Breakout-master\Tetris-Breakout-master\DXlib_CS\DXlib_CS

>csc /out:teto.exe src\Color.cs src\Comp\DifficultyAI.cs src\Comp\DrawComp\DrawableComponent.cs src\Comp\Component.cs src\Comp\DrawComp\Image\DxImage.cs src\Comp\DrawComp\Image\ImageBox.cs src\Comp\DrawComp\Image\ImageCircle.cs src\Comp\DrawComp\Image\ImageObject.cs src\Comp\DrawComp\Object\Ball.cs src\Comp\DrawComp\Object\Bar.cs src\Comp\DrawComp\Object\Block.cs src\Comp\DrawComp\Object\Effect\EffectBreakBlock.cs src\Comp\DrawComp\Object\GameObject.cs src\Comp\DrawComp\Pages\PageAImode.cs src\Comp\DrawComp\Pages\PageGame.cs src\Comp\DrawComp\Pages\PageTitle.cs src\Comp\Tetrimino.cs src\Difficulty.cs src\DxDLL.cs src\FPSTimer.cs src\Frame.cs src\Comp\Key.cs src\Hit.cs src\IniFileHandler.cs src\main.cs src\Comp\DrawComp\Pages\Page.cs  /r:C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\UIAutomationClient\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationClient.dll /r:C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\UIAutomationProvider\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationProvider.dll /r:C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\UIAutomationTypes\v4.0_4.0.0.0__31bf3856ad364e35\UIAutomationTypes.dll /r:C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\WindowsBase\v4.0_4.0.0.0__31bf3856ad364e35\WindowsBase.dll

>teto



```


以上。
AWSにDjangoの環境を整えていく_目次

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

この記事は自分が連載(?)している『AWSにDjango環境を様々なAWSサービスを使ってデプロイする』という記事をまとめた記事となります。

GCPでも似たことをやってますので、参考までに・・・

https://qiita.com/ohtsuka-shota/items/af5808995a0a5b9fc9df

# 目次
## 1）AWSにDjangoの環境を整えていく01(VPC/subnet/IGW/RouteTable/SG/EC2)
### 記事

https://qiita.com/ohtsuka-shota/items/347bf23fdfeafb542255

### 関連
CloudFormation用のyamlは以下のGitHubにあります。

https://github.com/ohtsuka-shota/aws-django/blob/main/django01_all.yaml

## 2）AWSにDjangoの環境を整えていく02(RDS)
### 記事

https://qiita.com/ohtsuka-shota/items/3395d70488cf777ac7a7

### 関連
GitHub作成予定

## 3）AWSにDjangoの環境を整えていく03(ALB)
### 記事

https://qiita.com/ohtsuka-shota/items/da72670d0157a9e537bd

### 関連
GitHub作成予定

## 4）AWSにDjangoの環境を整えていく04(CloudFront)
### 記事
https://qiita.com/ohtsuka-shota/items/434198a543dcdadb94cd

### 関連
GitHub作成予定


## その他）AWSにDjango環境を整えていく_CloudFormation編

https://qiita.com/ohtsuka-shota/items/7e4358186613f8ebbc8e



---
今後も更新予定
AWSにDjango環境を整えていく_CloudFormation編

こんにちは。
株式会社クラスアクト インフラストラクチャ事業部の大塚です。

今回はAWSのCloudFormationについてとなります。
2024年4月現在、AWSにDjango環境を作るという名目でAWSのサービスを鋭意触っております。
折角なら手動で作成した環境をCloudFormationを使って、一発でデプロイできるようにしよう、という事で用意したコードをここにまとめておきます。

親記事は以下になります。

https://qiita.com/ohtsuka-shota/items/4b80538569b81f8c19a6

# CloudFormationを使った環境デプロイ手順
まず、AWS管理コンソールからCloudFormation管理画面に移動指定下さい。
スタックタブを押下するとデフォルトだとスタック無しという表示がされているかと思います。スタックの作成を押下してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/cec77824-b590-7fb7-4da1-e3b59ca199bd.png)

以下の画面に遷移します。
- テンプレートの準備：既存のテンプレートを選択
- テンプレートソース：テンプレートのアップロード

と選択し、ファイル選択で作成したyamlを指定します。
構文エラーなどはここで行われ、発見されるとエラーを返されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/bb368a34-4d0d-527a-a787-0e52abd80840.png)
スタックの名前を聞かれます。ここは任意のものでOKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/8d03f122-a3dd-824e-6ff5-fc1ad47b0ef6.png)
スタックのオプションを問われます。基本デフォルトのまま次に進みます。
![screencapture-ap-northeast-1-console-aws-amazon-cloudformation-home-2024-04-20-22_41_37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/378e3dec-13da-8d2a-0219-53bfd2d4495f.png)
確認画面が表示されます。ざっと確認して送信を押下します。
![screencapture-ap-northeast-1-console-aws-amazon-cloudformation-home-2024-04-20-22_42_07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/3ad1ce80-8e7f-00f6-889e-724eb49feb58.png)
画面が遷移します。しばらく待つとリソースタブに作成したyamlからデプロイされたリソースを確認することが出来ます。デプロイされたリソースは各リンクから確認しに行くことが可能で、かつ通常の画面からも確認が出来ます。
また、CloudFormationでデプロイした環境は、この画面からスタック単位でまとめて削除することが可能です。便利ですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/59ef8f59-e8bf-673f-294b-aa9678a18d83.png)

以下のようなイメージですね。
![島田様01-ページ34.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3219385/b4cd209b-9c1e-d1fa-897b-1762b50705e7.png)


# CloudFormationで使用するyaml
## AWSにDjangoの環境を整えていく01(VPC/subnet/IGW/RouteTable/SG/EC2)
以下記事の環境構築について

https://qiita.com/ohtsuka-shota/items/347bf23fdfeafb542255

yamlはこちらになります。

https://github.com/ohtsuka-shota/aws-django/blob/main/django01_all.yaml

## 今後更新予定
Storybookで書いたテストをコマンドで実行する方法

# はじめに

初めまして。エンジニアのkeita_Maxです。

Storybookで書いたテストをGitHubActionsとかで使用するために、コマンドで実行したいということでやり方を調べました。

# ライブラリインストールと設定

まずコマンドで実行するためにライブラリをインストールします。
以下のコマンドでインストールして下さい。

```
npm i -D @storybook/test-runner @storybook/jest
```

package.jsonのscriptsに以下を追記します。

```json:package.json
    "storybook": "storybook dev -p 6006",
    "test-storybook":"test-storybook --url http://localhost:6006",
```

# テストコードについて

テストコードについては以前記事で紹介したのでこちらを参考にしてください。

https://qiita.com/keitaMax/items/bdabc2b6f1435c503547

https://qiita.com/keitaMax/items/64b3956775ac83959bdf


# 実行する

まず、以下コマンドでStorybookを立ち上げます。
```
npm run storybook
```

次に以下のコマンドでテストを実行します。
```
npm run test-storybook 
```

するとテストが走り、以下のように結果が出てきます。

```
Test Suites: 8 passed, 8 total
Tests:       8 passed, 8 total
Snapshots:   0 total
Time:        5.808 s
Ran all test suites.
```

これでコマンドでテストができるようになりました。

# さいごに

簡単にStorybookでテストできるようになりました。

やり方が違ったり、もっといいやり方があるというご指摘がある方はコメントしていただけると幸いです。

最後まで読んでいただきありがとうございました。

# 参考

https://qiita.com/kenji7157/items/dab0b587325325cb7b69
Salesforceの環境の中で特定の文字を見つける



+ [特定の文字列がシステム全体のどこで使用されているのかを検索するツールについて](https://trailhead.salesforce.com/trailblazer-community/feed/0D54V00007ajNQ7)

:::note
以下に組織からメタデータの取得という手順が書かれているので参考になると思います。

Visual Studio Code + Salesforce CLIを使用したメタデータのリリース 
https://base.terrasky.co.jp/articles/cHjOB

 メタデータ はxmlフォーマットのテキストファイルなので、あとはUnixの grep、findコマンドなどを使えばファイルの中で使われている単語を検索できると思います。

 ```
 find [検索対象フォルダのパス] -type f -print | xargs grep '[検索したい文字列]'
 ```
 
:::
Pythonで「ファイル名またはディレクトリ名を変更する(pathlibモジュール)」の動作を確認してみた

# 概要

Pythonで「ファイル名またはディレクトリ名を変更する(pathlibモジュール)」の動作を確認してみました。
以下のページを参考にしました。

https://www.javadrive.jp/python/file/index17.html

# 実装

以下のファイルを作成しました。
```sample.py
import pathlib

oldpath = pathlib.Path('./test/book.txt')
oldpath.rename(pathlib.Path('./test/memo.txt'))

oldpath = pathlib.Path('./test/back')
oldpath.rename(pathlib.Path('./test/old'))
```

以下のコマンドを実行しました。
```
$ mkdir test
$ touch test/book.txt
$ mkdir test/back
$ ls test
back  book.txt
$ python3 sample.py 
$ ls test
memo.txt  old
```

# まとめ

何かの役に立てばと。
「脱Git初心者」一歩差が出るgitconfigの設定

# 有用なgit config

## はじめに
[So You Think You Know Git 2024](https://www.youtube.com/watch?v=aolI_Rz0ZqY&list=LL&index=10)をみてgitconfigの設定をいじることでかなり生産性が上げられそうだなと感じたので紹介されていたものを自分なりに取り入れてみたので防備録代わりに投稿します。
******

## よく使う基本の設定
この辺はみんなやっていると思うので詳細は割愛。

```shell
username="sigma"
usermail="example@gmail.com"
git config --global user.name "${username}"
git config --global user.email "${uesremail}"

git config --global color.ui auto
git config --global core.editor vim # コミットメッセージの修正に使うエディタをvimにする
git config --global core.ignorecase false # ファイル名の大文字小文字の変化を検知できるようにする。
```
******


## stash実行時にstash --allが実行されるようになる
- stash --allはすべての変更を一時的なスタッシュに保存する。

```shell
git config --global alias.staash 'stash --all'
```
******


## git bbでカスタムスクリプトを実行させる

1. [better-branch.sh](https://gist.github.com/schacon/e9e743dee2e92db9a464619b99e94eff)をコピペして~/initialsetting/配下に保存
2. config追加。

```shell
git config --global alias.bb '!/home/tomita/initialsetting/better-branch.sh'
```
******


## 解決したことのあるコンフリクトを記録して自動で解消されるようになる。

```shell
git config --global rerere.enabled true
```
******


## git branchの結果を複数行にする
- git branch実行時にgit branch --columnが実行されるようにする。

```shell
git config --global column.ui auto
```
******


## ツリーの生成を早くする。

```shell
git config --global fetch.writeCommitGraph true
git log --graph --oneline
```
******


## git maintenanceを使う
- gitは到達不可能オブジェクトを削除する等のガーベジコレクションを行っているがこれはコマンドを実行するタイミングである。
- 大規模プロジェクトでは時間がとられる可能性があるので定期的にgcするようにする。
> [git maintenance](https://adsholoko.me/blog/get-to-speed-up-to-git/)

```shell
git maintenance start # 特定のリポジトリに対するメンテナンスを実行する。
```


## rebase時に自動で編集中のファイルをstashする。
- rebase時に自動でstashしてくれる。

```shell
git config --global rebase.autoStash true
```
******


## 自動でfixupされるようにする

```shell
git config --global rebase.autosquash true
```

```shell
git commit -m "test" --fixup=HEAD # fixup!がついたコミットを生成
git rebase -i HEAD~2 # fixupがついたコミットを自動でfixupにする
```
> [!WARNING]
> git rebaseするまではfixupのタグがついたコミットになるだけなのでrebaseすること。
******


## push --force-with-leaseのエイリアス

```shell
git config --global alias.pushf 'push --force-with-lease'
```

```shell
# 使い方
git pushf -u origin main
```
******


## ファイルシステムのモニタを早くする(大規模プロジェクトで役に立つシリーズ)

- gitはファイルシステムから直接未追跡ファイルの情報を問い合わせるため，大規模プロジェクトでは`git status`するだけで時間がかかることがある。
- ファイルの更新をローカルでキャッシュしておくことで動作を早くできる

```shell
git config core.untrackedCache true

# ファイルシステムの監視を利用してファイルの変更をリアルタイム検出できる。大規模プロジェクトで役立つ。
git config core.fsmonitor true
```
******
AWS CLI を活用する方法まとめ


## AWS　CLIを利用する方法
CLIを利用する方法としては主に3つあります。

・ローカルPCにCLIをインストールする
・CloudShell
・Cloud9

CloudShellとCloud9は最初からCLIがインストールされています。アクセス許可はコンソールログインのIAMユーザーの権限で認証されます。
※Cloud9はIAMユーザーやロールが作成できないなどの一部制限があります。

ローカルPCからCLIを利用するには、CLIをインストールした後に、「aws configure」コマンドを実行してアクセスキー、シークレットアクセスキーを設定する必要があります。

## AWS CLIの基本構文

```
aws ec2 run-instances <パラメータ/オプション>
```
上記のCLIコマンドを例に基本構文を解説していきます。

①aws
こちらは固定となります。最初の書き出しはawsと記述します。
②ec2
awsあとの2つ目の要素にサービス名を記述します。
③run-instances
3つ目の要素に実行する操作を記述します。
④　<パラメータ/オプション>
③で実行する操作に必要なパラメータやオプションを指定します。


②のサービス名や③の実行する操作や④パラメータ/オプションは「AWS CLI Command Reference」にまとまっています。
こちらのリファレンスを参照しながらCLIコマンドを実行することになります。

以下AWS CLI Command Referenceのリンク

https://awscli.amazonaws.com/v2/documentation/api/latest/index.html


## よく活用するオプション
### --filters
出力結果を絞り込むときに利用するオプションです。
Name=キー,Values=値　で指定します。
SQLのWHERE句に近いです。＆条件で検索するときはスペースで区切ります。
valuesに書く値をカンマで区切って複数指定することもできます。
フィルターに指定できる項目はリファレンスかhelpの--filtersで確認します。

### --query
出力項目を絞り込むときに利用するオプションです。
SQLのSELECT句でカラム指定する感覚に近いです。
--queryに続いてjmespathで出力を項目を指定します。

https://jmespath.org/

### --output
JSON、TEXT、Table,YAML　のどの形式で出力するかを選択できる。省略した場合はjsonまたはaws configureで指定した形式で出力する。

参考記事

https://dev.classmethod.jp/articles/aws-cli-filter-and-query-howto/

https://qiita.com/empty948/items/e480bca687052d447538
達人に学ぶDB設計徹底指南書 第1章 要約

達人に学ぶDB設計徹底指南書の第1章を要約してみました

# この記事を書いた人
https://twitter.com/noobmental456

# はじめに
- 本書は、リレーショナルデータベースにおける設計について説明
- データベース設計は大まかに３種類に分かれる
    - 論理設計（正規化やER図といった道具を使ったデータのモデル設計）
    - 物理設計（サーバやストレージといった物理的なハードウェアレベルの設計）
    - 実装設計（具体的な構築の手順や方法）
- 論理設計と物理設計にはトレードオフの関係がある

# 1-1 システムとデータベース
- データベースとはデータの集まりを指すために使われる言葉で、そのデータベースを管理するためのシステムを「DBMS（Database Management System）」と呼ぶ
- データベースは多くの所で使われている（Youtube、Amazonなどなど)。データベースを使わないシステムは、この世に存在しない

# 1-2 データベースのあれこれ
- データベースの代表的なモデル（構造/仕様）は何種類かある
    - リレーショナルデータベース（Relational Database：RDB）
        - 現在最も広く利用されるデータベース
        - 特徴は、データを人間が理解しやすい二次元表の形式で管理できるため、データの取り扱いが他のデータベースに比べて直感的。本書ではRDBについて解説している
| 名前 | 住まい | 業種 |
            |:-:|:-:|:-:|
            | 五条 |  東京 | 先生 |
            | エレン  |  エルディア島 | 兵士 | 
    - オブジェクト指向データベース（Object Oriented Database：OODB）
        - このオブジェクトをデータベースに保存するために作られたデータベース
    - XMLデータベース（XML Database：XMLDB）
        - XMLはHTMLのようにタグでデータ管理を行なう言語のこと。このXML形式のデータを扱うことのできるデータベースとして開発されたデータベース
        - RDBが苦手とする階層構造のデータの扱いが得意
    - キー・バリュー型ストア（Key-Value Store：KVS）
        - データをKey（識別キー）とValue（値）の組み合わせだけの単純なデータ型で表現するデータベース
    - 階層型データベース
        - データを階層構造（木構造）で表現するデータベース
        - RDBが流行る前は最も使われていた
- データベースのモデルが変われば本書で学ぶ正規化などの設計方法は異なることに注意する

## DBMSの違いは設計に影響するか？
- RDBにもDBMSがいくつか存在する
    - Oracle Database （オラクル社の製品。最大のシェアを誇る）
    - SQL Server（マイクロソフト社の製品）
    - DB2（マルチプラットフォーム対応）
    - PostgreSQL（オープンソース）
    - MySQL（オラクル社の製品）
- DBMSの違いと設計技法の関係
    - データベースのモデルと違って、DBMSの違いで設計技法を変える必要はない
# 1-3 システム開発の工程と設計
- システム開発の設計工程は以下の工程が順番にある
    - 要件定義（要件を決める工程）
    - 設計（定義された要件を決めるためシステムを設計する。本書の解説はここの部分）
    - 開発（コーディング、ハードウェアの物理的構築も含む）
    - テスト（要件仕様通りに動くか品質を担保する）
- 設計工程と開発モデルの種類
    - ウォーターフォールモデル
    - プロトタイピングモデル（アジャイル開発も含む）
# 設計工程とデータベース
- データベース設計が必要な２つの理由
    - システムが永続的なデータを持つにはデータ設計つまりデータベース設計が必要不可欠
    - データ設計がシステムの品質を左右するため（例えば、データフォーマットが扱いづらい設計にしてしまうとそれだけシステム全体の保守に影響を及ぼしてしまう）
- DOAとPOA
    - 近年のソフトウェア開発では、データ中心アプローチ(DOA)が主流。プログラムを作るよりも初めにデータの設計をする方法論
    - 一方、プログラム中心アプローチ(POA)がある。複数のチームでプログラムから先に作るとデータに不整合が生まれ非効率なため廃れ、現代ではアンチパターンとされている
- 3層スキーマ
    - スキーマとは、データベース設計において、データベースの構造やフォーマットという意味で使われる
    - 外部スキーマとは、システムの利用者であるユーザーから見て、データベースがどのような機能とインタフェースを持っているかを定義するスキーマ
    - 概念スキーマとは、データベースに保持するデータの要素および、データ同士の関係を記述するスキーマ
    - 内部スキーマとは、概念スキーマで定義された論理データモデルを、具体的にどのようにしてDBMS内部に格納するかを定義するスキーマ
- 概念スキーマはなぜ必要なのか？
一見、内部スキーマと外部スキーマだけで充分かのうように思える。しかし、内部スキーマと外部スキーマだけでは、独立性が低くなり、システムが変更に弱くなる。そのため、インターフェース（概念スキーマ）を設けることで、変更に柔軟となる
Xcodeが予期せぬエラーで開かない

### 初めてSwiftでアプリ開発をしようと思ったら、最初の最初でつまづいてしまったので備忘録です...
早速アプリ開発をしてみようと思ったら、
Xcodeを開こうとしても予期せぬエラーで開けない。
何回再起動しても、キャッシュを消しても、
再インストールしても開けない。😇


## 結論

**AppStoreからインストールしたものをアンインストールして、[Developerサイト](https://developer.apple.com/download/all/)からダウンロードしました。**
<br>
うまくいかなくなった原因の究明が、まだできていない
(そして、つまづいてた部分が恥ずかしい)のですが、
経緯は以下のとおりです。

**エラーが起きるまでにしていたこと**

- チームで作業用にGithubと連携しようとしていた
- 既存のプロジェクトの開き方がわからなすぎて多分開くファイルを間違えた。(多分これ。アプリを開くのを許可しますかみたいな確認が何個か来たあと動かなくなった) 


![スクリーンショット 2024-04-21 午前2.30.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626601/dac6e8de-8360-7b69-c34e-e4e9fcfe878e.png)
~~これ絶対ワナでしょ...~~
Xcodeで既存のプロジェクト開く方法ってみんな最初から習得してるんですか...？

Xcodeを開いた後、File → Open Recent → アプリ名.xcodeproj
![スクリーンショット 2024-04-21 午前3.52.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3626601/904a06b9-30e3-7f87-65be-8f174a54201b.png)

</details>


**結論に至った経緯**
調べていく中で、Library/Developer/Xcode/DerivedDataのキャッシュを消しましょう！が何回も出てきたのですが、
```
cd /Library/Developer
ls
```
#### 私のDeveloperフォルダにそもそもXcodeが無い...
AppStoreからうまくインストールできないことがあるみたいです。

とにかく、

[Developerサイト](https://developer.apple.com/download/all/)からインストールしなおしたら、
無事にXcodeフォルダが作られて、とうとうXcodeが開けました！

予期しないエラー、調べると他にもいろんなところで起こっていて、すごく怖い。AppStoreからでも無事インストールできるようになれば楽なのに...🥲

解決策わかる方ぜひ教えてください...
Claris FileMakerのODBC経由で.NET C#のプログラムが落ちる問題

# はじめに
この記事は[Claris FileMaker](https://www.claris.com/ja/filemaker/)でODBCによるデータ操作を検証し、 **うまくいかなかったという事を発見した** 内容となります。

## Claris FileMakerとは
データベース管理とカスタムアプリケーション開発を容易にするための多機能プラットフォームです。
※ AI様より。

# 環境
* FileMaker Pro 2023
* Windows 11 Pro
* Claris FileMaker 2023 向け xDBC クライアントドライバ
* Visual Studio 2022
* .NET8
* C#

# サンプルプログラム

以下のサンプルプログラムでテストしてみました。

``` C#
// ODBCのデータソース名、ユーザー名、パスワードを設定
string connectionString = "DSN=データソース名;UID=ユーザー名;PWD=パスワード";

// ODBC接続を開く
using (OdbcConnection connection = new OdbcConnection(connectionString))
{
    try
    {
        // 接続開始
        connection.Open();

        // SQLクエリ
        string query = "SELECT * FROM \"テーブル名\"";

        // ODBCコマンドの作成
        OdbcCommand command = new OdbcCommand(query, connection);

        // クエリ実行
        using (OdbcDataReader reader = command.ExecuteReader())
        {
            while (reader.Read())
            {
                // ここで、読み取ったデータを表示
                Console.WriteLine(reader[0].ToString()); // ここでエラーになる！
            }
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
    finally
    {
        // 接続を閉じる
        if (connection.State == System.Data.ConnectionState.Open)
        {
            // 接続終了
            connection.Close();
        }
    }
}
```

上記プログラムで **「ここでエラーになる！」** の箇所でExceptionに飛んだ実行結果は下記のものとなります。

### 実行結果

``` StackTrace.Messege
Arithmetic operation resulted in an overflow.
```

``` Exception.StackTrace
at System.IntPtr.ToInt32()
at System.Data.Odbc.SQLLEN.op_Implicit(SQLLEN value)
at System.Data.Odbc.OdbcDataReader.GetSqlType(Int32 i)
at System.Data.Odbc.OdbcDataReader.GetValue(Int32 i)
at System.Data.Odbc.OdbcDataReader.get_Item(Int32 i)
```

## 放置された問題
この問題をネットで調べていると、先人の方が似たような問題に直面している事を発見しました。
11年くらい前から似たような現象があるので.NETで使うのは厳しいのかもしれません。
検証してませんがSelect文は通るのでUpdateやDeleteも成功しそうです。
ただし、Selectの結果が確認できないので、ODBC経由でデータ操作をするのは難しいかもしれません。


#### FileMaker ODBC Client Driver 64bit版の不具合
https://community.claris.com/ja/s/question/0D50H00006ezePUSAY/filemaker-odbc-client-driver-64bit%E7%89%88%E3%81%AE%E4%B8%8D%E5%85%B7%E5%90%88


#### There is an error in the syntax of the query
https://community.claris.com/en/s/question/0D53w00005lqrGACAY/there-is-an-error-in-the-syntax-of-the-query



## 解決策
[Claris FileMaker 2023 Data API](https://help.claris.com/ja/data-api-guide/content/index.html)というものがあり、RestAPI経由での連携が主流の様です。
※ ODBC接続は[非推奨](https://community.claris.com/en/s/question/0D53w00005lqrGACAY/there-is-an-error-in-the-syntax-of-the-query)になっているようです。

### 参考
* [FileMaker ODBC Client Driver 64bit版の不具合](https://community.claris.com/ja/s/question/0D50H00006ezePUSAY/filemaker-odbc-client-driver-64bit%E7%89%88%E3%81%AE%E4%B8%8D%E5%85%B7%E5%90%88)
* [There is an error in the syntax of the query](https://community.claris.com/en/s/question/0D53w00005lqrGACAY/there-is-an-error-in-the-syntax-of-the-query)
Springのエラーあれこれ

# はじめに
本記事はSpringプロジェクト開発時に発生した(させた)エラー集です。
エラーメッセージ読めばすぐに解決する内容ばかりになりそうな予感ですが備忘録として記載してこうと思います。

# 開発環境
- バージョン
    - Java17
    - Spring Boot3.0.5
- OS：Ubuntu Desktop
- IDE：Intellij IDEA
- ビルドシステム：Gradle
- テンプレートエンジン：Thymeleaf

# Bean登録漏れ
アプリケーション起動時にエラーが発生する。

コンソールログ
```txt
Parameter 0 of constructor in 【使う側のFQCN】 required a bean of type '【使われる側のFQCN】' that could not be found.


Action:

Consider defining a bean of type '【使われる側のFQCN】' in your configuration.
```
解消方法
使われる側のクラスに@Component相当(@Serviceとか)のアノテーションを付与する。

# Bean取得漏れ
アプリケーション起動は出来る。また、該当の処理が実行されるまでは正常に動く。

エラー内容はブラウザに表示されたエラー内容を以下に抜粋
```txt
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Apr 21 03:41:46 JST 2024
There was an unexpected error (type=Internal Server Error, status=500).
Cannot invoke "【使われる側のFQCN.メソッド名】" because "this.taskService" is null
java.lang.NullPointerException: Cannot invoke "【使われる側のFQCN.メソッド名】" because "this.【使われる側のインスタンスを保持する想定のフィールド名】" is null
```

結局はBeanを取得できてないのでnullオブジェクトのメソッド呼び出しが原因でNullPointerExceptionが発生している。
原因はコンストラクターインジェクションなのにコンストラクタがないとかフィールドインジェクションするつもりが@Autowired書いてないとか。

# テンプレート名のpath記述ミス
404かと思ったが500エラーが出るらしい。
以下ブラウザに表示されたエラー内容を抜粋
```txt
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Apr 21 06:26:39 JST 2024
There was an unexpected error (type=Internal Server Error, status=500).
Error resolving template [【Controllerでreturnしているパス名】], template might not exist or might not be accessible by any of the configured Template Resolvers
org.thymeleaf.exceptions.TemplateInputException: Error resolving template [【Controllerでreturnしているパス名】], template might not exist or might not be accessible by any of the configured Template Resolvers
```

解消方法
templates配下からのパスを拡張子無しで記述(Thymeleafの場合のみ？)

# ハンドラーメソッドにアノテーションつけ忘れ
こちらは想定通りだが404
```txt
Whitelabel Error Page
This application has no explicit mapping for /error, so you are seeing this as a fallback.

Sun Apr 21 06:30:46 JST 2024
There was an unexpected error (type=Not Found, status=404).
No message available
```

解消方法
対象のハンドラーメソッドに@GetMappingなど目的に沿ったアノテーションを付与する。
メソッドチェーン

メソッドチェーンを使用すれば、変数を取らなくて良なり、簡潔にコードを書くことができる。
メソッドチェーンとはメソッドを呼び出した返り値に対して、さらにメソッド呼び出しを行うこと。チェーンを長くしす
ぎると読みにくくなるので改行するなどして工夫する。

```javascript
const array = [1, 10, 3, 7, 6, 9, 5, 8, 2, 4]

// 変数を取った場合
const result = array.filter(value => value <= 5)
result.forEach((result) => console.log(result))
// 1 3 5 2 4

// メソッドチェーンを使用した場合
array.filter(value => value <= 5).forEach((numbers) => console.log(numbers))
// 1 3 5 2 4
```
#### 参考
https://qiita.com/andota05/items/2a0461dc1d6f4e31781f
[Unity]キー押下時の短押しと長押しの分岐をInvoke()で実装する

## 前置き
Unityでキーを押した際、短く押した場合（短押し）と長押しをした場合で処理を分けたい場合があります。

・攻撃キーを短押し：通常攻撃が出る
・攻撃キーを長押し：必殺技が出る

という風。
## 実装例
Invokeによるメソッドが呼び出し中か否かを判定するMonoBehaviour.IsInvoking
(https://docs.unity3d.com/ja/2018.4/ScriptReference/MonoBehaviour.IsInvoking.html)
を利用して作ったもの。↓

</details>

```csharp
float LongPushTime = 0.5f; // 長押しに必要な時間

void Update()
{
    if (Input.GetKeyDown(KeyCode.Space))
    {
        Invoke(nameof(LongPushed), LongPushTime);
    }
    else if (Input.GetKeyUp(KeyCode.Space) && IsInvoking(nameof(LongPushed)))
    {
        CancelInvoke(nameof(LongPushed));
        ShortPushed();
    }
}

void ShortPushed()
{
    /* 短押しアクション */
}

void LongPushed()
{
    /* 長押しアクション */
}
```

メリットとしては、Invokeをタイマー代わりに利用しているので、押下時間を計測するための変数を用意する必要が無い点です。

:::note warn
細かい点として、このコードの場合は
短押しアクションは **キーを離したタイミング** で実行されますが、
長押しアクションは **長押し時間が経過したタイミング** で実行されます。

これは、長押ししている時に最短で長押しアクションが出るようにするためですが、
長押し時も最短ではなく **キーを離したタイミング** で実行させたい場合などには他の方法をお勧めします。

:::

Qiita初記事ですが、ご参考になれば幸いです。
ビルドやデバッグのメモ(組込みC言語)

### ビルドの流れをおさらい
ソースファイル(.cや.h)→コンパイル実行→オブジェクトファイル(.o)、
ライブラリやモジュール(.aや.ld)→リンク実行→実行可能ファイル(.motや.run)
※拡張子は適当

### デバッグ時の心構え
・プログラムを詳細に理解する（フローチャートを用意しておくといい）
・特に非効率なのはプログラムコードを理解しない状態で
　修正してみてはコンパイル実行の繰り返し

### Q1:ビルド実行時、何らかのシンボルが定義されていない系のエラー
→どこの段階でのエラーかをまずは確認する

☆コンパイル段階でのエラーの場合
・タイプミスないか（セミコロン抜け、文字コード、タブ、全角など）
・定義されてないシンボルを参照していないか
・ヘッダーファイルのインクルードが正しくできてるか
・実際のエラーを示す行と問題の行が一致しているとは限らない

☆リンク段階でのエラーの場合
・必要なライブラリやモジュールをリンクできているか
・古いプリコンパイル済みのヘッダーファイルを参照していないか、
　疑わしければリビルド（再コンパイル）する

### Q2:ビルド実行時、ヘッダーファイルが見つからないエラー
・環境変数INCLUDEは適切に設定できているか
・コンパイルオプションの指定は正しいか
・IDE利用中であれば、IDEのプロジェクトの設定は正しいか

### Q3:処理速度が要求を満たしていないとき
・コンパイラの最適化機能で速度優先にする
・配列のループ格納処理をポインタにする
・関数をマクロにできないか検討する
・Cからアセンブラにする（インラインアセンブラもしくはソースファイルごとアセンブラ）
・メモリ定義をレジスタ（register)にする。現場では見たことない
・サイズの小さなデータ型を使う
・シフトを使って計算を速く行う
・短絡評価（演算子の左側の数を評価した段階で式全体の値が
　定まらない時のみ右側を評価）を使う
 
  例：if(func()>3 || x>3) ではなく 、
  　　if(x>3 || func()>3) こう書いておけば、
　　　x>3の時はfuncが呼ばれなくて無駄な処理時間を省ける。

### Q4:どこかでリセットが掛かっているが原因不明のとき
・リセット要因レジスタに条件付きwriteブレークを張り、リセット要因を特定する
☆ハードウェアリセットの場合
・ウォッチドッグがリセットしてるかも（外部、内部どちらかも判別しておく）
・電源ICの仕様を確認する

☆ソフトウェアリセットの場合
・Resetで飛んでくる処理の先頭にブレークを張って、
　止まったときのコールスタック（関数の呼び出し履歴）を確認すると分かることもある
・二分法などを用いてリセット発生させてる処理を特定する
・無限ループに入る→ウォッチドッグがリセットのパターンはよくある
・想定と全然違うところで問題発生してる場合はスタックオーバーフローも疑う

### Q5:デバッガ操作前に事前に知っておきたいこと
・ステップ実行、ステップオーバー実行の違い
・ソフトウェアブレークとハードウェアブレークの違い
・コールスタックの見方
・レジスタの見方
・pc(プログラムカウンタ)で現在番地を操作する

### Q6:デバッガ接続時は問題ないが、デバッガ未接続時のみ問題が発生する
・デバッガではRAMなどのメモリを事前にクリアしており、問題ない挙動になることがある。
・デバッガではウォッチドッグが無効になっており、問題発生しないことも
リーダブルコードの読書記録

## リーダブルコードを読みました
本書には、より良いコードとは短く、見やすく、わかりやすく、誤解のないコードであり、
具体的な実現方法やコードの誤解によって生じた問題の紹介などが記載されている。
概念としては、いつも意識しているものだが、具体的な例は良く迷う事項、
納得できる内容が多かったので、個人のメモとして特に参考になった箇所をまとめる。

## 参考になった点
### ■変数名は誤解がないよう分かりやすく
get→download
send→deliver
find→search
start→launch
make→create
ループイテレータi,j,k→たくさん使う場合はclub_i,member_i,user_iなど
size→size_mb
html→html_utf8
⇒値の単位や属性をつけるとより分かりやすい

### ■関数名なども誤解がないよう分かりやすく
filter→select or exclude
clip→truncate or remove
limit→限界値を含める場合はmin,max
start,stop→指定値を含む場合first,last、終わりを含めない場合begin,end
read_password→これから読み込むneed_password、読み込み済みuser_is_authenticated

### ■コードの美しさ
一貫性があることが重要

### ■制御フローの読みやすさ
不等号の向きは＞になる方が読みやすい
条件式は肯定形を使う
単純な条件を先に書き、複雑な条件は後続に書く
do/whileは読みにくいので避け、whileを使う
関数の最後だけでなく、returnを早く返す
失敗はなるべ早く返すことでネストはできるだけ浅くする
複雑な式はわかりやすい名称の変数に格納することで理解しやすくする

## 書籍情報
リーダブルコード ―より良いコードを書くためのシンプルで実践的なテクニック (Theory in practice)
Dustin Boswell (著), Trevor Foucher (著), 須藤 功平 (解説), 角 征典 (翻訳)
Ubuntuを利用していて最新のカーネルを自前でビルドした際にv4l2loopbackのdkmsがビルドエラーになった場合

# 概要
- Ubuntuを利用している
- カーネルを自前でビルドしてインストールしている
- v4l2loopbackをdkmsで利用している
    - Ubuntu 23.10でのaptでインストールされるバージョンは0.12.7

という場合にLinux Kernel 6.8をインストールした際にdkmsのビルドがエラーになった件の調査と対応となります

## 原因
- Linux Kernel 6.8で `strlcpy()` 関数がなくなった
- v4l2loopback.cで該当の関数を利用している

## 対応
- `strlcpy()` を `strscpy()` で置き換える

(参考)

https://qiita.com/mhiramat/items/e5c3218c776f6581de9b

`strlcpy()` と `strscpy()` の違いは上記リンク先を参照してもらうとして、v4l2loopback.cで `strlcpy()` を利用している箇所では戻り値は参照されない
これより、文字列のコピー処理については `strlcpy()` と `strscpy()` の挙動が同様になるので `strlcpy()` を `strscpy()` で置き換えることにする

### diff

```diff
--- v4l2loopback.c.orig 2023-07-05 21:05:05.000000000 +0900
+++ v4l2loopback.c      2024-03-13 21:16:45.204190824 +0900
@@ -739,7 +739,7 @@ static int vidioc_querycap(struct file *
                        ->devicenr;
        __u32 capabilities = V4L2_CAP_STREAMING | V4L2_CAP_READWRITE;
 
-       strlcpy(cap->driver, "v4l2 loopback", sizeof(cap->driver));
+       strscpy(cap->driver, "v4l2 loopback", sizeof(cap->driver));
        vidioc_fill_name(cap->card, sizeof(cap->card), devnr);
        snprintf(cap->bus_info, sizeof(cap->bus_info),
                 "platform:v4l2loopback-%03d", devnr);
@@ -1247,7 +1247,7 @@ static int vidioc_queryctrl(struct file
        if (!cnf)
                BUG();
 
-       strlcpy(q->name, cnf->name, sizeof(q->name));
+       strscpy(q->name, cnf->name, sizeof(q->name));
        q->default_value = cnf->def;
        q->type = cnf->type;
        q->minimum = cnf->min;
@@ -1352,7 +1352,7 @@ static int vidioc_enum_output(struct fil
        memset(outp, 0, sizeof(*outp));
 
        outp->index = index;
-       strlcpy(outp->name, "loopback in", sizeof(outp->name));
+       strscpy(outp->name, "loopback in", sizeof(outp->name));
        outp->type = V4L2_OUTPUT_TYPE_ANALOG;
        outp->audioset = 0;
        outp->modulator = 0;
@@ -1411,7 +1411,7 @@ static int vidioc_enum_input(struct file
        memset(inp, 0, sizeof(*inp));
 
        inp->index = index;
-       strlcpy(inp->name, "loopback", sizeof(inp->name));
+       strscpy(inp->name, "loopback", sizeof(inp->name));
        inp->type = V4L2_INPUT_TYPE_CAMERA;
        inp->audioset = 0;
        inp->tuner = 0;
```

## 注意事項

`sudo apt install v4l2loopback-dkms` というコマンドでソースコードは `/usr/src/v4l2loopback-0.12.7/` にインストールされている
そこに今回対象とする `v4l2loopback.c` が置いてある

ビルドが失敗した際のエラーメッセージに `/var/lib/dkms/v4l2loopback/0.12.7/build/make.log` を見ろと表示され、そこに `v4l2loopback.c` があったので最初そこにパッチを当てたがビルドされる際に生成されるディレクトリーの模様で反映されなかった

`/var/lib/dkms/v4l2loopback/0.12.7/source` というシンボリックリンクがあり、これが `/usr/src/v4l2loopback-0.12.7` を指していた

なおGitHub上の最新のコードではすでに `strscpy()` が利用されている

https://github.com/umlaeute/v4l2loopback/blob/main/v4l2loopback.c

ちなみにマクロを利用してkernelのバージョンが4.3以前の場合は `strlcpy()` を使う模様

Ubuntu 24.04ではkernelは6.8を採用するようですがv4l2loopback-dkmsのバージョンは引き続き0.12.7のようなのでビルド出来ない件に対するパッチが当たってるのか気になるところです👀
さすがに対応されてるとは思いますが、もしおかしなことがあった場合に今回の記事が参考になれば幸いです

---

それでは良いLinuxライフを
【Flutter】connectivity_plusで「Execution failed for task ':connectivity_plus:compileDebugJavaWithJavac'.」のビルドエラー

## はじめに
大学生のFlutterコードレビューのボランティア的なことをしているのですが、レビュー対象のプロジェクトをビルドしようとしたところ、ビルドエラーになって2時間ほど溶かしてしまったのでメモ。

## 状況
レビュー対象のFlutterプロジェクトをローカルにclone
↓
Androidのエミュレータを立ち上げる
↓
Android Studioでビルド
↓
エラー発生

## エラー文
```
FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':connectivity_plus:compileDebugJavaWithJavac'.
> エラー: 17は無効なソース・リリースです

* Try:
> Run with --stacktrace option to get the stack trace.
> Run with --info or --debug option to get more log output.
> Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 1s
Running Gradle task 'assembleDebug'...                           2,232ms
Error: Gradle task assembleDebug failed with exit code 1
```

## 原因
Flutterのpackageであるconnectivity_plusが原因でした。
connectivity_plusのリポジトリにもバグ報告のissueが上がっていました。

https://github.com/fluttercommunity/plus_plugins/issues/2839

## 解決策
connectivity_plusのバージョンを変えることにより、このビルドエラーを回避することができます。
この記事執筆時点でのconnectivity_plusの最新バージョンは6.0.2ですが、6.0.2だとビルドエラーが発生してしまいます。
現時点でconnectivity_plusのバグ修正対応が完了していないため、ダウングレードを行なって5.0.2以前のバージョンを利用するのが解決策になります。
5.0.2以前のバージョンであれば、ビルドエラーも発生しないはずです。
Deviseを使用した複数モデル間のアクセス制御

## はじめに
この記事では、Ruby on Railsの人気認証ライブラリであるDeviseを使用して、異なるユーザーモデル間でのアクセス制御を実装する方法を解説します。特に、`Company` モデルがログインしている状態から、ログインせずに `Staff` モデルを編集する方法に焦点を当てます。

## 実装の試みと課題
初めに、`Staffs::RegistrationsController` を使ったアプローチを試みましたが、どうしてもログイン画面に遷移してしまい原因がわからないという問題に直面しました。

## 最終的な解決策
この問題を解決するために、`StaffsController` を利用して、`Company` モデルが `Staff` モデルのデータを安全に編集できるようにしました。以下はその具体的な実装です。

### 1. コントローラの設定
```ruby
class StaffsController < ApplicationController
  before_action :authenticate_company_or_staff!, only: %i(edit update destroy)
  before_action :set_staff, only: %i[show edit update]

  def edit
  end

  def update
    if @staff.update(staff_params)
      redirect_to staff_path(@staff), notice: 'スタッフ情報が更新されました。'
    else
      render :edit
    end
  end

  private

  def set_staff
    @staff = Staff.find(params[:id])
  end

  # 以下で認証確認
  def authenticate_company_or_staff!
    unless company_signed_in? || staff_signed_in?
      redirect_to new_company_session_path, alert: 'ログインが必要です。'
    end
  end

  def staff_params
    params.require(:staff).permit(:company_id,
        :name,
        :email,
        :position,
        :telephone,
        :postal_code,
        :prefecture,
        :city,
        :street_address,
        :description,
        :password,
        :password_confirmation,
        :current_password,
        service_ids: [])
  end

  def parse_date
    @date = params[:date].present? ? Date.parse(params[:date]) : Date.today # パラメータが存在する場合のみDateオブジェクトを作成
  end
end

```

### 2. ビューファイルの編集フォーム
```erb
<div class="container mt-4">
  <h2>スタッフ更新</h2>
  <%= render 'form', staff: @staff %>
</div>
```

### 3. フォームの部分テンプレート
フォームは、`_form.html.erb` に分けて、スタッフの情報を更新できるようにフィールドを配置しました。このフォームは、`current_company` が存在する場合に限り、会社IDを隠しフィールドとして送信します。

## 知見
- Deviseで異なるモデル間のアクセス制御を行う際には、RegistrationControllerではうまく制御できず、ログイン画面に遷移させられることがある。
- 上記の場合、自身でコントローラを作成して制御することで対応可能（`StaffsController`など）
- CanCanCanを使用することで、誰がどのリソースにアクセスできるかを細かく制御可能。
Scannerを用いた標準入力まとめ

個人的な備忘録も含めてScannerを用いた様々な標準入力をまとめてみた。

# Scaneerクラスの基本的な使い方
1.「java.util.scanner」をimportする
2. Scannerクラスのインスタンスを作成(引数にはSystem.inを指定)

## 主な入力メソッド
|メソッド|内容|
|-------|----|
|next()|空白までの文字列を取得|
|nextLine()|1行分の文字列を取得|
|nextInt()|入力した文字を整数型に変換。※整数以外を入力するとエラー|

### 1. 基本的な使用
```Java
import java.util.Scanner;

public class Main{
    public static void main(String[] args){
    //Scannerクラスのインスタンス作成
    Scanner scanner = new Scanner(System.in);

    //入力内容を取得
    String text = scanner.next();

    //入力内容出力
    System.out.println(text);
    }
}
/*入力内容がそのまま出力される。
入力値：リンゴ
出力値：リンゴ
*/
```

### 異なる行で複数の入力値を受け取る
・入力値の数が3つの場合
```Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        //入力値を格納する配列を作成
        String[] str= new String[3];

        //入力値を配列に代入
        for(int i=0; i<3; i++){
            str[i] = scanner.next();
         }
        //入力内容を出力
         for(int i=0; i<3; i++){
            System.out.println(str[i]);         
        
　}
}

/*入力値
りんご
ばなな
めろん

出力値
りんご
ばなな
めろん
*/
```

・入力する要素数を最初に指定する
```Java
import java.util.*;

public class Main {
    public static void main(String[] args) {
        Scanner scanner = new Scanner(System.in);

        //格納する要素数を指定
        int num = scanner.nextInt();
        //入力
        String[] str= new String[num];
        for(int i=0; i<num; i++){
            str[i] = scanner.next();
         }
         //出力
        for(int i=0; i<num; i++){
            System.out.println(str[i]);         
        }
    }
}
/*入力
3
入力1
入力2
入力3

出力値
入力1
入力2
*/
```


### 半角スペース区切られた入力値を受け取る
```java
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scanner = new Scanner(System.in);
        String[][] str = new String[3][2];
        
        for(int i=0; i<3; i++){
            for(int j=0; j<2; j++){
                str[i][j] = scanner.next();
            }
        }
        for(int i=0; i<3; i++){
            for(int j=0; j<2; j++){
                System.out.print(str[i][j]);
            }
            System.out.println("");
        }
        }
    }
/*入力
1 2
3 4
5 6

出力
12
34
56
*/
```

# 参考
https://rnsr0371.boy.jp/2020/10/09/java_stdin/
Windows キー ショートカット メモ




## 本記事で実現できること
- ショートカットキー何だっけと引き出したくなった時に見返して解決
- 見返したいショートカットキーは出てきたら随時追加
- 汎用で見れるように説明も加える

## スクロールロックでExcelが操作しづらくなった
ExcelのPgup,Pgdnした時、セルごとに移動しなくなった

### ショートカットキーの説明
[Windows] + [Ctrl] + [O] 
スクリーンキーボードを表示します。
ScrLkが光っていたならそれが原因です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754524/355f7e71-7ae3-f9ff-a00d-af697f5b8aa0.png)
※ScrLkがキーボード上にある場合は、
　[ScrLk]のみを入力もしくは[Fn]+[ScrLk]を入力すれば解決します。


## まとめ
本稿が、Windows キー ショートカットでなんだったっけってなった方の参考になれば嬉しいです。

ITエンジニア向け、AWS資格取得を目指す方向けに個人ブログで記事も投稿していますので、
合わせて読んでもらえると嬉しいです。
[ことなの学校(個人ブログ)](https://kotona-school.com)

更によりレベル感の高そうなAWS関連の発信はZennの方で行います。
こちらももしよければフォロー、ご確認いただけると嬉しいです。
[Zenn個人アカウント](https://zenn.dev/tomo_itbizblog)

Twitterでも役立つ情報を発信しますのでフォローしてもらえると嬉しいです 
→ [@tomo_ITBizBlog](https://twitter.com/tomo_ITBizBlog)
行動メモのすすめ

## はじめに
私は仕事・プライベート問わず、何かを開発したり、技術的な調べ物をする際に「行動メモ」というものをつけている。
仕事を始める前からかれこれ3年ほど続けているが、なかなかメリットがあるものだと思っているので、記事にしてみる。

## 私の情報
- Unityのエンジニア　歴1年

## 行動メモとは
**今考えていること、目の前に起きたこと、読んでいる記事のリンクなどを片っ端から書き込んだメモのこと**を勝手にそう呼んでいる。
私の場合はSlackのスレッド欄に、Twitterのような感覚でひたすら書き込んでいる。
![スクリーンショット 2024-04-20 23.04.57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679129/8458f662-5c01-c19d-0002-f702ea852dc7.jpeg)
![スクリーンショット 2024-04-20 23.06.57.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3679129/a557dba2-9465-1e71-7dbd-c337e1e3d0c9.jpeg)


## メリットは？
- **思考が整理できる**
    - 思っていることを文字に書き起こすことで思考が整理され、考えもより明確になる。
- **行動を振り返りやすい**
    - 当然だが、あの時何を考えて何をしていたかの情報が全て書かれているので、久々の作業等で記憶喪失に陥ってても安心。明確な日付を思い出せなくても、思い当たるワードでチャンネル内を検索すれば大体ヒットする。
- **自分が無駄にした時間を視覚化できる**
    - Slackの場合は投稿日時がわかるので、何の作業にどれくらい時間をかけたかがすぐわかる。気がついたらすぐ投稿日時が数十分前とかになってるので、無駄な時間を発見しやすい。
- **得た知見をドキュメント化する時に役立つ**
    - 作業中「この情報はどこかにしっかりまとめておきたい！」と思っても、なかなかすぐに着手はできない。が、とりあえず行動メモに書き殴っておけば、後で参照しながらまとめ直すことができる。
- **仲間・先輩・上司に状況を説明しやすい**
    - 困ったことが発生した場合に、どうしてそうなったのかの流れを説明しやすい。また、行動メモはある程度パブリックな場所（自分のtimesチャンネルなど）に書いておくと、メモを見た先輩・上司からアドバイスしてもらえることもある。

## デメリットは？
- **いちいち書くのがめんどくさい**
    - 実際のところ私はそこまで気にならないが、人によっては当然こういった意見も出てくると思う。
- **小さい画面ではメモしづらい**
  - 私はMacBookPro14インチをメインマシンにしている。外部ディスプレイに繋いで作業ができる環境であれば問題ないが、出先などで内臓ディスプレイを使用する際は、Slackをとそれ以外の画面を行き来するのが結構大変。

とはいえ、現状表立って考えられるデメリットはこれくらい。
書くのに時間を食うだろうという意見もあると思うが、私の場合はまだ未熟なエンジニア故、行動メモを書いておくことでむしろ時間短縮につながっている面もある。

## メモを書く場所について
色々試したが、現状はSlackの**スレッド欄**に書くのがベストだと考えている。
チャンネルに直接書くと、連続した投稿が区切りなく繋がって見づらくなってしまったり、通知面でワークスペースメンバーに迷惑をかけてしまうことも考えられる。

パソコンのメモ帳などでも良いのだが、一つの文章を書いた時間が記録されないことに加え、画像・動画・ファイルなどをバンバン貼り付けていく使い方をするなら、Slackの方が良いだろう。

ちなみにDiscordでもほぼ同じことができるが、Slackのチャンネル直書き同様、連続した投稿が区切りなく繋がってしまうため、見づらい。

## おわりに
作業時間に余裕がない時などはサボってしまうこともあるが、それ以外はできるだけ行動メモを書くようにしている。

皆さんもぜひ一度やってみて、自分に合うかどうか試してみてはいかがだろうか。
VaultwardenをAzure Container Appsで立ち上げる

# 必要なもの
- Azure環境(無料枠でOK)
- ちょっとの予算(月100円もかからないと思う…)

# 構築手順
## 細々したもの
リソースグループに次のものを作成して下さい。
- ストレージ アカウント(最低限の設定でOK)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/ae20dfd2-dd3e-6da1-76b3-96266a5ecbbd.png)
本当はIPアドレス指定で許可したいのですが、なぜかマウント出来なくなってしまうのでやむなくパブリック許可にしています。
~~(VNET統合したほうが良いんでしょうが…)~~ 
> →普通にContainer Apps環境作成時にサブネット生成してVNET統合するだけで簡単にできました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/aa6fc8dc-e7a4-7094-e450-cb8afc5331ef.png)

    - Azure Files(ファイル共有)もついでに適当に作っておいて下さい
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/471da74e-7c42-242f-43b5-40052ec0a801.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/b95e4b5e-2dfb-8c82-ae40-046d484dd04a.png)
`トランザクションが最適化されました`レベルで良いと思います。よくわかりませんが。

- Azure Database for PostgreSQL フレキシブルサーバー(最低設定・無料枠でOK)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/f33ab93f-6330-a183-7480-4f00b36450cc.png)
ついでにデータベースから`vaultwarden`を事前に作っておきましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/53db7542-407d-8d5f-1eeb-3c5febc125d1.png)

## メインのやつ
本命のContainer Apps(コンテナー アプリ)を作りましょう。
大事な所だけ書き出します。それ以外は流れかお好みで決めて下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/9e7878f0-97c9-4dbb-9cff-00b49700abe4.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/7ee5c143-b5da-9121-5d3f-7e4cd39395d9.png)

完成したら次はAzure Filesとの連携です。
`Container Apps環境`→`Azure Files`からAzure Filesとファイルの読み書きが出来るようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/19afdf31-59c7-0e2d-6168-ad9f6867090e.png)
必ずアクセスモードは`読み取り/書き込み`にしましょう。
> 名前は何でもいいですが、どうもContainer Apps側の名前と被るとおかしくなる気がします。

お次にコンテナーアプリを開いてコンテナーから編集とデプロイで環境変数等を設定します。
環境変数はこんな感じです。(メール送信にmailtrapを利用、各種重要設定はシークレットに隠しています)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/953537c0-db63-ac82-d140-134e3ea24cd0.png)
db-postgresの中身はこんな感じです。
`postgresql://ユーザー名:パスワード@接続先名.postgres.database.azure.com:5432/vaultwarden`
ユーザー名、パスワードはAzure Database for PostgreSQL フレキシブルサーバーの作成時に決めたものを入れて下さい。接続先名は同管理画面から確認できます。

ボリュームマウントでAzure Filesをマウントしましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3314743/d1c86073-ba95-6b6b-b633-526b0e07ceb6.png)
> ちなみにSQLiteで動かそうとすると何故かWALを無効にしてもエラーで起動しなくなります。よくわかりません。なのでケチケチせずAzure Database for PostgreSQLの無料枠を使いましょう。

ここまで来れば、もう利用できる状態になっているはずです。
カスタムドメインはマネージド証明書も使えるようになったので、ドメインをお持ちの方はCNAMEとTXTを登録してあげるだけですぐに使えます。

## SQLiteからPostgresに移行したいんだけど？
pgloaderを使う方法が公式に案内されています。が、謎のスキーマエラーでよくわからなかったのでDBeaverでゴリ押し移行しました。
単純にDBeaverでSQLiteのデータを開いてテーブルを選択し、右クリックからエクスポートを選んだ後にエクスポート先をPostgresにしてあげるだけです。
事前にPostgresとVaultwardenが初期連携出来ていれば、後は移行先スキーマに指定すると勝手にExist判定で突っ込んでくれます。すっごい便利。
詳細はまた後日書き直します。