OmniAICreator/Qiita-1.07M huggingface dataset:
Google スプレッドシートを見やすくする条件付き書式一覧

## 値に応じてセルの色を変える

### ステータスが「進行中」ならセルを緑にする

条件付き書式による実装は次の通り。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/e08f0119-5aed-1b61-30a1-d23f9631321f.png)

似たようなことがツールチップでも可能。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/c11042c9-8951-6bb4-f3cb-3746adf1137f.png)

### 上の行と同じ値なら文字色をグレーにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/5d6b8b4c-9669-0c15-c3f8-1bf929a07287.png)

複数行にわたって同じ値が続くときに見やすくできる。

範囲の左上のセル（画像の例だとA2）とひとつ上のセル（画像の例だとA1）を比較するカスタム数式によって該当セルを設定できる。

## 値に応じて行の色を変える

### ステータスが「完了」になったら行をグレーにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/402f9cb8-8e0a-4461-98c9-f8a22d043154.png)

完了の行をグレーにしておくと、見る必要のない行がひと目でわかるようになる。

実装方法は以下の通り。

1. グレーになる可能性がある範囲すべてに適用する（画像の例ではA2:B7）
1. ステータスを表す列の一番上のセルを確認する（画像の例ではB2）
1. 列を固定（ `$B2` のように列の前に `$` を書く）した上で、設定したいステータスとの比較をカスタム数式に記載する（画像の例では `=$B2="完了"` ）

### 見出し記号に対応して行の色を変える

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/8fa55b6b-b975-67be-71ff-8dc3ceefce00.png)

スプレッドシートにドキュメントを記載したいとき、見出し行をわかりやすくするために色を変える。
見出しを増やしたり減らしたりしても、書式を再設定し直さなくて良いメリットがある。

セルの値の左1文字を `LEFT` 関数により切り出し、それが見出し記号（画像の例では `★` ）と一致していたら見出し行と判定している。

## 日付に応じて色を変える

### 過去の日付ならセルをグレーにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/ea88d224-b832-bda7-9da7-e8891b411b51.png)

### 今週の日付ならセルを緑にする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/e8af9eb2-c9cf-ac2b-ae6d-b290163b8b4c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/5debb1a3-f513-b599-3818-2fb0fb1bd2a9.png)

「過去の日付ならセルをグレーにする」と組み合わせて、直近1週間以内の日付を緑にすることで、よりフォーカスするべきところをわかりやすくする。
2つの条件付き書式設定の適用順序も大事だ。

別の方法として、ピンポイントで今週だけ色をつけたい場合は、カスタム数式でも実現できる。
```
=and(b2>=(today()-weekday(today(),3)),b2<(today()-weekday(today(),3)+7))
```
この数式は、セルの値が、今日と同じ週の月曜日かそれより後で、来週の月曜日より前の日であれば、マッチする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/172889/a068a91c-dc03-f6d8-2dbd-f36bc8fb38a5.png)
k8sのディレクトリ設計の個人的に好きな管理


k8s+argocdでリソースを管理するときの構成について記述してみました。

```bash
.
├── argocd
│   ├── application //基本applyするときはここのみ
│   │   ├── dev
│   │   │   └── <※1の名前>
│   │   │       └──  <※1の名前>.yaml
│   │   └── prod
│   │       └── <※1の名前>
│   │           └── <※1の名前>.yaml
│   └── ns.yaml // argocdのns
├── <argocdにapplyさせるk8sリソースの名前　※1>
│   ├── <argocdにapplyさせるk8sリソースの名前> //基本この中身がargocdによってk8s-clusterの中に展開される
│   │   ├── configmap.yaml
│   │   ├── deployment.yaml
│   │   ├── secret.yaml
│   │   ├── statefulset.yaml
│   │   └── svc.yaml
│   └── ns.yaml
└── readme.md
```

### terraformバージョンはこちら

https://qiita.com/magisystem0408/items/a04602ddd217cdf7591c


### おまけ

https://qiita.com/magisystem0408/items/7cf67728756f0f87d1d7
Azure DevOpsで削除したリポジトリ復元

# 概要

Azure DevOpsのRepoで削除したリポジトリに対して復元する手順を整理します。
削除したリポジトリは30日保存されるので、その日数を経過すると復元することはできないのでご注意ください。

# 個人用アクセストークン(PAT)作成

Microsoft Learnサイトで詳しく書いてありますので、そちらのサイトを参考して個人用アクセストークンを作成してください。
トークンは復旧作業で使いますので、とりあえず権限は「Full Access」、期間は「1日」で作成してください。
最終でトークンが現れたらメモしてください。

https://learn.microsoft.com/ja-jp/azure/devops/organizations/accounts/use-personal-access-tokens-to-authenticate

```plaintext:PAT作成ページ
https://dev.azure.com/{組織名}/_usersSettings/tokens
```

# Postmanアプリ起動

REST APIを発行するので、Postmanをダウンロードしてください。

https://www.postman.com/downloads/

# Postmanで認証設定

新しいHTTP Requestを作成し、「Authorization」タブメニューから下記のイメージで①の「Basic Auth」を選択します。UsernameとPasswordページが見えたら、②のようにUsernameは空欄、PasswordはメモしたPATを入力してください。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/8b4c0890-af70-1f43-ace6-de9c4aa0954e.png)

# 識別子取得

削除したリポジトリを復元するにはリポジトリの識別子(GUID)が必要なので、Azure DevOps REST APIを使って識別子を取得します。
PostmanのHTTPメソッドを「GET」にし、URLを下記のように設定してください。

```plaintext:識別子取得API
https://dev.azure.com/{組織名}/{プロジェクト名}/_apis/git/deletedrepositories?api-version=7.0
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/96fd5485-1218-f021-eef1-69d06cb7a76c.png)


https://learn.microsoft.com/en-us/rest/api/azure/devops/git/repositories/get-deleted-repositories?view=azure-devops-rest-7.0

うまく取得できたら、Postmanの結果画面で削除したリポジトリのリストが見えます。識別子はid項目の値となります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/95279f3f-1007-6e11-06d1-996c00fc36d8.png)

# リポジトリ復元

最後の手順となります。
新しいHTTP Requestを作成しても、HTTPメソッドを「PATCH」にし、URLと「Body」の内容を下記のように設定してください。
ちなみにPostmanの仕様上、「Authorization」設定内容は引き続けられますので設定する必要がありません。

```plaintext:復元API
https://dev.azure.com/{組織名}/{プロジェクト名}/_apis/git/recycleBin/repositories/{識別子}?api-version=7.0
```

```plaintext:BODY内容
{
　　"deleted":false
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/287622/ffed0d2e-8b49-65ac-5acb-a9691cbbf3c7.png)
DBパスワード変更後、BIサーバ再起動に失敗

<h2>エラー事象</h2>
他チームから、DBのパスワードの変更を実施するとの連絡を受け、
それに伴いBIconsole画面でデータソースに対して、既存のBIスキーマを含めDBパスワード変更を実施。

パスワード変更し、BIサーバ再起動しましたが、エラーが発生してしまった。
＞ORA-01017：invalid username/password; logon denied

<h2>解決方法</h2>
アカウントが無効というエラーで、console画面のモニタリングでテストを実施し、<br>
問題なかったことを確認したが、上記のエラーが発生。<br>
変更前のパスワードがセッションに残ってるせいかと思い、サーバのキャッシュフォルダを回避し、<br>
サーバ再起動したが、でも同じエラーが発生しちゃった。
<br><br>
oracle supportで検索すると、em画面のdatasource.biplatform資格証明のパスワードもbiplatformスキーマのパスワードに統一させる必要があるそうで、
統一した後に、再起動したら正常再起動できた。<br>
追加で、DBパスワードが変更されたら、リポジトリのパスワードの変更も必須！<br>
変更してからuploadrpdを実施する必要がある。
Golangでdlvが動作してない件（ブレイクポイントで止まらない件）(忘備録)

# PCの環境
```
M1 MAC Monterey
Golang 1.17, 1.19
vscode
```

# 経緯
1. Golangのバージョンを`1.17`から`1.19.3`にあげた
1. go delveのバージョンをvscodeを通じてあげた
1. デバックは動作するが、ブレークポイントでブレークされない

# 対応記録
1. golangバージョンを`1.17`に下げる
    → delveからバージョンが低すぎるとエラーが表示された

1. golangバージョンをbrew, goenv としてダウンロード
    → ブレイクポイントで止まらない

1. [vscode launch.json substitutePathの変更](https://github.com/go-delve/delve/issues/2795)
  → ブレイクポイントで止まらない

1. 現在ダウンロードされている全てのGolangを削除し、[asdf](https://asdf-vm.com/)でGolangを再度ダウンロード、パスを通す
  → ブレイクポイントで止まらない


# 解決
https://github.com/golang/vscode-go/issues/2417

vscode > Run and Debug: Focus on Breakpoints Viewを実行し、dlv内部のエラーを確認

上記の対応で、ブレーキポイントを探さないというエラーが表示されていた
普通のDebugボタンではエラーが表示されなかった


GoFlagのオプションを確認した

https://github.com/microsoft/vscode-go/issues/2807

`go env` で私のPCで`GOFLAGS="-trimpath"`になっていることを確認
仕事で同じM1 MACを持っている人と比較し、そのMacでは`GOFLAGS`の設定がなかったので削除

```
go env -w GOFLAGS=''
```

## 対応完了
Docker環境でPHPのエラーログを出力する

# 事前準備としてコンテナ名を確認

docker ps

# ログを確認したい時

docker logs -f <コンテナ名>

# アクセスログを確認したい時

docker logs <コンテナ名> -f 2>/dev/null
※ 2 はエラーという意味で、/dev/null は　破棄する　という意味。エラー出力を破棄する、という意味になる。

# エラーログを確認したい時

docker logs <コンテナ名> -f 1>dev/null
※ 1 は標準出力のことになり、この場合は　標準出力を破棄する、という意味になる。

注意：　上記では dockerコマンドを使用しているが、docker-composeコマンドでもログを取れる。
その場合は docker ps などとコンテナを調べずにログが取れるので簡単。
しかしダメ。採用していない。
理由は、アクセスログとエラーログが混ざって出力されるため、切り分けしづらいから。
それでも良い場合だけ使う。
でなければ、ログだけ見たいとかならば使わない。

dockerの場合、正常系とエラー系の二種類しか分離でいない。
MVCについて

# はじめに
Webアプリケーションフレームワークでよく用いられるMVCモデル。
当たり前のように使ってきたモデルだが、改めてどんなメリットがあり、どんな特徴があるのか
頭の中を整理したくてこの記事を作成した。

## この記事の対象者
* これからMVCモデルを使う人
* ざっくりMVCモデルを知りたい人

# MVCモデルって何？
> MVC は、Webフレームワークで一般的に取り入れられているアプリケーション設定を整理するための概念の一つです。
モデル（Model）頭文字「M」、ビュー（View）頭文字「V」、コントローラー（Controller）頭文字「C」で「MVC」と言います。

参考：https://www.geekly.co.jp/column/cat-technology/1911_040/#MVC-2

Model、View、Controllerという役割ごとにディレクトリが分かれている。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/697198/7b995b69-1a11-dc2f-c14b-01d46cd97ac0.png)



## <font color="Red">モデル（Model）って何？</font>
<font color="Red">データの管理とビジネスロジック</font>を担当している。
データの管理とはDBとのやり取り、ビュー/コントローラーが欲しい形に整形することを指す。
O/Rマッピングという手法を使えば、モデルの記載をもとに、SQLを書かずにデータベースのテーブルを作成したり
CRUD処理を行うことが可能。

## <font color="DarkKhaki">ビュー（View）って何？
<font color="Red">UIの表示</font>を担当している。モデル→コントローラーとわたってきたデータを画面に表示させる。
画面表示用に、for文、if文のような簡単なロジックを書くことも可能。

## <font color="Green">コントローラー（Controller）って何？</font>
ユーザーの入力を受け付けて、<font color="Red">モデルとビューの仲立ち</font>をする。

# メリット

### 複数人に分かれて実装する際に、役割分担がしやすい
画面実装が得意なAさんはView、ロジック書くのが得意なBさんはModel、といった分担が可能。
（私はMVCモデルを現場で使ったことがない、珍しいよわよわエンジニアなので、本当にこんな分担がされているかは不明。）


### 保守性が高くなる
例えばだが、テストで画面上の表示にエラーがわかったとする。
MVCモデルに則って実装していれば、「まずはViewを確認しよう」となり、
<font color="Red">予測を立ててバグ潰しができる。</font>

### 使っているフレームワークが多いので、一度覚えると潰しがきく
MVCを使うメリットというより、覚えておくとメリットがあるという話。
MVCモデルを使用している代表的なフレームワークは以下の通り。
他にもまだまだあるので、構造を覚えておくと潰しがきいてよい。
* Spring Boot（Java）
* Spring MVC（Java）
* ASP.NET Core（C#）
* Rails（Ruby）
* Laravel（PHP）
* CakePHP（PHP）
* etc...

### 理解している人が多いので、現場で使いやすい
これは、現場で使用するフレームワークを検討している人向け。
MVCモデルのフレームワークを選ぶとこんなメリットがあるよという話。

# まとめ
* モデルはデータの管理担当
* ビューは画面担当
* コントローラーはリクエストを受け付けて、モデルとビューの仲介担当

# 参考文献
https://www.geekly.co.jp/column/cat-technology/1911_040/
Seleniumを使ったWebページのPDF化

# 事前準備

```shell
# pip install selenium
# pip install webdriver-manager
```

# 1つのURLだけの場合
```python
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager


options = webdriver.ChromeOptions()
options.add_experimental_option('prefs', {
    'download.default_directory': '~/Downloads'
})
options.add_argument('--kiosk-printing')

driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
driver.get("ここにURLを入れる")
driver.execute_script('window.print();')
driver.quit()
```

# 複数のURLの場合
* テキストファイルにURLを1行ずつ入れておく

```python
from selenium import webdriver
from webdriver_manager.chrome import ChromeDriverManager
import random
from time import sleep

# オプション設定
options = webdriver.ChromeOptions()
options.add_experimental_option('prefs', {
    'download.default_directory': '~/Downloads'
})
options.add_argument('--kiosk-printing')

with open("URLのリスト") as urls:
    # ドライバ起動
    for url in urls.read().split("\n"):
        driver = webdriver.Chrome(ChromeDriverManager().install(), options=options)
        driver.get(url)
        sleep(random.randint(3, 6))
        driver.execute_script('window.print();')
        driver.quit()
        sleep(random.randint(3, 6))
```
[PracticeA][Welcome to AtCoder]を解いてみた！RubyでAtCoderの解説

# 正解したコードの解答例
```
a = gets.to_i
b,c = gets.split(" ").map(&:to_i)
s = gets.chomp

puts ("#{a+b+c} #{s}")

```
# 解説
1行目a = gets.to_i
のgetsメソッドでは、ユーザーがキーボードで入力した値を文字列として取得しています。
問題文は数値での出力が求められるためto_iメソッドで数値化してあげます。

2行目b,c = gets.split(" ").map(&:to_i)
b,cで入力したコードをsplitメソッドで指定した区切り文字（" "）で分割し、配列で返します。
b cの入力時にスペースをあけるため、ここでsplit(" ")が作用して文字列の配列が作成されます。
このままでは配列の中身は文字列の状態なので.map(&:to_i)を使用して配列の中身を全て数値オブジェクトに変換します。

３行目のchompは改行をなくすメソッドです。getsのみだと改行が入るようになっています。

最後、計算結果を出力しています。

以上、PracticeAの解説でした。

■参考サイトURL
https://pikawaka.com/ruby/map
https://pikawaka.com/ruby/gets
https://pikawaka.com/ruby/split

# 追記
split(" ")の記述はsplitのみでも同じ動作をするようなので省略可能です。
PHPでリダイレクトする

# 生のHTTPヘッダを送信する

$header：ヘッダ文字列

```
header($header)
```

リダイレクトするにh Location: ヘッダを付与する。
当然ながら、リダイレクトさせると、その後にコードを記述していても実行されない。
しかしこれまた当然ながら、条件文ならば、条件に合わずリダイレクトされなければその後のコードは実行される。

```
header("Location: https://www.mysite.com/");
```
[AWS]踏み台サーバーとWebサーバー

# 踏み台サーバー

### 踏み台サーバーを作成する意味

VPC内に設定したリソースは常に悪意あるユーザーからの侵入の脅威にさらされます。特に外部から直接SSH接続できる環境では不正アクセスのターゲットになる可能性があります。そこでネットーワーク上の安全性を保つためには、中継用のサーバーである「踏み台サーバー」を作成し、目的のサーバーに接続するにも一旦踏み台サーバーを経由することで、セキュリティ強化を図ります。

### 踏み台サーバーの作成

まずはSSH接続に必要なキーペアを用意する必要があります。


https://qiita.com/tumu1632/items/e7b5357f7c36939209d5

<br>
<br>

| 名前 | AMI | インスタンスタイプ | キーペア | VPC | サブネット | パブリックIP | セキュリティグループ |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| sample-ec2-bastion | Linux | t2.micro | 作成したキーペア | sample-vpc | subnet-publick01 | 有効 | default, sample-sg-bastion |

※踏み台サーバーのためインスタンスタイプはデフォルトのままで十分です。

上記のようにEC2サーバーを作成し、セキュリティグループは2つ設定します
　default => VPC内の全てのリソースからの通信を許可する
　sample-sg-bastion => SSH通信を許可する

# Webサーバーの作成
既に作成したパブリックサブネット内にWebサーバーを２つ作成していきます。このWebサーバーは踏み台サーバーと違って、インスタンスタイプは利用者の数に応じて適切なインスタンスタイプを設定する必要がありますが、今回は学習のために作成するためデフォルトのままにします。

| 名前 | AMI | インスタンスタイプ | キーペア | VPC | サブネット | パブリックIP | セキュリティグループ |
| :---: | :---: | :---: | :---: | :---: | :---: | :---: | :---: |
| sample-ec2-web01 | Linux | t2.micro | 作成したキーペア | sample-vpc | subnet-private01 | 無効 | default |
| sample-ec2-web02 | Linux | t2.micro | 作成したキーペア | sample-vpc | subnet-private02 | 無効 | default |

# 参考
AWSではじめるインフラ構築入門 翔泳社出版

https://baresupport.jp/blog/2022/07/29/154/
PHPで投稿日時から現在までの経過時間を表示するための関数の書き方

 ## 投稿日時を表示する方法
Twitterみたいに投稿から経過した時間を表示すための関数をPHPで書いていきます。

### 表示例
* 現在時刻が「2023-01-01 00:00:00」だった場合
    * 2022-12-31 23:59:50 ->10秒前
    * 2022-12-31 23:59:00 ->1分前
    * 2022-12-31 23:00:00 ->1時間前
    * 2022-12-30 00:00:00 ->1日前
    * 2022-11-30 00:00:00 ->2022年11月30日

### 手順
`convertToDayTimeAgo`という関数を作成し、引数の`$datetime`に「2023-01-01 00:00:00」のような日時と時間を指定した文字列が挿入される想定です。

```php:php
/**
 * 指定した日時からどれくらい経過したかを取得
 * @param string $datetime 日時
 * @return string
 */
function convertToDayTimeAgo(string $datetime)
{
  // ※UNIX時間とは、UTC時刻における1970年1月1日午前0時0分0秒（UNIXエポック）からの経過秒数を計算したものです。
  // $datetimeには'2023-02-13 21:55:00'のような指定した日時の文字列が入ってくる想定です
  $unix = strtotime($datetime);
  // time関数はUNIX時刻から現在までの秒数を返します
  $now = time();
  // 現在の時刻から指定した日時のユニックスタイムを引きます。これによって現在からどれくらい時間が経っているかを取得することができます。
  $diff_sec = $now - $unix;

  if ($diff_sec < 60) {
    $time = $diff_sec;
    $unit = '秒前';
  } elseif ($diff_sec < 3600) {
    $time = $diff_sec / 60;
    $unit = '分前';
  } elseif ($diff_sec < 86400) {
    $time = $diff_sec / 3600;
    $unit = '時間前';
  } elseif ($diff_sec < 2764800) {
    $time = $diff_sec / 86400;
    $unit = '日前';
  } else {
    if (date('Y') !== date('Y', $unix)) {
      $time = date('Y年n月j日', $unix);
    } else {
      $time = date('n月j日', $unix);
    }
    return $time;
  }
  return (int)$time . $unit;
}
```
`strtotime($datetime)`ではUNIXタイムスタンプに置き変えています。
UNIXタイムとは1970 年 1 月 1 日 00:00:00 UTC からの経過秒数を表しているのですが、詳しくは下記のPHP公式マニュアルを確認してください。

https://www.php.net/manual/ja/function.strtotime.php

 `time()`ではUNIX時刻から現在までの秒数を返します。

`time()`から`strtotime($datetime)`を引くことによって(ここでは引いた数を仮に`$diff_sec`とする)、現在からどれくらい経過したかを秒数で表すことができます。

以降の処理については、経過した秒数から表示する方法をif文で構成しています。
・経過した時間 < 60だった場合、〇秒前で表示
・経過した時間 < 3600（60×60）だった場合、`$diff_sec`÷60→〇分前で表示

「時間前」も「日前」もこの繰り返しです。

elseでは、１ヶ月以上前の投稿、1年以上前の投稿の記述について記載しています。

最終のreturnではint型で小数点を切り捨てて、$unitに入ってきた文字列とともに表示します。
PAD: SharePoint Lists への SQL を利用した User 追加や更新時は、SiteUsers の Id を利用する

# 背景
会社で、User 追加でエラーになるって話だったので、たぶん SiteUsers 使えばいいんじゃない？って思ったけど余裕が無かったので、自宅で検証した記録

# 結論

SiteUsers の Id で更新も追加も出来ました。

テナントの User Id を使って更新・追加しようとしてしまうんですが・・
SharePoint のサイトごとにある User ID を利用する必要があるっていうオチですね。

昔、Teams メンバー一覧リストを作った際の知見が役に立ちました :laughing: 

https://qiita.com/baku2san/items/c5b56ce21c5a880a9d3f

# 詳細

そもそもの SQL 操作は以下で確認を

https://qiita.com/MiyakeMito/items/4c9408744d7ed3486770#%E3%83%87%E3%83%BC%E3%82%BF%E3%81%AE%E8%BF%BD%E5%8A%A0

困る部分としての説明のみ

以下 API を使って、SiteUser ID を取得します

```url
{SharePoint Site URL}/_api/Web/SiteUsers

例
https://***.sharepoint.com/sites/testsite/_api/Web/SiteUsers
```
:::note info
一覧としては、<code>{SharePoint Site URL}/_catalogs/users</code> で見られるんですが、ID を取る方法はやっぱりAPIかな
:::

これで取得出来るのは xml 形式で、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/892c3478-d5ed-d07c-d17f-303a17ecb395.png)
こんな感じで、各ユーザー毎の Id が格納されています。

ということで、あとは、この Id を PAD の Insert Statement に設定してやれば OK

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9c9a232f-8b87-ad9c-8a2c-24fa85716326.png)

で、実行結果は以下
無事目的のユーザーで更新出来てますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/9d32af6b-691d-bdfd-2b37-ab3e84802002.png)

あとは頑張って自動化してください。

## 更新の場合の例

ユーザ列を更新しないと、上手くいかない、という話があったので試してみた

```sql: ユーザー列自体の更新
UPDATE  list SET usr = 9 WHERE Title = 'shima_kuma'
```
```sql: ユーザー列を更新しない場合
UPDATE  list SET RawA = '×' WHERE Title = 'shima_kuma'
```

上記で、以下もOK
1. ユーザー列を更新
1. 〇⇒×へ更新：ユーザ列を非糠疹

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/7a4ee725-673e-b246-5a0c-ed339cb5e996.png)

同一のユーザ情報を別の列で参照してる・・とか・・かな？

かと思って、ユーザー列を参照して、substring() を利用した列を追加してみたが、特に問題なく更新出来た。
状況を聞いてみないとこれ以上はわからないね。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/8425937c-f664-abda-bb5b-631398b2b081.png)

コンテンツタイプを有効にしても変わらず

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/e99bb444-3ed1-2c07-df07-dffbcd3325b2.png)


# ドキュメント
|目的|API|Doc|
|-|-|-|
|Site の user 一覧|_api/Web/SiteUsers|[SPWeb.SiteUsers Property](https://docs.microsoft.com/en-us/dotnet/api/microsoft.sharepoint.spweb.siteusers?view=sharepoint-server)|

https://learn.microsoft.com/ja-jp/sharepoint/dev/sp-add-ins/sharepoint-net-server-csom-jsom-and-rest-api-index#sharepoint-api-index

#　あとがき
ROS2 の勉強しないとなんだけど・・やる気が起きないので、ついつい横道へ・・ :cry:
rails deviseを使った論理削除と、垢BANさせる機能と復活させる機能

# 管理者側で、会員ステータスを思うがままにする
論理削除で退会したユーザーのデータは残っています。なので、退会したユーザーを復活させることが可能。


チーム開発で管理者権限で垢BANさせる機能の実装ができなかったので、ポートフォリオで実装してみました。そして、復活させることもできます。神ですね。

## 前提

- deviseで、管理者側と、会員側のpublicで分けて実装している。
- データベースにbooleanのデータ型で、default: falseの会員ステータスを作成している。
- public(user)側で退会機能を実装してある。


### routes.rb
      namespace :admin do
      :
      :
      ユーザーを退会させる :idでユーザーのIDが取得できる。
      patch "withdrawal/:id" => "users#withdrawal", as: "withdrawal"
      end



### controllers/admin/users_controller.rb


     既に実装してあるpublic側から退会アクションメソッドをコピペしてきて修正。

     def withdrawal
         @user = User.find(params[:id])
               #!をつけて、true/falseを反転させて、有効、退会を切り替えることができる。
         @user.update(is_deleted: !@user.is_deleted)
     
            if @user.is_deleted
               flash[:notice] = "退会処理を実行いたしました"
            else
               flash[:notice] = "有効にします"
            end
               redirect_to admin_root_path
        
      end


### views/admin/users/show.html.erb


    <th>会員ステータス</th>
        <td>
            <% if @user.is_deleted %>
              退会済み
    <%= link_to "有効にする", admin_withdrawal_path(@user.id), method: :patch, class: "btn btn-success" %>
            <% else %>
              有効
    <%= link_to "退会させる", admin_withdrawal_path(@user.id), method: :patch, class: "btn btn-danger" %>
            <% end %>
          </td>


こんな感じで、実装できた。やったね。
boolean型は　==　などを省略できる。演算子の!をつけることで。真偽値を返してくる。
なので、同じアクション内で簡潔に書くことができた。

数学苦手なので、演算子などの理解がまだ難しい。
SSHキーの作成(AWS)

# キーペアを作成する意味

キーペアは、EC2インスタンスにアクセスする時などに利用される暗号鍵で、セキュリティ認証を行うために作られています。キーの暗号化にはRSAやED25519というアルゴリズムが使われてます。

まず、キーペアを作成する意味の一つは暗号化です。暗号化を施すことによって、第三者への情報漏洩を避けることができる点です。そして二つ目にこれから説明する暗号化と複合化の仕組みを利用して、送信者が指定した人以外にデータの送受信ができない仕組みを整えることで、通信のなりすましを防ぐことができる点です。


# キーペアの方式(公開鍵暗号方式)
キーペアを作成するにあたって、まずは秘密鍵と公開鍵のキーをそれぞれ作成する必要があります。秘密鍵は、特定の人しか知らない鍵に対して公開鍵は、公に公開していい鍵になります。

一般的な通信では公開鍵暗号方式が挙げられます。これはまず受信者が秘密鍵を作成します。秘密鍵から公開鍵を作成し、受信者はデータを送っていい人に公開鍵を渡します。データの送信をする上で、送信者の公開鍵でデータを暗号化した後、受信者の秘密鍵でデータを複合化します。この仕組みによって、データの改ざんや情報漏洩を防ぐ効果が期待できます。

(イメージ図)

![公開鍵方式 (2).jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/c50668d9-7118-583c-d4d4-a2ee53fdf97b.jpeg)





# コンソール画面とターミナルにてSSHキーを作成および接続

### コンソール画面

![AWS_key ssh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/790379/6db2bc1a-5f7f-3202-3926-809ef915527d.png)

今回はMacでキーペアを作るため、pem形式を使っていきます。(Windowsはppk形式)


### ターミナルの入力

```
$ mkdir .ssh

$ cp ~/Downloads/AWS_key.pem .ssh
　　　　("AWS_key.pem"は任意の名前を設定する)
```
AWSのコンソール画面で作成された、SSHキーはDownloadフォルダに保存されるため、秘密鍵である"AWS_key.pem"を先ほど作成した.sshディレクトリにコピーしていきます。

```
$ ssh -i ~/.ssh/AWS_key.pem ec2-user@XXXXXXXXXXXX
```
AWS画面にて作成した後に出たものをそのままコピーすることによって、サーバーに接続できます。
また、サーバーへの接続を切断するには、logoutやexitコマンドを入力することで、切断できます。

# 多段接続

ssh接続をするには、まずは踏み台サーバーに接続した上でプラーベートサブネット内にあるWebサーバーにssh接続を行うといった２重に接続をしなければなりません。そこで、一回のコマンド入力によって、SSH接続できるように設定していきます。

先ほど作った".ssh"フォルダの中にconfigファイルを作成し以下のコマンドを入力します。

```
Host bastion ----------------------------------------- ①
    Hostname (踏み台サーバーのパブリックIP) ---------------- ②
    User ec2-user ------------------------------------ ③
    IdentityFile ~/.ssh/AWS_key.pem ------------------ ④

Host web01
    Hostname (Webサーバー01のプライベートIP)
    User ec2-user
    IdentityFile ~/.ssh/AWS_key.pem
    ProxyCommand ssh bastion -W %h:%p -----------------　⑤

Host web02
    Hostname (Webサーバー02のプライベートIP)
    User ec2-user
    IdentityFile ~/.ssh/AWS_key.pem
    ProxyCommand ssh bastion -W %h:%p
```

① Hostの項目には、エイリアスを登録
② 踏み台サーバーのパブリックIDやWebサーバーのプライベートIPなどを指定
③ ログインするユーザー名
④ 秘密鍵のパスを指定
⑤ 踏み台サーバーを経由してログイン

```
$ ssh bastion(サーバーのエイリアス)
```
上記のコマンドでサーバーに接続できます。

# サーバー接続エラー
今回は上記のコマンドを入力した時に、「Permissinon denied」エラーが出ました。
下記のコマンドを入力をすることで、権限を許可します。

```
$ chmod 600 AWS_key.pem
```

# 参考

http://artbyrosalia.com/blog/#:~:text=%E3%82%AD%E3%83%BC%E3%83%9A%E3%82%A2%E3%81%AF%E3%81%A9%E3%82%93%E3%81%AA%E3%83%A1%E3%83%AA%E3%83%83%E3%83%88%E3%81%8C%E3%81%82%E3%82%8B%E4%BB%95%E7%B5%84%E3%81%BF%E3%81%AA%E3%81%AE%E3%81%8B&text=%E3%81%99%E3%82%8B%E3%81%A8%E3%80%81%E4%BD%9C%E6%88%90%E8%80%85%E3%81%8C%E9%80%81%E3%82%8B,%E9%80%81%E3%82%8B%E3%81%93%E3%81%A8%E3%81%8C%E5%8F%AF%E8%83%BD%E3%81%A7%E3%81%99%E3%80%82

https://rurukblog.com/post/ssh-multi-stage/
formの値（連想配列）を受け取ってデータベース（MySQL）へ保存するまでの流れまとめ

# HTML、、ライブラリ取得用php、.env、使い回し用php、DB保存用phpを作成

# HTML
formの項目ごとにdivタグで囲む。
labelタグのfor要素と、inputタグ等のname要素が紐付いている。
id要素は複数の値があるタグ（radioやselect）で個別化できる。
昔と違い、今はsubmitはbuttonタグがあって楽。

# ライブラリ取得用php
使用するライブラリをPHP Composerが管理しており自動生成。
PHPファイルの冒頭でrequireして本ファイルを呼び出す。

# 環境変数を登録した.envファイル
DB接続情報が漏洩するとデータが盗まれてしまう。セキュリティのため、DB接続情報は環境変数化する。
PHPファイルでDB接続記述をする際、環境変数を記述するためDB接続情報の中身は見えない。

```
DB_HOST="mydb"
DB_USERNAME="myuserame"
DB_PASSWORD="mypassword"
DB_DATABASE="mydatabase"
```

# 使い回し用php
ライブラリをrequireし、環境変数に代入されたDB接続情報を取得。
使い回しできるようにするために外部ファイルになっている。

```
// 環境変数の取得
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../..');
$dotenv->load();
```

```
// 取得した環境変数は、文字の冗長化を防ぐために単純な変数へ代入して使う
// 公式曰く、「$_ENV」でも「$_SERVER」でも良い。
$dbHost = $_ENV['DB_HOST'];
$dbUsername = $_SERVER['DB_USERNAME'];
$dbPassword = $_ENV['DB_PASSWORD'];
$dbDatabase = $_SERVER['DB_DATABASE'];
```

```
// mysqliを使う場合なら、以下のように記述してDBへ接続（あとの記述で使うため変数へ代入）
$dbInfo = mysqli_connect($dbHost, $dbUsername, $dbPass, $dbDatabase);
```

# DB保存用php
## 使い回し用phpをrequire。

## DBへ値を保存する関数（DB接続情報とDB保存用SQL文を取得）を作成。

## formの値が正常ならDBへ値を保存し、DB切断する「実行文」を書く。
if文で、formの値が正常ならば（$_SERVER['REQUEST_METHOD'] === 'POST'）上記SQL文へ仕込む連想配列変数へ代入

```
// SQL文で使用するために値を連想配列へ代入
$categoryData = [
        'atai1' => $_POST['atai1'],
        'atai2' => $_POST['atai2']
    ];
```

```
// データベースに接続する
$dbInfo = dbConnect();
// データベースにデータを登録する
createCategory($dbInfo, $categoryData);
// データベースとの接続を切断する
mysqli_close($dbInfo);
```
CSSをCSS in JSに変換しよう！(ついでに色々変換できるツールの紹介)

# CSSをCSS in JSに変換しよう！
## CSS in JSを使う時の悩み
FigmaやCSS設定ツールなど、便利なデザインツールの多くはCSSを出力します。しかし、CSS in JS(JSのオブジェクトで定義するタイプ)はCSSで多いkebab-caseではなく、camelCaseで書かれる(JavaScriptの流儀に則る)ので出力されたCSSをそのまま貼り付けることができません。

- kabab-caseをcamelCaseに直して…
- 単位付きの値をクオテーションで囲んで文字列にして…
- セレクタはネストしたり、キーを文字列にしたり…

このようになかなか面倒な作業です。vanilla-extractのように型補完の効く便利なCSS in JSがあっても、この辺りが厄介でCSSがそのまま使えるCSS Modulesや、既にコンポーネントになってるMUIやChakra UIを使う理由の一つになる時があります…

最近、筆者は会社の研修でFigmaのデザインをvanilla-extractで再現することになり、Figmaなどから貼り付けたくなったので調べてみました。

## VSCode
VSCodeであれば以下のような拡張機能が提供されています。
双方向の変換が可能みたいなので、JSのオブジェクト形式をCSSに取り込めます(需要ある？)。

https://marketplace.visualstudio.com/items?itemName=Lakkannawalikar.css-converter

## Vim
以下のようなプラグインやPerlによるスクリプトが作成されていました。

https://github.com/isomoar/vim-css-to-inline

https://dev.to/acro5piano/convert-js-object-to-css-in-command-1che

## ブラウザ
ブラウザ上で変換するためのサイトが色々と提供されています。
以下は使ってみたところ、裏側の通信もないようなので、安心して使えそうです。
特に[transform](https://transform.tools)は色々な変換に対応している(CSS -> tailwindやJSON -> Zodなど)みたいなので、非常に便利そうです。

http://kachibito.net/useful-resource/css2js

https://transform.tools/css-to-js

## 最後に
同じ悩みを持ってる人は多く、探せば色々な方法が見つかりました。
個人的にはNeoVimを使用しているので、Vimプラグインかブラウザが良さげかなと思っています。

ただ今回調べての一番の収穫は、[transform](https://transform.tools)な気がします。
言語を超えて型や書式を変換できるのは非常に便利です。
個人開発で複数の言語を使う際も、一つ書けば使いまわせるようになるのが嬉しいですね。
Leetcode 989. Add to Array-Form of Integer

https://leetcode.com/problems/add-to-array-form-of-integer/description/

## アプローチ
### Brute-force

```java
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

class Solution {
    // アプローチが悪い
    public List<Integer> addToArrayForm1(int[] num, int k) {

        StringBuilder sb = new StringBuilder();
        for (int n : num) {
            sb.append(n);
        }

        System.out.println(sb);
        BigDecimal tempBigDecimal = new BigDecimal(sb.toString());

        BigDecimal tempK = new BigDecimal(k);


        tempBigDecimal = tempBigDecimal.add(tempK);
        List<Integer> result = new ArrayList<>();

        for (char c : tempBigDecimal.toString().toCharArray()) {
            result.add(Integer.parseInt("" + c));
        }
        return result;
        
    }

    public List<Integer> addToArrayForm(int[] num, int k) {
        List<Integer> result = new ArrayList<>();

        int i = num.length - 1;

        int value = 0;
        int digitSum = 0;
        int carry = 0;

        while (i >= 0 || k > 0 || carry > 0) {
            digitSum = carry;
            if (i >= 0) {
                digitSum += num[i--];
            }
            if (k > 0) {
                digitSum += k % 10;
            }
            result.add(digitSum % 10);
            k /= 10;
            carry = digitSum / 10;
        }

        Collections.reverse(result);


        return result;
    }
}
```
- [こちら](https://leetcode.com/problems/add-to-array-form-of-integer/solutions/3187352/java-easy-solution-with-detailed-explanation/?orderBy=hot)を参考しました
【Swift】WebViewに表示されない問題

# はじめに
WebViewを使っていて、表示できないサイトがありました。
原因を調べると`https`ではなく`http`だからでした。
`http`でも表示できるようにしたので記録しておきます。

WebViewはこちらのコードを使用しています。

https://qiita.com/SNQ-2001/items/d86685481b4697e81e38

# コード
```swift
import SwiftUI

struct ContentView: View {
    private let url = URL(string: "http://www.chiseki.go.jp/")
    var body: some View {
        WebView(url: url)
            .frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
    }
}
```

何も設定していないと真っ白の画面になってしまいます。

# 解決方法
① プロジェクトを選択します
② ターゲットを選択します
③ 「Info」を選択します
④ 1番下の「+」を選択します
![スクリーンショット 2023-02-15 21.49.28.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/357358f7-399e-a220-4c89-63040e3aa1df.jpeg)

⑤ `NSAppTransportSecurity`を入力します
![スクリーンショット 2023-02-15 21.52.54.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/f1d1ea95-eb07-f9f4-a308-b12655b123be.jpeg)

⑥ 矢印をタップして下向きにします
⑦ 「+」をタップします
![スクリーンショット 2023-02-15 21.54.16.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/febd2286-6423-de2d-e860-da0d3ddb5152.jpeg)

⑧ `NSAllowsArbitraryLoads`を入力します旧
![スクリーンショット 2023-02-15 21.56.15.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/ef017e20-8f25-3543-4db8-ea211eff60c3.jpeg)

⑨ 「YES」に変更します
![スクリーンショット 2023-02-15 21.57.26.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/3fcc9b15-ed60-877c-2b21-f34a28803732.jpeg)

設定終了！！

# 確認
実行してみます
表示されました！！
![simulator_screenshot_AF75F18E-94F4-4D32-B305-7C76F29D3CE6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1745371/737bde05-3105-e88a-a40a-9f1ead1313f4.png)

# おわり
これは知らないと沼りそうな箇所ですね
【Rails】３種類のラベルのうち1つは必ず選択（バリデーション）

## はじめに
現在webアプリ制作に携わらせていただいている中で調べて学んだことをアウトプットしていきたいと思います。
よろしくお願いいたします。

## 開発環境
Rails 6.0.3
Ruby 3.0.1

## 参考記事
[Active Record バリデーション](https://railsguides.jp/active_record_validations.html)
[Railsで特定の条件下で走るバリデーションを作りたい](https://qiita.com/tmzkysk/items/a0c874715ba38eb23350)


## どうしたいか
新規質問投稿時に、3種類のタグから当てはまるタグを複数選択できるようになっているが、`「投稿時にタグを1つは必ず選択させる」`ようなバリデーションを構築したい。

## ER図
questionsテーブルにlabelsテーブル、categoriesテーブル 、kindsテーブルがそれぞれ多対多の関係で紐づいています。
![Qiita.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2666919/4394d868-7537-cf1e-237b-5045f627be1c.png)

## 結果
```ruby:models/question.rb
class Question < ApplicationRecord
  #それぞれのテーブルに中間テーブルを作り多対多の関係にしています
  has_many :labellings, dependent: :destroy
  has_many :labels, through: :labellings
  has_many :category_labellings, dependent: :destroy
  has_many :categories, through: :category_labellings
  has_many :kind_labellings, dependent: :destroy
  has_many :kinds, through: :kind_labellings

  validates :title, presence: true
  # selected_label?メソッドがtrueの場合にバリデーションチェック
  validates :label_ids, presence: { message: "ラベルは必ず１つ選んでください"}, if: :selected_label?

  def selected_label?
    category_ids.empty? && kind_ids.empty?
  end

end

```
考え方を変えればもう少し早く答えにたどり着いていたかもしれません。
考え方を変え、`「３種類のラベルが全て空ではいけない」`⇒`「2種類のラベルが空の時、1種類のラベルは必須」`
この考えにたどり着き、`「category_idsとkind_idsが空の時、label_idsが空では保存できない」`という実装を思いつきました。
あとは参考記事をもとに、`presence: { message: "タグを1種類は選択してください" }`の部分でオリジナルのメッセージに変更。
`if: :method`if分岐のオプションを使用して、`method`メソッドを作り条件分岐を設定ました。
`method`では`category_ids`と`kind_ids`の値があるか確認し両方値がない場合に`true`を返します。

## 最後に
見え方や考え方を変えることの大切さを改めて感じました。考え方が固執してしまわないように「逆に考えるんだ！」の言葉を胸に開発を続けます。
【Solidity】(tips)関数に対して複数の値を受け取る方法


今回は関数に対して複数の値を受け取る方法を下記します。
2つの数字を引数として渡すと、その値をそれぞれ返す関数numと
numの関数から値を受け取り、その数字を足す関数exNumを定義します。
関数exNum内で、num関数の値を受けとるためには(型 変数名, 型 変数名)で定義します。


```
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Sample{
    function num(uint _a, uint _b)internal pure returns(uint, uint){
       return (_a, _b);
    }
    //
    function exNum(uint _s, uint _t)public pure returns(uint){
        (uint number1, uint number2) = num(_s, _t);
        return number1 + number2;
    }
}

```
【Solidity】(tips)関数内での戻り値の記載方法

関数内での戻り値の記載方法が2通りあったので下記します。
ここで、num関数のように、関数の見出しのreturnsの()内に型のみを記載するし、関数内でreturnを用いて値を返す方法が多く見られれます。

```
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Sample{
    function num(uint _a, uint _b)internal pure returns(uint, uint){
       return (_a, _b);
    }
}
```

ここで、exNum関数のように、関数の見出しのreturnsの()内に型及び変数名を記載すれば、関数内でreturnの記載はなしで、記載した変数名に値を代入するのみで関数を実行することができます。

```
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract Sample{
    function exNum(uint _a, uint _b)internal pure returns(uint number1, uint number2){
        number1 = _a;
        number2 = _b;
    }
}
```
【Docker環境】.envファイルに保存したDB接続情報の環境変数を用いてデータベースへ接続し、HTMLのformから受け取った値をDBへ保存する

# Dockerをスタンバイ

## Dockerアプリを起動

## コードのディレクトリへ cd で移動

## docker-composeを開始
```
docker-compose up
```

# HTMLを書く

## formの項目ごとにdivタグで纏める
例1
```
<div>
   <label for="name">会社名</label>
   <input type="text" id="name" name="name">
</div>
```

例2
各ラジオボタンはid名で区別
```
<div>
    <input type="radio" name="status" id="status1" value="選択肢1">
    <label for="status1">選択肢1</label>
<input type="radio" name="status" id="status2" value="選択肢2">
    <label for="status2">選択肢2</label>
</div>
```

## formのactionに移動するPHPファイルを指定し、methodは当然POST
```
<form action="next.php" method="POST">
```

# ライブラリ取得やDB接続を行う、使い回し用のphpファイルを作成

## ライブラリを呼び出すファイル（Composerが自動生成）をrequire
```
require __DIR__ . '/../../vendor/autoload.php';
```

## データベースを取得する関数を書き、冒頭で環境変数を取得する
例

```
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__ . '/../..');
    $dotenv->load();
    // 「$_ENV」でも「$_SERVER」でも良い。
    $dbHost = $_ENV['DB_HOST'];
    $dbUsername = $_SERVER['DB_USERNAME'];
    $dbPassword = $_ENV['DB_PASSWORD'];
    $dbDatabase = $_SERVER['DB_DATABASE'];
    $dbInfo = mysqli_connect($dbHost, $dbUsername, $dbPassword, $dbDatabase);


```

## 環境変数は.envファイルへ記述
```
DB_HOST="mydb"
DB_USERNAME="myusername"
DB_PASSWORD="mypassword"
DB_DATABASE="mydbname"
```

# formの値を受け取り、データベースへ保存するphpファイルを作成

## 冒頭で上記の使い回し用のphpファイルをrequire
```
require_once __DIR__ . '/lib/another.php';
```
## データベースへ値を保存
受け取った「formからの値（連想配列データ）」と「DB接続情報」を使ってMySQLへ値を保存。

例

```

$sql = <<<EOT
INSERT INTO columnname (
    atai1,
    atai2
) VALUES (
    "{$categoryData['atai1']}",
    "{$categoryData['atai2']}"
)
EOT;


if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $categoryData = [
        'atai1' => $_POST['atai1'],
        'atai2' => $_POST['atai2']
    ];
}
```
openshift（k8s）とminikubeの違いでいろいろハマった話

本番、テスト環境はopenshiftで運用している弊社ですが、営業担当より営業用に使える第三の環境が欲しいとのことだったのでminikubeで環境構築しました。
openshitの基盤自体は別チームにて構築しているため、マニフェストより下のレイヤを触るのは初めてです。

### 環境
　・Amazon EC2
　・Ubuntu 22.04 LTS

### 目標
　・本番、テスト環境のopenshiftのマニフェストをそのまま使いたい
　・多少の差分はパイプラインで吸収できる範囲としたい

minikubeの構築自体は難しいものではなく、調べたらいくらでも出てくると思います。
ここでは、openshift（k8s）のつもりでやってたらハマったポイントをご紹介

### 1. 永続ストレージのマウント
minikubeは構成上 ホストサーバ → minikube VM → k8s clusterとなっており、PODからhostPath等でホストサーバのパスをマウントしようとしてもうまくいきません。
ホストサーバのパスをminikube VMでマウントし、そのパスをPODがマウントする必要があります。
minikube開始時に下記でマウントのオプションを入れてやればOKです。
```
minikube start --mount --mount-string /LOCAL_PATH:/MOUNT_PATH
```
さらにハマりポイントなのですが、--mount-stringは一つしか指定できないようで、マウントポイントが一つになるようディレクトリ設計をする必要があります。
私の環境ではディレクトリが/のレベルで分かれていたので、パイプラインでminikube環境のマニフェストは一つのパスに集約するよう変更を行いました。

### 2. Dockerイメージの取得
minikubeだからというわけではないのですが、Dockerレジストリを別途構築し、そこからイメージをpull。ではなくてminikubeをインストールしているホストのローカルからDockerイメージを取得するようにしたかったのです。
その際、単にdocker loadやdocker buildでローカルのdockerdにイメージを追加するだけではだめで、先に出てきた構成の話と同じですが、minikube vmにdockerイメージをロードさせる必要があります。
面倒ですがdocker loadやdocker buildした後に、minikube image loadでさらにminikube vmにDocker imageをロードさせてやればOKです。
```
docker load -i xxxx.tar.gz
  or
docker build -t .

minikube image load docker-image-name:tag-name
```

### 3. Routerが存在しない
これはopenshiftとk8sの違いです。。。openshiftにはホスト名とURLにより、Serviceへのルーティングを行ってくれる機能があるのですがk8sにはないので変更しました。
もともとService定義をClusterIPにて行ってましたが、NodePortへ変更しています。

### 4. NodePortにアクセスできない
NodePortを構成するとk8sクラスタの外からアクセス可能となりますが、私はホストサーバのIPに対してアクセスしていて30分くらいハマりました。。。
minikubeが公開しているIP、URLにアクセスする必要があります。minikube vmのプライベートIPなのかな。。。ちゃんと調べてないです、すみません。
minikube service listコマンドで出てきたURLにアクセスすればOKです。
ただし、当然minikubeが動作しているホスト上からしかアクセスできないので、さらに外からアクセスさせたい場合は、nginxでプロキシさせたり、LBを作れば良いかと思います
```
$ minikube service list
|-------------|----------------------|-----------------------------|
|  NAMESPACE  |         NAME         |             URL             |
|-------------|----------------------|-----------------------------|
| default     | myapp-service        | http://192.168.10.10:30010  |
|-------------|----------------------|-----------------------------|
```

### 番外編 Proxyを切ったり張ったりが怠かった
私の環境は認証プロキシを通さないとインターネットに出られないのですが、環境構築の中でプロキシ設定が必要な場面と設定してはいけない場面がありました。

■プロキシが必要
　curl, aptなどのパッケージインストール
　minikube start （おそらくDocker Hubへ接続している）
■プロキシを設定してはいけない
　kubectl全般 （ローカルのminikube APIサーバへ接続しないといけないが、外に出ようとしてしまう）

NO_PROXYなどでminikube宛の通信はプロキシ使用しないよう設定すればよいと思います。

今回は断片的な情報になりましたが、時間があれば一連をまとめて公開します。
【Solidity】(tips)引数の指定方法


今回は引数の指定方法に関して、メモします。
2つの数字を返す関数numと、num関数を呼び出すexNum関数を定義します。
exNum関数の中でnum関数を呼び出す際に、引数を指定する場合は下記のようになります。
exNum関数に(1,2)の順番で引数を渡し実行すると、(1,2)の順番で値を返します。

```
pragma solidity ^0.8.17;

contract Sample{

    function num(uint _a, uint _b)internal pure returns(uint, uint){
        return (_a, _b);
    }
 
    function exNum(uint _s, uint _t)public pure returns(uint, uint){
        return num({_a:_s, _b:_t});
    }
}
```
ここで下記のようにexNum関数内で呼び出しているnum内を変更し、
exNum関数に(1,2)の順番で引数を渡し実行すると、(2,1)の順番で値を返します。
このようにnum({_b:_s, _a:_t})で渡す値を指定できます。

```
pragma solidity ^0.8.17;

contract Sample{

    function num(uint _a, uint _b)internal pure returns(uint, uint){
        return (_a, _b);
    }
 
    function exNum(uint _s, uint _t)public pure returns(uint, uint){
        return num({_b:_s, _a:_t});
    }
}
```
Windows10 の WSL2 で USB が反応しないときの対処法

# 背景

Jetson 用に WSL2 を用意した際に、SDK Manager で書き込みをしようとしたところ、デバイスを認識してくれなかった。

なんでやーってなって調べたところ・・ WSL2 では Windows 11 でないとデフォルトで対応してないそうな。

ってことで、対処策の備忘録

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/db456ad2-5111-c148-1f7c-3922181d4801.png)

# 対処策

- [usbipd](https://github.com/dorssel/usbipd-win) を利用する
- その為に、winget をインストールする

## winget インストール

power shell で winget を実行して使用法が表示されればここは不要

なかった場合には、以下のような感じで入れる。

```powershell: winget 追加
Add-AppxPackage -RegisterByFamilyName -MainPackage Microsoft.DesktopAppInstaller_8wekyb3d8bbwe
```

詳細は以下で

https://learn.microsoft.com/ja-jp/windows/package-manager/winget/

## usbipd インストール

1. PowerShell で以下を実施して install 
   ```powershell: winget を使って usbipd インストール
   winget install --exact dorssel.usbipd-win
   ```

   :::note info
   --interactive を付けると、再起動が必要な場合も止められます
   :::
1. PowerShell の再起動
1. PowerShell でデバイス一覧を表示する
   ```powershell: デバイス一覧
   usbipd list
   ```
   こんな感じで一覧が出る
   ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/120072/188bb1f3-a5eb-631e-b985-10f773fc06af.png)

1. wsl を起動して、Ubuntu 内で USB 機器接続。
    ```bash: 上の例での、接続例
    usbipd wsl attach --busid "1-14"
    ```
1. 接続したかの確認は、Ubuntu で以下
    ```bash: USB一覧
    lsusb
    ```
1. 必要なら解除は、<code>detach</code> で
    ```bash: 上の例での、解除例
    usbipd wsl detach --busid "1-14"
    ```

https://learn.microsoft.com/ja-jp/windows/wsl/connect-usb


# あとがき
これで jetson も認識してくれたので、NVIDIA SDK Manager で書き込み出来るようになった。

こっから・・ROS2 や C++ Cmake などまだまだ長い道のりが・・ :laughing:
円の面積

円は正∞角形なので、
円に内接している正∞角形の面積を求めた後に
円に外接している正∞角形の面積を求めます。
面積の大きさは、
円に外接している正∞角形＞円＞円に内接している正∞角形
なので、挟み撃ちの定理を用います。
nを3以上の自然数とします。
半径がrの円に内接している正n角形の面積(ISn)は
(1÷2)*r2*sin(2ϖ÷n)*n
です。
半径がrの円に外接している正n角形の面積(OSn)は
(1÷2)*[r÷{cos(ϖ÷n)}]2*sin(2ϖ÷n)*n
です。
(OSn)÷(ISn) = [1÷{cos(ϖ÷n)}]2 となり [1÷{cos(ϖ÷n)}]2＞1 から常に(OSn)＞(ISn)になります。
また微分の結果、ISnはnが大きくなるほど面積が増え、OSnはnが大きくなるほど面積が減ります。
即ちISnはn=∞で最も大きくなり、OSnはn=∞で最も小さくなります。
ここで2*ϖ÷n=Kとすると
lim(n→∞)ISn = lim(k→0){sin(k)÷k}*ϖ*r2 → ϖ*r2
lim(n→∞)OSn = lim(k→0){sin(k)÷k}*ϖ*r2*[1÷{cos(k÷2)}]2 → ϖ*r2
挟み撃ちの定理により、円の面積 = ϖ*r2 となります。
結論ですが、円の面積を求めるには
円に内接及び外接している正n形の面積
外接している側が内接している側より常に面積が大きい事実、即ちnが幾つであっても追い抜かれない事実
内接している側はnが∞に近づくほど面積が大きくなり、外接している側はnが∞に近づくほど面積が小さくなる事実
以上が必要になるのです。
JetBrains IDEのFind in Filesの上限を変更する

# 前提とするIDEとversion
```
InteliJ IDEA 2022.3.2
```

# 設定箇所
`Settings | Advanced Settings | Maximum number of results to show in Find in Files/Show Usages preview`

![Screenshot from 2023-02-15 20-25-13_2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/196806/3430a198-263f-2439-11b6-677ebc659940.png)

⚠メモリ使用量が大幅に増える可能性があるとのこと


# 古い記事について

`Edit Custom VM Options...`で`-Dide.usages.page.size=1000`とやったり、`Registry...`で`ide.usages.page.size`に`1000`を設定する記事がありますが、前提とするversionのIDEではこの方法で設定できないようです。

# 参考

https://stackoverflow.com/questions/44803519/can-i-adjust-the-100-matches-in-x-files-from-intellijs-find-in-path
エンジニアインターン15日目

今日は完成させたスクレイピング機能を自社アプリの管理画面から使えるような仕組みを作ることになった。使う言語はVue.jsで、初めての言語だったため、コードを読み解くので精一杯だった。まじで頭抱えながらやっていたが、なかなか進まない…こんな時に頼るのはやはり先輩エンジニア！一緒にコードを読み解いてくださったり、これから実装していくタスクのこともイメージしやすく説明していただいたりほんとに助かる存在だ。でも、自分一人でも読み解けるようにならないといけないとも思っている。でもできない。とにかく今はたくさんコードを観て、たくさんコード書いて、成長していくことがとても大切だと感じた。いまはほんとに頑張り時だなと改めて思った。今日は作業もあまり進まず、技術的なことは書くことがない…まあ頑張らないといけないってことだな。
【転職活動】面接で聞かれたこと書いてくで（前半）


## この記事を書こうと思ったきっかけ

自分の整理のためと皆さんの参考になればという思いで記載します。
最近やっと書類選考を通過しまして、面接に漕ぎつけましたので
その会社でどんなことを聞かれたか書いていきます。

エンジニアになるべく転職活動中ですが、
某転職サイトで２０２２年１２月ごろから３０社以上応募をして
２０２３年２月にようやく１社書類通過しまして面接してくれる会社が現れました。



## まずは当方のスペックから。

現在無職。
前の職場では８年くらい働いてました。
２０２３年２月１６日現在、３５歳です。

ITと全然関係ない業界で事務してました。
２０２２年８月末に退職、現在に至るまで無職。

エンジニアになりたいのですが業務未経験です。
再就職に向けて２０２２年１２月から重い腰を上げて就職活動を開始しました。スキルアップのため２０２２年３月からプログラミングスクールに通ってます。PHP、JavaScript、JQuery、HTML、CSSを勉強中。

実力はまだ初級レベルです。
IT業界、全くゼロからのスタートです。
IT系の仕事で即戦力にはなるにはまだたくさん勉強が必要です。

## 面接を受けた会社について

イベント系、サービス業の会社
社内DX化推進中

今回の募集ボジションとしては、社内のインフラ整備や非IT職の社内スタッフに対するPCリテラシー研修などなどの担当者を募集。


## 実際に聞かれた質問たち

まずは面接官から会社の概要を５分〜１０分ほど紹介がてらお話をいただきました。その後、当方への質問タイムに入りました。
それでは、実際に聞かれた質問を箇条書きで書いていきます。

+ <b>今までのキャリアを教えてください</b>
+ <b>なぜ卒業から就職までギャップがあるのですか</b>
+ <b>なぜ転職活動しているのですか？きっかけは？</b>
+ <b>学生時代、社会人時代でリーダー経験はありますか？</b>
+ <b>人生で一番苦しかった経験はなんですか？</b>
+ <b>今まで何かに夢中になった経験があれば教えてください</b>
+ <b>今後どんなキャリアを積んでいきたいですか？</b>

された質問に対して当方の回答を踏まえてさらに
質問が飛んではきましたが上記が質問の主な概要となります。

一旦こちらで記事の前半終了とさせていただきます。
後半には当方が実際にどのように答えたか、
その答えを踏まえて面接官からどんな追加の質問をされたかを
もっとこう答えればよかった、など
当方の反省も踏まえながら書いていきます。

ここまでお読みいただきありがとうございます。
後半もぜひお読みいただければ幸いです！
Elasticsearchの検索でscoreの最小値を指定する方法

検索結果が異常に長いため、特定のスコアで足切りしたい....
以下のように、`min_score`を指定することで解決できます。

ex)  score=8.0 で足切り
```
GET /{index_name}/_search
{
  "from":0, 
  "size":100,
  "min_score": 8.0,   <= ココ
  "query":{
    ...省略
  }
}
```
配列からランダムに配列の要素を表示する

配列からランダムに配列の要素を表示するサンプルプログラムを実装しました。

```Powershell
#########################################
########## Powershell  ##################
######### ランダムに配列から文字を表示###
###### 新規作成 2023/2/15          ######
#########################################


$input_ans = 0
$ans = Get-Random -Minimum 0 -Maximum 6
$cnt = 0
$sw = 0
$array1 = @('秋元真夏','白石麻衣','西野七瀬','生田絵梨花','齋藤飛鳥','松村沙友理','桜井玲香')

echo $array1[$ans]

```
TSUTAYAの置き土産のその後について

こちらの記事を投稿してから2年経ったので、アプリのその後についてお話しします。
[TSUTAYAでアルバイトしていた学生エンジニアが退職するので置き土産に業務効率アプリを開発した話](https://qiita.com/apple-yagi/items/59b626a371ea80cdee6e)

先に言っておくと、本アプリは自分が業務時間外に勝手に作ったものなので、完全に自分の著作物です。TSUTAYA側とは何の契約（秘密保持契約等）も結んでいません。また、TSUTAYA側の業務情報には自分は全くアクセスすることができません。自分が本アプリを通じて知ることのできる情報は、店頭に並んでいる商品の商品名と賞味期限だけです。

※ 本記事で出てくる「TSUTAYA側」というのは、自分が働いていたTSUTAYAのフランチャイジー、又はTSUTAYAを運営している[CCC](https://www.ccc.co.jp/?sid=p_000_000)のことを指します

## アプリのその後について
現在もバリバリ使用されており、月に1000件以上、商品の賞味期限をLINEに通知しています。
自分が使用しているLINE Botのプランは無料プランで月に1000件までしかメッセージを送ることができないので、先月は一時LINE通知が止まる事態まで起きてました。
![スクリーンショット 2023-02-14 1.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/533652/fc740736-587a-c875-ffbf-f34fa4c08323.png)
20日くらいで1000件送り切ってしまってました。。

この時は賞味期限が近づいてきた商品1つにつき1件のLINE通知を飛ばしていましたが、今はある程度の商品の情報を1件のメッセージにまとめてから通知するようにしたので大丈夫そうです。

皆さんが気になっていたであろう運用・保守については今も自分がやっています。
とは言っても、インフラ周りは全てFirebaseで構築しており、その他の外部サービスもLINE Botしか使っていないので、インフラ周りで何かしら作業が発生したことや落ちたことはこの2年間ありませんでした。
アプリケーションの方では先ほどお話ししたLINE通知を送信するロジックを変えたこと以外は特に触っていません。
元々運用・保守をしなくても済む構成にしていたので、この結果は想定通りでした（LINE通知が月1000件を超えたこと以外は）。

気になる費用の方もFirebaseしか料金が発生するものを使っていないこともあり、年間0円で運用できています。
こちらもFirebaseはある程度の規模まで大きくならないと料金は掛からないことを知っていたので、想定通りでした。

また、セキュリティに関して気にされていた方もいらっしゃったかもしれませんが、突然データが消えたや変なLINEが来たみたいな不思議事象は報告されていないので大丈夫だと思っています。そもそも不正アクセスをされても、店頭に並んでいる商品の商品名と賞味期限しか見れないので、そこまでセキュリティを気にしていませんでした（前提として本アプリにはFirebase Authenticationで実装されたログイン機能があり、XSSなどもある程度は対策しています）。

## FAQ

### TSUTAYAの名前を出してQiitaを書くことは許可を得てたんですか？
許可は得ていませんでしたが、記事を出した後に[CCC](https://www.ccc.co.jp/?sid=p_000_000)の社員の方とお話しする機会があり、その時に特に問題はないですと言ってもらえました。

### Excel管理じゃダメだったんですか？
自分が実際に商品の賞味期限を管理して感じていたことは、賞味期限を確認するということはとても億劫ということでした。
エンジニアの方なら分かるかもしれませんが、Unit Testなどをコミット or プッシュするたびに回すのは億劫じゃないですか？
だからCIとかで自動でテスト回すようにしませんか？

商品の賞味期限を管理するのも同じで、商品が入荷したときのフローに賞味期限を入力するのは（エンジニアがテストを書くのと同じく）やるんですけど、その後の賞味期限を確認する作業は億劫なんですよね。これは紙でもExcelでも同じことでした。

自分が解決したかった課題はそこだったのでLINE Botで賞味期限を通知するという構成にしました。

あとExcelで管理することの問題点はExcelの起動が遅いというところにありました。これは使用しているPCのスペックの問題だと思ってますが、起動が遅いと入力するのも億劫になるので紙でパパッと書けた方が逆に便利というところもあり、あえて紙で管理していました。
こういうこともあって、アプリの表示速度を気にしてました。

### TSUTAYAにアプリを移管しないんですか？
今のところ考えていません。運用負荷やコストを考えてもこのままが一番上手くやっていけると思っているので、移管したいとも特に思っていません。
ただ、TSUTAYAを既に退職している人がアプリの運用・保守をし続けているところに違和感があるというご指摘は、全くもってその通りだと思っています。

### 全国のTSUTAYAで使われているんですか？
自分の働いていたTSUTAYAはフランチャイズ店なので、全国的に使用はされておらず、今後されるという話も聞いていません。フランチャイズ関連のTSUTAYA数店舗でのみ使われています。
逆に全国のTSUTAYAで使われるようになってしまうと、インフラのコストやLINE Botの利用料がかなりかかってしまうので、そのときは移管することを考えます。

### POSで賞味期限を管理できないのですか？
おそらく賞味期限を管理できるPOSは世の中に存在しないんじゃないかなと思っています。もしあれば、スーパーやコンビニの従業員の方があんなに店頭商品の賞味期限を確認しに行ってる姿を見ることはないと思うので。

## まとめ
置き土産のその後はいかがでしたでしょうか？自分の中では色々と上手くいったと思っています。
個人的に上手くいった理由は、解決したい課題が明確で単純、実運用を考えた構成、その職場で実際に4年間働いた経験の3つがあったからだと思っています。特に実際に働いた経験があったことが一番重要だと思っていて、これがあったからこそ現場のリアルに答えたアプリを作れ、今もまだ使われ続けてるのだと思っています（実運用を考えた構成については、自分はインターンなどで開発をした経験などはなかったので机上の空論でしたが）。

ただ、これだけを見ると君損してない？と思われる方がいるかもしれません。
実際にはそんなことはなく、このアプリを作ってQiitaで紹介したことにより、繋がりが出来た人もいますし、自分のポートフォリオとして十分なものとなってくれています。
また元々使って欲しくて作ったアプリが実際に2年間も使われていて、それで少しメンテナンスするくらいは全然嬉しいことです（逆に使われてなくてcloseする方が悲しい）。
なので、これからも利用してくれているユーザーがいる限りは運用していこうと思います。
[FastAPI] 依存性注入って結局なんで使うんじゃい？

# この記事の目的
- FastAPIにおける依存性注入についてわかる
- 依存性注入を利用することによるメリットがわかる
- 具体的な実装例を知ることができる

# 記述しないこと
FastAPIの書き方

# 依存性注入とは
依存性注入はクラスや関数の引数としてオブジェクトを渡すことで、そのオブジェクトに依存する別のクラスや関数を呼び出すことができるようにするデザインパターンの一つだよ
FastAPIの場合はAPIのエンドポイント関数やビジネスロジックの関数に必要なデータを自動的に提供することができるよ
FastAPIでは、関数に必要なデータを引数として宣言するだけで、FastAPIが自動的に依存関係を解決し、必要なデータを提供してくれるよ
例えば、APIのエンドポイント関数であれば、HTTPリクエスト情報やデータベースコネクションを引数として宣言することができ、FastAPIが自動的にこれらのオブジェクトを生成し、関数に渡してくれるよ

### 依存性注入によって、アプリケーションのコードがよりスマートでシンプルになり、テスト容易性が向上するというメリットがあるんだよ！


# 言葉では何いうてるかわからんし実装例見てみよかぁ〜
FastAPIで依存性注入を使用し、MyServiceクラスをインスタンス化する例だよ

```dependency_injection.py
from fastapi import Depends, FastAPI

class MyService:
def __init__(self, db: Database):
self.db = db

class Database:
def __init__(self, host: str, port: int):
self.host = host
self.port = port

app = FastAPI()

# Databaseの依存性を定義する
def get_database():
return Database(host="localhost", port=5432)

# MyServiceにDatabaseの依存性を注入する
@app.get("/")
"""
serviceはインスタンス化されたMyServiceオブジェクト
Databaseの依存性はget_database()関数から自動的に解決されるよ
"""
async def root(service: MyService = Depends(get_database)):

pass
```

MyServiceクラスにDatabaseクラスのインスタンスを注入することで、MyServiceクラス内でデータベースに関する処理を実装することができるよ
たとえばね、データベースからデータを取得することやデータを更新する、削除する、新しいデータを作成するなどの操作が可能になるんだ！
また、依存性注入により、テストの容易性が向上するよ
依存するオブジェクトをモックオブジェクトに置き換えることができるため、単体テストをより簡単に実行できるんだ！
これによりMyServiceクラスの振る舞いをより確実にテストし、品質の高いコードを実現することができるよ

## つまり依存性注入のメリットって？？
1. テスト容易性の向上：依存するオブジェクトをモック化することで、依存先のオブジェクトの振る舞いをコントロールしやすくなり、単体テストが容易になるよ！
1. 可読性・保守性の向上：依存関係が明示的に宣言されるため、コードの可読性が向上するよ。また、依存性が分離されることで、コードの保守性が向上するよ！
1. 柔軟性の向上：依存先を容易に入れ替えることができるため、アプリケーションの柔軟性が向上するよ。例えば、データベースの実装を変更する際にも、依存性注入を使うことで、変更が容易になるんだ！
1. 再利用性の向上：依存関係が明示的に宣言されるため、依存性のあるコンポーネントを他のアプリケーションに再利用することが容易になるよ！

# う〜ん、実装例が少ないなぁ。じゃあもう一つ見てみようか！
```dependency_injection_sample.py
from typing import Union

from fastapi import Depends, FastAPI

app = FastAPI()


fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


class CommonQueryParams:
    def __init__(self, q: Union[str, None] = None, skip: int = 0, limit: int = 100):
        self.q = q
        self.skip = skip
        self.limit = limit


@app.get("/items/")
async def read_items(commons: CommonQueryParams = Depends(CommonQueryParams)):
    response = {}
    if commons.q:
        response.update({"q": commons.q})
    items = fake_items_db[commons.skip : commons.skip + commons.limit]
    response.update({"items": items})
    return response
```

このコードの場合、FastAPIのDependsデコレータを使用して、CommonQueryParamsクラスを依存関係として注入することで、クエリパラメータの値を簡単に取得できるんだ
CommonQueryParamsクラスは、q、skip、limitの3つのパラメータを解析し、それぞれの値をインスタンス変数に割り当てるため、APIの実装を簡素化できるよ
また、DependsデコレータによってFastAPIがクエリパラメータを検証してエラーを返すため、APIの安全性も向上するんだよね
つまりは依存性注入により、このAPIの実装はより明確になり、保守性やテストのしやすさが向上し、コードの品質も改善されるため、依存性注入が行われていると考えられるんだ！

# 参考
- [Dependencies - First Step](https://fastapi.tiangolo.com/ja/tutorial/dependencies/)
- [Classes as Dependencies](https://fastapi.tiangolo.com/ja/tutorial/dependencies/classes-as-dependencies/)
- [Python Fast APIで依存性注入をどう使うかまとめてみた](https://qiita.com/nakapar_/items/83eda50cca5c68209e0c)
乱数を発生させて円周率を計算する

# はじめに
　乱数を発生させて円周率を計算できるというのを知っていましたが、初めて実装しました。新規性も何もないですが、matlabでの実装法を知りたい人は御覧ください。
# 円周率を計算する方法
まず、どのように円周率を計算するか説明します。
ある正方形に円が内接している場合を考えます。円の面積は次のとおりです
```math
S_{circle} = \pi r^2
```
次に正方形の面積は次のとおりです。
```math
S_{square} = 4 \times r^2
```
したがって、正方形における円の面積比率は次のとおりです。
```math
　S_{rate} = S_{circle} / S_{square} = \pi/4
```
つまり、正方形型の乱数を発生させ、円の中に入る確率が$\pi/4$となります。

![circleandsquare.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3035813/10d3805d-afd1-3e19-ef46-3cc995e7b4c0.png)

# 実装
それでは、matlabを使用して円周率を計算します。
今回は乱数を-1~1で発生させます。内接する円は(0,0)を中心とした半径1の円です。
## 正方形の乱数を発生させる
　まずは正方形の乱数を100個発生させます。
```
N = 100
x = 2*rand(N,1)-1;
y = 2*rand(N,1)-1;
```

## 円を定義し、確認する
　この項目は必須ではないですが、円を定義し、乱数との関係を整理します。
```
cx = 0; cy = 0; % 中心
r = 1;           % 半径
hold on 
scatter(x(1:30),y(1:30));
t = linspace(0,2*pi,100);
plot(r*sin(t)+cx,r*cos(t)+cy)
axis square 
```
　このコードを実行すると次のような図が出てきます。乱数が円の中に入っていたり入っていなかったりします。

![rand.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3035813/ff5356e8-fc03-5550-00ce-7bea341fc10d.jpeg)

## 円に入っているか判別し、数を数える
円の中心からの距離を求め、その距離が半径より小さい場合は円の中に入っていると考えます。
```
dist = sqrt((x-cx).^2 + (y-cy).^2);
n = length(find(dist<r));
```

## 円の中に入っている数を計算し、円周率を求める
ここまでで、円の中に入っている乱数の数がわかりました。
ここから、円周率を求めます。
```
calc_pi = n/N * 4
```

# 結果
計算したところ次のようになりました。
N=100のとき3.52
N=1000のとき3.156
N=10000のとき3.13
N=100000のとき3.1427
このように乱数の数が増えていくにつれて真の値（3.1415…）に近づくことがわかりました。なお、乱数ですので、上記値は演算を行うたびに変わります。この値がどのような散らばりを持つかなどは統計学を学ぶ必要があります。

# 感想
初めて乱数を用いた計算をしてみました。乱数はこのようにとにかく数をこなしてみるという活用がありそうです。つまり、平均がどこに収束するか、乱数によりどれくらい値がばらつくかなどを評価できそうです。