OmniAICreator/Qiita-1.07M huggingface dataset:
Power Apps 基本

# はじめに

業務アプリで検索して詳細を確認できるだけの簡単なアプリを簡単に作りたいなぁってことがありました。
Fluterって選択肢も一瞬浮かんだんですが、ローコードでWebで見れるだけでも良いのでつくりたいなぁと。一番は時間をかけたくない。
で、Power Appsでやってみることにしました。Power Pagesも今度試したいなぁと思いながら今回はPower Appsで。

# 実装

全く知識のない状態からローコードで簡単に作れるものだろうか。

https://www.microsoft.com/ja-jp/power-platform/products/power-apps

左のメニューから作成を選択し、空のアプリを作成します。

## データベース接続

今回は業務アプリでDBが存在していてそこから検索アプリを作成します。
DBではなくて、Excelであっても他のデータベースであっても大きくは変わりません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/be9b730b-297b-3251-f449-66eb6e2159ad.png)

## テーブル

レイアウトからテーブルを選択しキャンバスにドラッグアンドドロップします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/6de13e3d-667a-1142-a2b1-2ca0a5de8bed.png)

右側のプロパティ設定または、上部の関数入力欄に取得する情報を入力します。
どちらで入力しても良いのですが、上部の関数入力欄が良いのかなとは思います。だけど、左のドロップダウンリストで何が選択されているのか確認しないと間違った項目を編集してしまうことがよくあります。

itemsに入力

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/259d905e-5d7b-bc40-c7f8-95d7d4977b25.png)

ドロップダウンでItemsを選択

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/567564b7-a382-1e83-19da-4e7fe449e16a.png)

### 関数の説明

itemsに関数が設定されています。SQLで絞り込みたいところなんですが、そこはローコードツールと言ったところでしょうか？エクセルライクな書き方になります。

```
FirstN(
    Sort(
            Filter('hoge', moge=1),
            created_at,
            SortOrder.Descending
        ),
        1000
    )
```
ネストの最深部から確認します。

Filter関数で、第一引数にデータソース（ここではデータベースのテーブル名）を指定、第２引数に条件を指定しています。
Filterが複数条件になったときは、かなり癖があって、ここに一番時間がかかりました。

プログラマおなじみの || && Or を組み合わせます。||は最初がtrueなら後ろは評価されない。&&は最初がfalseなら後ろは評価されない。を利用してfilterを追加していきます。

Sort関数で、第一引数にデータ、第二引数に並び替える列名、第三引数に降順を指定しています。

全件表示すると時間がかかるので、FirstN関数で上位1000件を取得しています。

## フィールド選択

テーブルの列を選択します。
右側のプロパティで表示する列を選択したり、並び順を変更したりできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/e8db6385-47ed-e645-9569-8405127fc93d.png)

Tableにはステータスなどはコードで登録されていることはよくあります。そういった時は、関数を使ってわかりやすい名前に変更します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/d71225c9-473c-aa96-ec27-0f35304cf198.png)

左のメニューで変更したい項目を選択して上の関数に関数を入力 (左、右、上のどこを操作すればいいのか慣れるまでよく迷子になる）

## OnSelect

javascriptyと同じでそれが選択されたときのイベントを設定します。

```
Navigate(Details, ScreenTransition.Fade, {selectedId: hoge.Selected.id})
```

選択されたら詳細ページに遷移させます。

3つ目の引数は、パラメータ。コンテキスト変数と言うらしい。JSONで渡します。
受け取ったページでは、変数名を直接利用できます。
ここでは、selectedId　を利用できます。

## JSON

MySQLでJSON型の列があって、それをきれいに表示したいなと言うことがありました。
ここではテキストからJSON型にキャストして利用する方法を記載します。
つまりは、DB関係なくJSONを扱う方法を記載します。

```
ForAll(
    ParseJSON("{""hoge"": ""1"", ""moge"": ""2""}"),
    {
        new_hoge: Text(ThisRecord.hoge)
    }
)
```

ParseJSON関数にJSON文字列を設定します。(DBから取得した文字列や、APIを実行した結果のJSONなど）
第二引数で新たにJSONを定義してあげます。
これで、new_hogeがりようできるようになります。

つまりは、ParseJSONでJSON型に変換してもそこにどんなkeyやvalueが入っているか不明なため、Power Appsが理解できるようにJSONを作成してあげる

# まとめ

かなりの部分を端折ったのですが、少しでもエンジニア経験があれば、初見でも何となく作れてしまうのがローコードの良いところ。痒いところに手が届かないこともあるけど、簡単なものは簡単に作れるのはやっぱりいいなと思う。

今回は参照系のアプリを作ったのですが、これをフォームにして更新、新規作成もできるようにするのにもわりと簡単にできてしまいます。
Microsoft Forms + Azure Logic Apps + Azure Data Factory

# はじめに

管理画面を作成して、パラメータ指定してAzure Data Factoryを実行したいなアと言うのがあったのですが、管理画面作るのめんどい。APIでAzure Data Factoryを実行するのも認証とか実装するの時間かかりそう。誰が実行したとかの履歴管理とかもめんどくさい。

そこで考えたのが、タイトルにもなっているMicrosoft Formsから登録して、Azure Data Factoryを起動できれば簡単に作れるのでは？と思い試してみました。

結論から言うと、半日くらいで作れました。

# 実装

まずは、Microsoft Formsを用意します。

## Microsoft Forms

https://forms.office.com/Pages/DesignPageV2.aspx

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/dd57bdb1-9354-d0d6-bec1-46a4737cca5a.png)

回答できる人を限定することでAzure Data Factoryを実行できる人を限定できます。
また、アンケート結果に名前を記録するようにすれば、いつ誰が実行したのかをエクセルで管理することができます。

## Logic Apps ロジックアプリデザイナー

①Forms受信をトリガーとする
フォームIDを選択して登録する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/9b2716ce-87fe-5276-0390-53fdcdf94aca.png)

②応答通知の一覧を取得する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/0e601f15-2c48-bdc9-9f80-4f824a6f2101.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/7a8e898a-b7f9-1d77-fa43-72322ce36c31.png)

③質問と回答を使って変数の値を設定していく

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/ca6d9d7e-0ae4-17f6-4d8e-cb797dc82e75.png)

④データファクトリーを選択してパラメータを設定する
パラメータにjsonでADFのパラメータを指定する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/2a1c0aa6-7991-f8e5-b911-17a3a006367c.png)

⑤フォームから送信するとLogic Appsが実行されたことを確認できる

# 独り言

管理画面を作成することを考えるとかなりの工数削減ができた。
ログイン周りやセキュリティ周りの実装も設定だけで何とかなってるし。
利用者が限定されて利用者が少ない管理画面はこんな感じで作ってしまうのはありだなと思う。
今回はAzure Data Factoryを実行したが、Azure Functionsもできるだろうし、Windows環境、Microsoft製品を使っているところではありだなと思いました。
Azure Logic Apps基本

# できること

・フォルダの監視 (ポーリングします）を行い、ファイルが追加された編集されたなどをトリガーとします
・ファイルのコピー
・Azure Functionsの実行 HTTP トリガーのみ
・タイマー実行
・フォルダ作成
・Blobとの連携
・Sharepointとの連携
・Office製品との連携

などいろいろできます。
AzureなのでWindowsとの相性は良いです。Windowsでファイルの移動やバックアップを取ったりするのに昔ならバッチプログラムをVBScriptでつくってタスクスケジューラに登録したりってのが多かったかなと思います。

今回のLogic Appsの基本を押さえることで世の中で言われるRPAやローコード、ノーコードを理解するきっかけになればと思います。

# 実装

Blob Containerに一時間に一回アクセスしてCSVファイルをsharepointにコピーする。
タイマー実装としたのは、フォルダの監視の場合、もちろんフォルダを指定する必要があり、今回、動的に日付フォルダが作成されるため作成時にフォルダを指定する方法がわからなかったため。

## タイマー

特に困ることはないと思います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/e3f980b0-a21f-853f-7246-9cf69f95d16b.png)

## 変数の設定

変数の設定（初期化）は最初に行う必要があります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/2a397907-a678-0300-7640-cd36e81e446c.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/3d59e2b5-8054-cf01-5e1f-3fd6bb9c76fe.png)

## try-catch-finally

エラーが起きた時に実行ログにエラーと残ってもよい場合は実装する必要はないですが、想定内のエラーは成功としてログに残したいときはtry-catch-finallyを実装します。
制御のスコープを使います

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/9b818ac1-21d8-8cf3-0f35-22bfb229bc39.png)

catchスコープの実行をtryスコープが失敗したときに設定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/feb291bf-bd02-9177-2c96-66e5568c7724.png)

catchの次のアクションの実行は、catchがスキップしたときに設定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/14847db0-1da4-b85d-e812-ce91f3d47f4d.png)

## if

if文で処理を分岐します。
上記 try-catch-finallyと組み合わせた場合、tryスコープでエラーが起きてcatchスコープで変数にfalseを設定します。
条件分岐でtrueパートにアクションを追加し、falseパートに何も書かなければそこで処理終了となります

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/30ea01f3-7789-bfb7-ef78-c9436cfd8aec.png)

## BLOB一覧を取得

BLOBのフォルダ以下のファイルを取得する場合、メタ情報だけを取得し、ループさせながら一つ一つ処理する必要があります。
まずは、一覧を取得します。
フォルダが動的に作成されるため、concatと変数を利用しました。

## メタ情報をループ

valueがループされた情報になります。if文などで、valueの情報を取得できるようになります。以下はNameを取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/9c20b643-0413-28b7-121d-1b0d7fee797e.png)

ファイルがcsvのものだけコピー対象とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/8f5d3291-3ff1-2a5e-fb69-93db49a19d22.png)

## ファイルコンテンツ取得

ここまででファイルのメタ情報を利用していたためファイルのコンテンツは取得していません。ここでコンテンツを取得します。
メタ情報のパスを利用してコンテンツを取得

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/11235a72-f124-ee66-d863-f5af0f9413e9.png)

## sharepointにファイルを作成

取得したコンテンツをsharepointにファイルを配置。
感覚的にはコピー＆ペーストなんだけど、おそらく、sharepointとblobのAPIを使ってやっているので、ファイルを作成することに注意する

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/984f2c33-d7b2-ce56-0a6f-781e697523ec.png)

ファイルが存在するときはエラーとなるのでtry-catchでエラーがログに残らないようにする

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3121550/4186fa77-6077-6845-54ab-c65a707e2db0.png)

今回は同名ファイルを作成できないことをエラー処理とした。ファイル存在チェックを入れてもいいかも。

# 独り言

正直プログラムが書けるならプログラム書いた方が簡単だと思う。
だけど、プログラムの保守メンテナンスの担当にはなりたくない。
なので、こういったローコード、ノーコードを使うのが後々の自分のためになると思う。
非エンジニアがこれをメンテナンスしてくれるとは思えないけど。
AWSサーバ公開の備忘録

# 何の記事？
AWSサーバを構築して、ドメインやネットワークの設定もしたはずなのにアクセスできない！
を解決する方法の記事
（解決を確約するものではないのでご了承ください）

# 何があったの？
Route５３でドメインを発行して設定し、EC2でインスタンスを立てて諸々設定したのに、ドメインにアクセスできなかった（「応答時間が長すぎる」と表示される）

# 解決方法
1. Apacheをインストールする
2. セキュリティグループの設定を追加する

## 1. Apacheをインストールする
飛んできたリクエストを仕分ける人が居ないんだから、そりゃWebページの表示なんかできないよね。

以下のコマンドをコピペで実行すればOK
```
sudo apt install apache2
sudo systemctl start apache2
sudo systemctl enable apache2
```

## 2. セキュリティグループの設定を追加する
インスタンス作成時の設定次第では、HTTP/HTTPS通信が許可されてない状態となる。
ということで、インスタンスのセキュリティグループの設定を変更する。

※今回はHTTP通信だけできるようにする

セキュリティグループのインバウンドルールの設定画面を開き、「ルールを追加」をクリック。
その後、タイプをHTTPに設定し、0.0.0.0/0を設定する。

これで保存すれば設定完了。

## 接続確認
`http://<自分のドメイン>`にアクセスし、Apacheのデフォルトページが表示されればOK
40 代おっさん AutoScaling を学ぶ

## 本記事について

本記事は AWS 初学者の私が学習していく中でわからない単語や概要をなるべくわかりやすい様にまとめたものです。
もし誤りなどありましたらコメントにてお知らせいただけるとありがたいです。

## 概要

EC2インスタンスが処理しきれないときに
AutoScalingにてEC2インスタンスを増やして対応してもらえるようにする。

## AutoScaling

### 起動テンプレート

![AutoScalingkidou.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/691f6e0c-eb03-62c3-e9e7-3326bf433d88.png)

上記の図のように起動テンプレートを作成

#### 起動テンプレートとは

AMIは何か
インスタンスタイプ何か
Key Pair何か
Security group は何か

を通常EC2を起動するときに手動するものを、まとめたもの

※これとは別に起動設定がある。AutoScaling group で使用できるが
　起動テンプレートVer管理
　起動設定は別の設定ファイルで管理

 ### AutoScaling group

![AutoScalingkidouCloudWatch.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/641940/f0c8f0cc-9d8c-63ac-3d26-369fddb1fbef.png)


 AutoScaling group作成時にどの起動テンプレート起動するかを紐づける。
 AutoScaling groupにどこのサブネットにどの程度配置するのかを決める。

 上の例だと
最小2　こちらはインスタンスを2以下にしない
最大4　こちらは最大４よりは増えません
という設定になる。

CPU使用率が対応できなくなった場合
メトリクス情報が CloudWatch に発行される。
CPU70％以上で発行されるアラーム
スケーリングポリシーでEC2追加
CPU30％以下で発行されるアラーム
スケーリングポリシーでEC2削除
この二つを紐づける

AutoScaling group はELBターゲットグループと紐づけることができる。

※ターゲットグループとは
ELB が振り分けることがグループのこと

## 最後に

またこの記事は AWS 初学者を導く体系的な動画学習サービス「AWS CloudTech」の課題カリキュラムで作成しました。
<https://aws-cloud-tech.com/>
テレビの津波警報のカラーユニバーサルに学ぶ (UIデザイン)

# 前提
UIの配色を決定する際に、色覚障害(色弱)を持たない正常な人の感覚で色分けをすると、
色覚障害(色弱)を持つ人にとっては区別できない配色となってしまうことがある。
そうならないように、すべての人に配慮した配色にしたデザインを、カラーユニバーサルデザインという。

# きっかけ
2024年1月1日に発生した石川県での大地震の際に、テレビの津波警報の表示色(カラーユニバーサル)について気になったので調べた。
大津波警報が紫に設定されていることについて、テレビで表示される津波警報を見ているときは特に疑問に思わなかったが、
Yahoo Japan のトップページにある、「大津波警報がでていること」の警告表示が紫色の背景になっていたので、
「カラーユニバーサルデザイン的には紫が最上級に警告を表現できるのか？」と疑問に思ったので、調べてみた。

![スクリーンショット 2024-01-01 180837.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619869/8ec893d3-77e4-7626-96c4-d3775d658bb0.png)

![スクリーンショット 2024-01-01 180756.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619869/6482db53-1d2d-0573-cf64-c9f996666993.png)


# 調査結果
他ページに丸投げとなるが、下記のようになっている。

https://jfly.uni-koeln.de/color/tsunami/#:~:text=4%EF%BD%81%EF%BC%9A%E5%A4%A7%E6%B4%A5%E6%B3%A2%E8%AD%A6%E5%A0%B1%E3%81%AE%E7%B4%AB%E8%89%B2&text=4%EF%BD%82%EF%BC%9A%E6%B4%A5%E6%B3%A2%E8%AD%A6%E5%A0%B1%E3%81%AE%E8%B5%A4%E8%89%B2&text=4%EF%BD%83%EF%BC%9A%E6%B4%A5%E6%B3%A2%E6%B3%A8%E6%84%8F%E5%A0%B1%E3%81%AE%E9%BB%84%E8%89%B2

# SE、PG、デザイナーへ
カラーユニバーサルデザインに配慮したUIデザインを普及させるべく、
なるべく意識してデザインしてほしいと思う。

カラーユニバーサルデザインに配慮したデザインが普及することを願う。
(最近は、デバイス側[OSレベル]でカラーユニバーサルデザインに配慮したデザインに即時変換する機能が実装されてきているが。)
ライセンス簡易まとめ

## はじめに

ライセンスについて把握しておいた方が良いと思うのでまとめ。

## GPL

- コピーレフト。ただし配布しなければ公開の義務はない（らしい）。
- ソースコードに著作権・ライセンス表示必須。

## AGPL

- コピーレフト。商用利用は現実的に厳しいかも
- ソースコードに著作権・ライセンス表示必須。
- GPLは配布しなければ公開できるがAGPLはそうもいかない。
- GPLの強化版みたいなもの？

## LGPL

- コピーレフトではない
- ソースコードに著作権・ライセンス表示必須。
- GPLのゆるい版みたいなもの。
- サーバに配置して利用するようなシーンの場合、このライセンスだったとしても利用が可能

## MIT License

- ソースコードに著作権・ライセンスを明記すれば後は自由に利用可。商用利用できる。

**デメリット**
- サポートがない（はず）

## Apache License

- ソースコードに著作権・ライセンスを明記すれば後は自由に利用可。商用利用できる。
- バージョンによって差異があるため要確認（Apache License 2.0が商用利用としては優れているっぽい）

## 商用利用できるライセンスおすすめ
基本的にはどのライセンスもソースコードなどに著作権やライセンス明記が必須。
商用利用の場合、ソースコードの開示が難しいと考えると、

- MIT License
- Apache License

このあたりのライセンスを選んでおけばよさそう。

## 最後に

誤りなどあればご指摘いただけると大変ありがたいです！
EEPROM 24FC1025を使う

# はじめに
電子工作用として、1Mbit(128kbyte)のEEPROMを使ってみたのでまとめる。

https://akizukidenshi.com/download/24fc1025-IP_jp.pdf

# 24FC1025のピン配置
A0/A1/A2I2Cのアドレスを設定できる。アドレスの下位3bit分表現できる。すべてLowにした場合は0x50。すべてHighにした場合は0x57。WPは書き込みのプロテクトピン。Lowにすることで書き込みができる。
A0/A1/A2/WPをすべてGNDでつなげるとI2Cアドレス0x50でいつでも読み書きができる状態となる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299802/8746bb3b-2020-cffe-36f5-a873ce8cb605.png)

# 書き込み
Offset 0x0000に0xAAを書き込む例。
I2cAddr(W)|AddrH|AddrL|Data1
---|---|---|---
0x50|0x00|0x00|0xAA

連続して書き込む場合は、先頭のオフセットを指定してから、連続してデータを設定する。Offset 0x0000から3byte 0xAA/0xBB/0xCCを書き込む例。
I2cAddr(W)|AddrH|AddrL|Data1|Data2|Data3
---|---|---|---|---|---
0x50|0x00|0x00|0xAA|0xBB|0xCC

# 読み込み
Offset 0x0000から1byte読み込む場合は、Offsetを設定後、読みこむ。
I2cAddr(W)|AddrH|AddrL|I2cAddr(R)|data1
---|---|---|---|---
0x50|0x00|0x00|0x51|0xAA

連続して読みこみ場合は、先頭のオフセットを指定してから、連続してデータを読み込む。Offset 0x0000から3byte を読み込む例。
I2cAddr(W)|AddrH|AddrL|I2cAddr(R)|data1|data2|data3
---|---|---|---|---|---|---
0x50|0x00|0x00|0x51|0xAA|0xBB|0xCC

以上
CSS の justify と align の違い

混乱したのでまとめました...

1. Flexbox ... １次元
1.1. align-content ... 上下
1.2. justify-content ... 左右
2. Grid Layout ... ２次元
2.1. align-items ... 上下
2.2. justify-items ... 左右


:::note warn
`flex-direction` に `column` を指定すると以下のように変わるので注意してください（初期値は `row`）。自分はハマりました。

1. Flexbox ... １次元
1.1. align-content ... 左右
1.2. justify-content ... 上下
:::


## 1. Flexbox と Grid Layout

### <font color="#5f9ea0">1.1. Flexbox</font>

ようするに一次元...

> [フレックスボックスの基本概念](https://bit.ly/3S0S9Dv)
> <font color="#444">フレキシブルボックスレイアウトモジュールは、</font> 通常フレックスボックスと呼ばれ、一次元のレイアウトモデルとして、<font color="#444">またインターフェイス中のアイテム間で余白の分配をする機能と強力な位置合わせをする機能を提供するものとして設計されました。</font>



### <font color="#5f9ea0">1.2. Grid Layout</font>

ようするに二次元...

> [グリッドレイアウトの基本概念](https://bit.ly/3ttedxn)
> CSS グリッドレイアウトは、二次元グリッドシステムを CSS にもたらします。








## 2. align と justfiy

### <font color="#5f9ea0">2.1. align</font>

上下の調整。`align-items: center`, `align-content: center` なら上下中央になる。

> [align](https://eow.alc.co.jp/search?q=align)
> 1.〔～を〕一直線［平行］にする［並べる］
> 2.〔部品などを〕調整する、調節する
> 3.〔大義や方針で～を〕同じ立場に置く、提携させる


3 の同じ立場に置くが上下のニュアンスがあるなと思いました。以下の図の EQUITY が `align-items: center` のイメージに近いのかなと思いました。

![download.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254825/7643137e-8c34-3378-83ce-a953c96e9307.jpeg)


あと alliance, 同盟とかも確かに対等な立場の意味合いがありそうな感じがします。以下はスターアライアンスのマークですが [傘連判状](https://www.google.com/search?q=%E5%82%98%E9%80%A3%E5%88%A4%E7%8A%B6) みたいに円形のデザインになっています、上下関係の対等な同盟ということを意味したいのでしょうか...


![Star_Alliance_Logo_bis_2011.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254825/9f432b4d-4129-3fa8-d81a-0a443292079b.png)

> [スターアライアンス](https://bit.ly/48FoKED) は、1997年5月14日に設立された、世界初で世界最大の航空連合。 その加盟会社による就航国は190カ国余り、1,300以上の空港に達し、1日当たりの便数は21,000便を超える。アライアンス・スローガンは「The Way The Earth Connects」。



### <font color="#5f9ea0">2.2. justify</font>

左右の調整。`justify-items: center`, `align-content: center` なら左右中央になる。

> [justify](https://eow.alc.co.jp/search?q=justify)
> 3.《編集》〔行の左端または右端を〕そろえる

天秤の左右の釣り合いのイメージから justify で左右中央なのでしょうか... いらすとや、なんでもあって笑ってしまう...

![Screenshot from 2024-01-01 16-56-59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/254825/7c8914a7-e561-eb68-70f8-f7cda790f4e7.png)

> ギリシャ神話に登場する法の女神（正義の女神）、テミスの目隠しをしていない状態としている状態のイラストです。裁判所などによく像が飾られています。
> [テミスのイラスト](https://www.irasutoya.com/2018/04/blog-post_790.html)






## 3. items と content

### <font color="#5f9ea0">3.1. content</font>

主に Flexbox に対して使用される...はず

なんで items は s がつくのに content は s がつかないんだよ〜、って思ったら通例単数形のみだそうです... 英語わからん... メリケン人の頭の中どうなってるんや...

> [content](https://eow.alc.co.jp/search?q=content)
> 1\. 〔容器などの〕内容物、中身◆通例、contents
> 7\. 《コ》コンテンツ、内容◆電子的に利用可能な情報・画像・映像など。◆【用法】通例、単数形のみ。

### <font color="#5f9ea0">3.2. items</font>

主に Grid Layout に対して使用される...はず

以下の中だと 3 番が一番近いんでしょうか... Flexbox で最も意味が近い content を使ってしまったから、Grid Layout ではつぎに意味がそれっぽい items を選んだみたいな感じだと思います。

> [item](https://eow.alc.co.jp/search?q=item)
> 1. 〔一覧の中の〕項目、品目
> 2. 〔法律などの〕条項、箇条
> 3. 〔製造される〕品物、商品、製品
> 4. 〔こまごました〕事柄、情報
「Invalid datetime format: 1292 Incorrect date value」への対応法

## はじめに
マイグレーションファイルを修正して実行しようとしたところ、


「Invalid datetime format: 1292 Incorrect date value」とエラーが出たので、対応策をまとめます。

## 環境
Laravel 9.52.16

## 問題
* 入力フォームに新たに日付を追加したい
* そのためマイグレーションファイルを修正
* しかし上手く実行できない

```php: マイグレーションファイル
<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('sales_orders', function (Blueprint $table) {
            $table->string('category');
            $table->decimal('budget', 10);
            $table->date('schedule');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('sales_orders', function (Blueprint $table) {
            $table->dropColumn('category');
            $table->dropColumn('budget');
            $table->dropColumn('schedule');
        });
    }
};
```

```sql: エラー
Illuminate\Database\QueryException 

SQLSTATE[22007]: Invalid datetime format: 1292 Incorrect date value: '0000-00-00' for column 'schedule' at row 1 
(SQL: alter table `sales_orders` add `category` varchar(255) not null, add `budget` decimal(10, 2) not null, add `schedule` date not null)

```

## 原因と解決策
* **既存のレコードにdateを挿入しようとしたとき、デフォルトの値がないためエラーが発生している**

自分の場合、事前にテストレコードを作成していました。

そこには当然今回追加しようとしているscheduleカラムなどは存在しません。

よってマイグレーション実行時に事前に定めるデフォルトの値を設定しようとします。

しかし自分はデフォルトの値を設定していないので、エラーが発生しています。

### 対応策①：NULLを許容する
scheduleカラムのデフォルト値のNULLを許容する方法です。

これにより、既存のレコードに対してscheduleカラムを追加すると、そこにはNULLが設定されます。

```php: 例（マイグレーションファイル内）
// 中略
$table->date('schedule')->nullable();
```

### 対応策②：デフォルト値を設定する
scheduleカラムにデフォルト値を設定する方法です。

ただしデフォルト値を設定する場合は、その値が意図する値であるか精査する必要があります。

```php: 例（マイグレーションファイル）
// 中略
$table->date('schedule')->default(DB::raw('CURRENT_DATE'));
```

例えばこのコードではデフォルト値としてCURRENT_DATE（現在時刻）が入ります。

## おわりに
自分はNULLを許容することで対応しましたが、NULL許容は不自然な挙動時の原因把握を難しくする可能性があります。

テストレコード数件程度であれば、一旦全部削除するのもアリかなと思いました。
symbol-networkで作成した private networkに shoestring nodeを同期させる

symbol-networkは知る人ぞ知る 独自に private networkを作成出来る toolである
現在は
`sudo npm install -g symbol-network`では正常な動作が見込めない為
以下の記事の方法で installする
又　基本的な使用方法も　以下の記事にある為　これを割愛する

https://qiita.com/ishidad2/items/12a704b52bc8594196e5#symbol-network%E3%82%92%E5%8F%96%E5%BE%97

# private networkを作成する
適当なﾃﾞｨﾚｸﾄﾘを作成し　作成したﾃﾞｨﾚｸﾄﾘに入る
```
symbol-network init --ready
symbol-network expandNodes
symbol-network generateNemesis
symbol-network configureNodes
cd nodes/node-001
symbol-bootstrap run -d
```
以上で networkが動き出す

# 作成した networkに同期する nodeを別の server上に(bootstrap)で作成する
networkは立ち上がったので　今度は別の serverに入り
適当なﾃﾞｨﾚｸﾄﾘを作成し　その中に networkを作成した serverから `nemesis-seed` `custom-network-preset.yml`
を copyし　これを元に symbol-bootstrapを使用して nodeを作る
```
symbol-bootstrap config -p custom-network-preset.yml -a dual
```

shoestring node用の作業ﾃﾞｨﾚｸﾄﾘを作成し
その中へ　上述の bootstrapで作成した
`target/nodes/node/server-config/resources`と
`nemesys-seed`を copyする

# shoestringで nodeを作成する 
`python3 -m shoestring.wizard`実行　shoestring node用の作業ﾃﾞｨﾚｸﾄﾘの中に　nodeを作成する
shoestring.wizardの使用については　以下の記事を参照

https://qiita.com/amenoudume/items/f1183d3619cd691dace2#shoestring%E3%81%A7%E3%81%AE%E3%81%89%E3%81%A9%E3%82%92%E5%BB%BA%E3%81%A6%E3%82%8B

shoestring node用作業ﾃﾞｨﾚｸﾄﾘに入り
先程 copyした`nemesis-seed`　`resources`がある事を確認した後
`seed`を削除し　`nemesis-seed`を`seed`の名前で copyする
```
rm -rf seed
cp -r nemesis-seed seed
```

resources内の`config-network.properties` `peers-api.json` `peers-p2p.json`を
userconfig/resource内に copy
元の fileと置き換える
```
cd userconfig/resources
sudo cp ../../resources/config-network.properties .
sudo cp ../../resources/peers-api.json .
sudo cp ../../resources/peers-p2p.json .
cd -
```
shoestring nodeを起動する

※元々 bootstrap nodeを動作させていた serverでは　このままでは動作しないので
`docker system prune`を実行
```
docker-compose up -d
```
【TIPS】マップリストからキー／バリューを削除

この記事は、[Elixir Advent Calendar 2023 シリーズ10](https://qiita.com/advent-calendar/2023/elixir) の21日目です

---

【本コラムは、3分で読め、3分で試せます】

[piacere](https://twitter.com/piacere_ex) です、ご覧いただいてありがとございます :bow:

マップリストは、同列の複数データを扱う際や、RepoによるDBデータ取得で頻出します

```diff_elixir
users = [
  %{id: :id000, name: "hoge", weight: 49}, 
  %{id: :id001, name: "foo",  weight: nil}, 
  %{id: :id002, name: "fuga", weight: 33}
]
```

下記コラムで更新について述べました

https://qiita.com/piacerex/items/8c19db49fcf6f68be9df

本コラムでは、削除を述べます

# マップリストの全体から削除

```diff_elixir
users
|> Enum.map(& Map.drop(&1, [:name]))
[
+ %{id: :id000, weight: 49},
+ %{id: :id001, weight: nil},
+ %{id: :id002, weight: 33}
]
```

複数キー／バリューの一括削除もできます

```diff_elixir
users
|> Enum.map(& Map.drop(&1, [:id, :name]))
[
+ %{weight: 49}, 
+ %{weight: nil}, 
+ %{weight: 33}
]
```

全体に対してであれば、forでもシンプルに書けます

```diff_elixir
for u <- users, reduce: [] do
  acc -> acc ++ [Map.drop(u, [:name])]
end
[
+ %{id: :id000, weight: 49},
+ %{id: :id001, weight: nil},
+ %{id: :id002, weight: 33}
]
```

# マップリストの一部のみ削除

```diff_elixir
users
|> Enum.map(& if &1.weight == nil, do: Map.drop(&1, [:weight]), else: &1)
[
  %{id: :id000, name: "hoge", weight: 49},
+ %{id: :id001, name: "foo"},
  %{id: :id002, name: "fuga", weight: 33}
]
```

`case` で書くなら、こうです

```diff_elixir
users
|> Enum.map(& case &1.weight do
    nil -> Map.drop(&1, [:weight])
    _ -> &1
  end)
[
  %{id: :id000, name: "hoge", weight: 49},
+ %{id: :id001, name: "foo"},
  %{id: :id002, name: "fuga", weight: 33}
]
```
戻り値が複数ある関数をタプル型で返す方法を理解しよう！

# タプル型(Tuple型)とは
複数の型を一つにまとめて扱う型のこと。
タプル型は`(型名1, 型名2, 型名3)`のように表す！
```Swift
var tuple: (String, Int, Double)
```

## タプル型の要素へのアクセス方法
タプル型の要素へのアクセス方法は2つあります！
### 1. インデックスによるアクセス
変数と0から始まるindex数を用いて`変数名.index数`でアクセスする！
```Swift
var tuple = ("Hinakko", 24, 24.89)
print(tuple.0) //Hinakko
```
**出力結果**
```
Hinakko
```

### 2. 要素名によるアクセス
引数名をつけ、`変数名.index数`でアクセスする！
```Swift
var tuple = (name: "Hinakko", age: 24, double1: 24.89)
print(tuple.name) //Hinakko
```
**出力結果**
```
Hinakko
```
# 戻り値が複数ある関数をタプル型で返す方法
戻り値が複数ある関数をタプル型で返す方法は2つあります！
### 1. 戻り値に引数名がない関数
関数の戻り値を`(型名1, 型名2, 型名3)`で指定し、呼び出し元で、戻り値に引数名がないので、インデックスによりアクセスする！
以下の例では`(String, Int, Double)`で指定し、呼び出し元で一番最初のindex数0にアクセスしている！
```Swift:関数
func returnProfile() -> (String, Int, Double) {
    return ("Hinakko", 24, 24.89)
}
```
```Swift:呼び出し元
var profile = returnProfile()
print(profile.0)
print(profile.1)
print(profile.2)
```
**出力結果**
```
Hinakko
24
24.89
```

### 2. 戻り値に引数名がある関数
関数の戻り値を`(引数名: 型名1, 引数名: 型名2, 引数名: 型名3)`で指定し、呼び出し元で戻り値の引数名によりアクセスする！
以下の例では`(name: String, age: Int, double1: Double)`で指定し、呼び出し元で一番最初のnameの引数名を用いアクセスしている！
```Swift
func returnProfile() -> (name: String, age: Int, double1: Double) {
    return (name: "Hinakko", age: 24, double1: 24.89)
}
var profile = returnProfile()
print(profile.name)
print(profile.age)
print(profile.double1)
```

**出力結果**
```
Hinakko
24
24.89
```
最後に紹介した戻り値に引数名をつけるアクセス方法の方が、呼び出しの際、引数名で何にアクセスしているか想像することができるので、扱いやすそうですね！


# 参考文献

https://swift.codelly.dev/guide/%E5%9F%BA%E6%9C%AC%E3%81%AE%E5%9E%8B/Tuple%E5%9E%8B.html#tuple%E5%9E%8B%E3%81%AE%E5%AE%A3%E8%A8%80%E6%96%B9%E6%B3%95

https://qiita.com/ohkawa/items/a7e5b9acc2aadba1d659

https://hajihaji-lemon.com/swift/post-5578/
Googleスプレッドシートの条件付き書式をGAS上で全シートに設定させる

自分用のメモ
・少し工夫すれば、特定のシートの条件を全シートにコピーできるのでしょうが、時間なくてできない
・copyAndOverrideConditionalFormats側に、シート名を指定し、sheet.getConditionalFormatRules();してパラメータで渡すことができれば、特定シートの条件を全シートのコピーが可能となる


```javascript:GAS
// 概要
// 指定したシートの全条件付き書式を、ほかの全シートに上書きコピーする関数
function copyAndOverrideConditionalFormats() {
  format = '=$A1:$A800="#"';
  insertFormulaToAllSheets_(format);

  format = '=OR(isnumber(A1:A800),(A1:A800<>""))';
  insertFormulaToAllSheets_(format);
}

/**
 * 全シートに対して、指定した条件付き書式を上書きして挿入する
 * @param {string} 条件付き書式
 */
function insertFormulaToAllSheets_(format) {
  const spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  const sheets = spreadsheet.getSheets();

  sheets.forEach(function (sheet) {
    const activeRange = sheet.getDataRange();
    const existingRules = sheet.getConditionalFormatRules(); // 既存の条件付き書式を取得

    // 新しい条件付き書式を追加
    if (format === '=$A1:$A800="#"') {
      newRule = SpreadsheetApp.newConditionalFormatRule()
        .whenFormulaSatisfied(format)
        .setBackground('#cfe2f3') // 背景色を水色にする
        .setRanges([sheet.getRange('A1:AF800')])
        .build(); // 条件を確定
    } else if (format === '=OR(isnumber(A1:A800),(A1:A800<>""))') {
      newRule = SpreadsheetApp.newConditionalFormatRule()
        .whenFormulaSatisfied(format)
        .setBackground('#cfe2f3') // 背景色を水色にする
        .setRanges([sheet.getRange('A1:A800')])
        .build(); // 条件を確定
    }

    // 既存の条件付き書式に新しい条件付き書式を追加
    existingRules.push(newRule);
    
    // 修正された条件付き書式をシートに再設定
    sheet.setConditionalFormatRules(existingRules);
  });
}
Qiita CLI のインストール方法【非IT従事者向け手順書】

# はじめに
この記事は私のように [Qiita 公式ドキュメント](https://github.com/increments/qiita-cli)を見ても何が何だか……と呆然としてしまう人向けです。その為、熟練のエンジニアから見れば、かなり回りくどいと思いますが、ご承知おきください。

# Qiita CLI とは？
Visual Studio Code など自分好みのエディターで記事の執筆やプレビュー、投稿ができるようになるツールです。
オフラインで記事が執筆できるなので新幹線に乗車している時とか隙間時間を有効活用できるようになります。

https://qiita.com/Qiita/items/666e190490d0af90a92b

# 事前準備
Qiita CLI の使用には Node.js が必要です。
Node.js のインストール方法は[こちら](https://qiita.com/yurimiyasakura/items/d4fe132fc9bc8189eff4)に記載しています。

# Qiita CLI のインストール方法
## ディレクトリの作成
1. Qiita の記事を保存したいディレクトリ（フォルダ）を作成します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6f3d6d5a-bad8-762b-7509-b986bddeee78.png)
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/bcdcfa5c-3741-38b2-472a-b35a99dabcf9.png)

2. フォルダを右クリック ＞ パスのコピーでパスをコピーします。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6ad02dae-a393-c20f-26e1-df397c4e8e96.png)

## インストールの実行
1. コマンドプロンプトを開きます。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/90ae9deb-2fbe-b3aa-bd83-459ced5ccb7c.png)

2. Qiita の記事を保存するディレクトリに移動する為に、以下のコマンドを入力してEnterキーを押します。
※フォルダパスはコピーしたパスを貼り付けます。

    ~~~
    cd [フォルダパス]
    ~~~
    
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/3ad3882d-0f1f-db03-5a10-6b0b58bc8fb1.png)

3. Qiita CLI をインストールする為に以下のコマンドを入力してEnterキーを押します。
    ~~~
    npm install @qiita/qiita-cli --save-dev
    ~~~
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/6c399167-4569-3343-7138-8dbe67a82597.png)

4. Qiita CLI のバージョンを確認するために、以下のコマンドを入力してEnterキーを押します。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/76d2a07f-5fa9-84ce-33ee-38decc7001f9.png)
    バージョンが表示されていれば、インストール完了です。

    :::note
    GitHub の最新バージョンと数字があっていればOKです。
    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3032705/61c949cb-cedf-74ae-0786-aa681e9c591c.png)
matplotlib で日本語を表示可能なフォントのみを列挙する (要 fonttools)

手元の環境で日本語を表示可能なフォントのみを列挙したいとき向けです。fonttools が必要です (pip で入ります)。以下で列挙できます。参考文献 [1] を参考にしました。

```python
import matplotlib
import fontTools

def is_character_supported(char, font_path):
    font = fontTools.ttLib.TTFont(font_path, fontNumber=0)
    cmap = font.getBestCmap()
    if cmap and ord(char) in cmap:
        return True
    return False

def get_font_names(char):
    font_names = set()
    for font_path in matplotlib.font_manager.findSystemFonts():
        if is_character_supported(char, font_path):
            font_name = matplotlib.font_manager.FontProperties(fname=font_path).get_name()
            font_names.add(font_name)
    return sorted(list(font_names))

font_names =  get_font_names('凪')  # 適当な1文字
print(len(font_names))
print(font_names)
```

```
31
['BIZ UDGothic', 'BIZ UDMincho', 'HGGothicE', 'HGGothicM',
 'HGGyoshotai', 'HGKyokashotai', 'HGMaruGothicMPRO', 'HGMinchoB',
 'HGMinchoE', 'HGSeikaishotaiPRO', 'HGSoeiKakugothicUB', 'HGSoeiKakupoptai',
 'HGSoeiPresenceEB', 'M PLUS 1', 'M PLUS 1 Code', 'M PLUS 2',
 'MS Gothic', 'MS Mincho', 'Meiryo', 'Microsoft JhengHei',
 'Microsoft YaHei', 'Ricty Diminished', 'Ricty Diminished Discord', 'Rounded Mplus 1c',
 'Rounded Mplus 1c Bold', 'SimSun', 'UD Digi Kyokasho N-B', 'UD Digi Kyokasho N-R',
 'Ume Gothic', 'Yu Gothic', 'Yu Mincho']
```

### 補足

- 日本語を表示可能なフォントをみつけるのに、可能なフォントをすべて描画してみて「豆腐」(□) にならないか確認する方法もありますが、それだと使用可能なフォント名のみを列挙しづらいので、列挙したいとき向けです。
  - 豆腐があるとグラフ描画時に UserWarning が出ますが、これでもって検知しようとするとノートブックにグラフ or エラーメッセージがぶわっと出てしまうことが避けられないと思います (たぶん)。
- 上記のスクリプトは `getBestCmap()` でそのフォントの Unicode コードポイント‐グリフID の対応表を取得し、「凪」という文字の Unicode コードポイントが対応表に含まれているかをみています [1][2]。「凪」を選んだのは国字なので中国語向けフォントが排除されるかと思ったのですが、別に排除されなかったです。

そういうわけで、私のお気に入りのフォント名が Rounded Mplus 1c であったのがわかったので指定しますが、このフォントを持っていないチームメンバーにも配慮して以下のようにした方がよさそうです [3]。

```python
%matplotlib inline  
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'sans-serif'
plt.rcParams['font.sans-serif'] = ['Rounded Mplus 1c', 'Meiryo']
```

フォント名を列挙するだけなく描画してみて選びたいのだという場合は、例えば以下のようにするとみられると思います (お手元のフォント数が多かったら figsize を調整してください)。

```python
%matplotlib inline  
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(7, 7))
for i, font_name in enumerate(font_names):
    plt.rcParams['font.family'] = font_name
    ax.text(0, i, font_name + ' 0123456789 来ぬ人を松帆の浦の夕凪に', size=11)
ax.set_ylim([0, len(font_names)])
plt.show()
```

### 参考文献

1. [Python フォントに指定した文字が収録されているか確認する](https://www.umayadia.com/pysample/sample0300/Sample337GlyphExistsInFont.htm)
1. [ttFont: Read/write OpenType and TrueType fonts &mdash; fontTools Documentation](https://fonttools.readthedocs.io/en/latest/ttLib/ttFont.html#fontTools.ttLib.ttFont.TTFont.getBestCmap)
1. [Configuring the font family &#8212; Matplotlib 3.8.2 documentation](https://matplotlib.org/stable/gallery/text_labels_and_annotations/font_family_rc.html)
データサイエンス100本ノックで UsageError: Cell magic `%%sql` not found. がでた時の対処

# 現象
SQL100本ノックのコンテナ起動後、SQLを実行させようとすると下記のようなエラーが出ることがあります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/b344a3b4-c636-769c-4376-4de643b1f3ea.png)


# 対処

**「はじめに」の直後にあるこちらのセルを選択**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/dbe16bfc-afba-a133-8f87-7c212afdbe13.png)


**実行ボタンを押下**
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/45688218-e8e1-a34e-660e-f43218704041.png)

**再度失敗したセルを選択し実行**

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2703223/f4a9283b-0f3c-3543-cf0f-c4980d17469c.png)

これでエラーは出なくなりました。


「はじめに」に書いてあることではありますが、読み飛ばしてしまってクエリの実行をし損ねて時間を浪費するのも悲しいのでメモっておきます。説明書はよく読みましょう（自戒）。
最近のvcpkgとVisual Studio Codeの使い方

[CMake でパッケージをインストールして使用する | Microsoft Learn](https://learn.microsoft.com/ja-jp/vcpkg/get_started/get-started?pivots=shell-cmd)

を参考に進めていく。

まず、コマンドプロンプト上で作業を始める。

```
set VCPKG_ROOT="C:\path\to\vcpkg"
```

とあるが、「"」は後に邪魔になるらしく、

```
>cmake --preset=default
Preset CMake variables:

  CMAKE_TOOLCHAIN_FILE=""C:\src\vcpkg"/scripts/buildsystems/vcpkg.cmake"

-- Building for: Visual Studio 17 2022
CMake Error at C:/Program Files/CMake/share/cmake-3.27/Modules/CMakeDetermineSystem.cmake:154 (message):
  Could not find toolchain file:
  "C:\src\vcpkg"/scripts/buildsystems/vcpkg.cmake
Call Stack (most recent call first):
  CMakeLists.txt:3 (project)


-- Configuring incomplete, errors occurred!
```

こんな感じのエラーが出るので、

```
set VCPKG_ROOT=C:\src\vcpkg
```

のように「"」を抜くとうまくいった。

一通り上記文章を終えたら、「code .」でVS codeを起動する。

まず、実行とデバッグだが、「launch.jsonファイルを作成する」をクリック、「C++ (Windows)」を選択する。

launch.jsonファイルに以下のように追記する。

```
{
    // IntelliSense を使用して利用可能な属性を学べます。
    // 既存の属性の説明をホバーして表示します。
    // 詳細情報は次を確認してください: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "C++ Launch (Windows)",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/Debug/HelloWorld.exe",
            "cwd": "${workspaceFolder}"
        }
    ]
}
```

すると、上記name通りの「C++ Launch (Windows)」という「実行とデバッグ」のためのボタン等が表示されるので、これを押してみると、正常に「HelloWorld!」が表示される。

また、helloworld.cppの適当な位置にブレークポイントを置いて止まるか確かめる。

それから、コマンドパネル（ctrl + shift + p）の「CMake: ビルド」でビルドできるか確認する。

次に、helloworld.cppの、

```
#include <fmt/core.h>
```

にincludeパスが通っていないので赤い波上の下線が表示されてると思うので、includeパスを通したい。

これも、いきなりコマンドパネルで「C/C++: 構成の編集（JSON）」を選択すると、.vscode下にc_cpp_properties.jsonが生成される。

そのincludeパスの設定に以下のように追記すると、上記下線は消えるようである。

```
            "includePath": [
                "${workspaceFolder}/**",
                "${workspaceFolder}/build/vcpkg_installed/x64-windows/include"
            ],
```

追記した瞬間に消えるわけではなく、VS codeを立ち上げなおしたり、helloworld.cppタブを開きなおしたりした。

以上
Selenium操作で完全Headlessを実現するためのいくつかのTips

PythonでSeleniumを用いる際、必ずしもGUIが使用できる環境ばかりではありません。クラウド環境はもちろん、ローカル環境でもバックグラウンドで実行できたほうが何かと都合良いでしょう。そう考えると、何も考えずにPyaoutguiなどを用いていると思った通りの挙動となりません。今年一年、そういった作業を多くしてきたので、それで蓄積されたノウハウをまとめておきたいと思います。

## 1. Formへのデータ入力はまずsend_keys（→Enter）を試す
```python
input_elem.send_keys(new_value)
input_elem.send_keys(Keys.ENTER) # send_keysだけでは入力確定にならない場合
```

## 2. send_keys.clear()が効かないときは全て選択してDelete
```python
input_elem.send_keys(Keys.COMMAND, 'a')
input_elem.send_keys(Keys.DELETE)
input_elem.send_keys(new_price)
```

## 3. どうしてもマウス移動が必要ならActionChainsを試す
```python
from selenium.webdriver import ActionChains

mouse_xpath = 'some_xpath' # hover状態にするためのpath
click_xpath = 'other_xpath' # hoverで出現した要素のpath

# マウスポインタを要素の位置に移動
element_to_move = driver.find_element(By.XPATH, mouse_xpath)
actions = ActionChains(driver)
actions.move_to_element(element_to_move).perform()

# 要素をクリック
element_to_click = driver.find_element(By.XPATH, click_xpath)
element_to_click.click()
```

## 4. WebDriverWait +  EC で要素の出現と同時に取得
```python
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

anchor_elem = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.XPATH, some_anchor_xpath))
)
anchor_url = anchor_elem.get_attribute('href')
```

## 5. Window.Alertを操作する
```python
some_button.click() # アラートのトリガーとなる動作
# アラートに対応するために待機
WebDriverWait(driver, 10).until(EC.alert_is_present())
time.sleep(3)

# アラートにスイッチし、'Enter'に相当する操作を実行
alert = driver.switch_to.alert
alert.accept()
```

## 6. スクロールしたいときはJSを使う
```python
# スクロール対象の要素までスクロールするJavaScriptコード
scroll_script = "arguments[0].scrollIntoView();"
scroll_target = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.XPATH, 'some_xpath')))
driver.execute_script(scroll_script, scroll_target)
```

## 7. elem.clickが効かないときもJSを使う
```python
click_target_elem = WebDriverWait(driver, 10).until(EC.presence_of_element_located(
    (By.XPATH, 'some_xpath')))
driver.execute_script("arguments[0].click();", click_target_elem)
```
LightningのCTA作成でエラー「更新に失敗しました。 返答が正しい JSON レスポンスではありません。」

以下の環境で、CTA作成時にエラー「更新に失敗しました。 返答が正しい JSON レスポンスではありません。」が発生した。

- ロリポップ
- Wordpress
- テーマLightning

なお、CTAの作成方法は以下の動画参照。
https://training.vektor-inc.co.jp/courses/lightning-basic-settings/lessons/lightning-exunit-cta/

エラーの原因は、ロリポップのWAFでブロックされていること。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298692/70187a25-4715-629b-5337-ff6f4fcfe406.png)

ロリポップのWAFを一時的に無効にすることで対応できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/298692/56770520-4d9f-0156-d605-a98230e7fc3e.png)
reportlabを使ったPDF添付メール送信でプレビューの文字が消える話


# はじめに

こんにちは、Pittaです。この記事は"HeiseiKakuGo-W5"フォントを用いたPDFをメールで送ると文字消えが発生する、という注意喚起です。

- [はじめに](#はじめに)
- [結論](#結論)
- [PythonでPDF作成](#pythonでpdf作成)
- [デフォルトで使える日本語フォント](#デフォルトで使える日本語フォント)
- [PDFを作る](#pdfを作る)
- [メール送信で消える文字](#メール送信で消える文字)
- [対策](#対策)
- [終わりに](#終わりに)

# 結論

reportlabではデフォルトのフォントは使わずにちゃんとした他のフォントを使った方がいいよ。


# PythonでPDF作成

PythonでPDFを作りたい時、重宝するのが`reportlab`というライブラリです。書き方等詳しいことはこちらの記事を参考にしてください。

https://qiita.com/takahashi_you/items/8c5fb1f07db1825c67a5



# デフォルトで使える日本語フォント

`reportlab`にデフォルトで組み込まれているフォントは`HeiseiMin-W3`と`HeiseiKakuGo-W5`のふたつです（以下の記事参考）。

https://assam-blog.com/python-reportlab-japanese-font/

今回は`HeiseiKakuGo-W5`を使用します。

# PDFを作る

サンプルのPDFを作ります。消えそうな漢字ばかりを集めてみました。

```python
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4, portrait
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.cidfonts import UnicodeCIDFont
import os

# ユーザのデスクトップのディレクトリを取得
file = "sample.pdf"
file_path = os.path.expanduser("~") + "/Desktop/" + file

# A4の新規PDFファイルを作成
page = canvas.Canvas(file_path, pagesize=portrait(A4))

pdfmetrics.registerFont(UnicodeCIDFont('HeiseiKakuGo-W5'))

page.setFont("HeiseiKakuGo-W5", 10)
page.drawString(250, 500, "親鸞対鬱鑑璽濱祇龍飛色")

# PDFファイルとして保存
page.save()

```

出力されたPDFを確認してみると、ちゃんと出来ています。

![sample-image1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611731/bd41357b-739a-1ff2-76bf-a8fb955ca332.png)



# メール送信で消える文字

このPDFをGmailに添付して送ってみます。Gmailには受信したメールの添付資料を確認できるプレビュー機能があるのでそれで確認してみると…。

![sample-image2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2611731/8b7e03b4-68b1-cf65-a5b2-077e609d4e5f.png)


「対」が消えています。

このファイルをダウンロードしてみるとちゃんと表示されているので、プレビュー表示内のみの問題なようです。


# 対策

フォントを変えるしか対処法はわかりませんでした。
組み込みのもう一つのフォントはカッコよくないので（エセ日本語感のあるフォントです）、おとなしくMS明朝を使います。

外部フォントを使う場合は、`.ttf`ファイルを Windows\fontsから探し（もしくは外部からダウンロードし）、フォントを登録します。

```python
from reportlab.pdfbase.ttfonts import TTFont

MINCHO = "msmincho.ttc"
pdfmetrics.registerFont(TTFont('Mincho', MINCHO))
```

これで組み込みフォントと同様に外部フォントが使えるようになります。

# 終わりに

安定感のあるフォントを使おう！
実行ポリシー下でのPowershellからパスワード変更

以下サイトにある実行ポリシーをすべて実行
https://learn.microsoft.com/ja-jp/powershell/module/microsoft.powershell.core/about/about_execution_policies?view=powershell-7.4

以下、AllSigned、Bypass、Default、RemoteSigned、Restricted、Undefined、Unrestrictedを実行してみる

```
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> Set-ExecutionPolicy -Scope CurrentUser AllSigned
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> .\password.ps1
.\password.ps1: File C:\Users\（現在のユーザ）\Desktop\共有フォルダ\password.ps1 cannot be loaded. The file C:\Users\（現在のユーザ）\Desktop\共有フォルダ\password.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.
```

```
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> Set-ExecutionPolicy -Scope CurrentUser Bypass
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> .\password.ps1
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> 
```
```
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> Set-ExecutionPolicy -Scope CurrentUser Default
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> .\password.ps1
.\password.ps1: File C:\Users\（現在のユーザ）\Desktop\共有フォルダ\password.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.
```
```
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> Set-ExecutionPolicy -Scope CurrentUser RemoteSigned
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> .\password.ps1
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> 
```
```
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> Set-ExecutionPolicy -Scope CurrentUser Restricted
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> .\password.ps1
.\password.ps1: File C:\Users\（現在のユーザ）\Desktop\共有フォルダ\password.ps1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.
```
```
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> Set-ExecutionPolicy -Scope CurrentUser Undefined
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> .\password.ps1
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> 
```
```
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> Set-ExecutionPolicy -Scope CurrentUser Unrestricted
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> .\password.ps1
PS C:\Users\（現在のユーザ）\Desktop\共有フォルダ> 
```
AleoのTestnetを触ってみた①

※前提
私は素人なので間違った解釈・説明があると思います。
もし間違いがあったり、理解が浅いなと思うようなところがありましたら、是非ご指摘お願いします。

# Aleoとは
ZKP(ゼロ知識証明)を活用したプラットフォームを作ってます。
例えば、Swapするときに自分のアドレスや残高を見せずに、トークンをスワップできたりします。
何故できるかというと、ゼロ知識証明で自分がSwapできる残高を持っていることを証明することができるからです。

まだ理解が弱く、おろおろと書いているのですが、実際にAleoでデプロイしてみたら何となく動きが直感的に分かりました。
なので、是非触ってみてください！

# 開発環境構築
開発環境は下記ドキュメントと公式のDiscordを読んで調べて作ることができました。
- Aleoドキュメント
https://developer.aleo.org/getting_started/
- Discord
https://discord.gg/aleohq

開発構築手順は２ステップです。
ドキュメント見ながら簡単にインストールできます。
1. Aleoのプログラム言語Leoをインストール
　 Rustで作られてて、その上で開発する感じです。

2. SnarkVMをインストール
　leo言語で書いたプログラムをローカルで実行するためにインストールします。
   
3. SnarkOSをインストール
　 snarkOSでtestnetにデプロイしたりトランザクションを流したりします。

4. インストールできたらコマンドを実行して、正常にインストールできてるか確認しましょう
　 `leo --help`
　 `snarkos --help`

私はDockerの勉強がてら、Dockerfileを作ってDockerで構築してみました。
https://github.com/ais31/Aleo_testnet_deploy_contract


# snarkOSとsnarkVMの違い
snarkOSとsnarkVMは役割に違いがあります。
簡単に言うと、snarkOSはノード、snarkVMはEVMといった感じです。


- snarkVMコマンド
  デプロイしたプログラムの実行などを行います。
- snarkOSコマンド
  レコードをネットワークに送信、トランザクションの検証、別ノードへの中継が行えます。
  
上記２つのコマンドの使われ方は、
- leoで書いたプログラムを実行したいときは「snarkVM」のコマンドを使う。
- レコードをtestnet3に流したり、プログラムをデプロイするときは「snarkOS」のコマンドを使う。

となります。


次の記事では簡単なプログラムのtestnetへのデプロイと実行をまとめていきたいと思ってます。
Macからプッシュしようとしたら権限がなくて怒られた

# はじめに
新年早々、gitの警告にハマりました・・

※おことわり※
基本的に学習内容のアウトプットです。
初学者であるため、間違い等あればご指摘いただけますと嬉しいです。

# この記事の内容
1. エラー
2. 結論
3. 対応

# 1. エラー

クローンしたリポジトリに変更を加え、プッシュ使用しようとしたら警告が出ました。
（コミットはできているが、プッシュできない）

```terminal
You don't have permissions to push to "ユーザー/リポジトリ" on GitHub. Would you like to create a fork and push to it instead?

プッシュする権限がないため、forkしますか？
```

# 2. 結論
Gitのアクセストークンの有効期限が切れていました。

**アクセストークンの確認方法**

1. 右上のアカウントからSettingsへ
1. サイドメニューからDeveloper Settingsへ
1. Personal access tokensを確認

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740809/2f46d949-e444-a91e-7ecf-484649eaa98c.png)


# 3. 対応

- 有効期限の延長を行う
    - 有効期限が切れている場合 `Expires on Sun, Mar 31 2024.` がクリックでき、設定画面に遷移する
    - 保存するとアクセストークンが表示されるので、コピーする

    ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2740809/a95c015b-a260-6bc6-1c68-845d0a128f03.png)
<br>

- Gitの構成設定を行う
    - 指定したURLの代わりに別のURLを使用する設定で、先ほどのアクセストークンを指定する

        ```terminal
        git config --global url."https://<アクセストークン>:x-oauth-basic@github.com/".insteadOf "https://github.com/"
        ```
<br>

- テストする
    - 空コミットをプッシュできたらOK
    
        ```terminal
        git commit --allow-empty -m "test"
        git push
        ```
ガンダムSEEDfortune用（発進シーケンス）辞書ファイルを作るためにAmazonLinux2にfotruneコマンドを入てみた

# 背景
年末のある日、機動戦士SEED FREEDOMの公開を記念して、SEEDとSEED DESTINYの発進シーケンスのセリフをLinuxログイン時にランダムで表示させるとかいう、どうでもいいことを思いついてしまった...
その中でfortuneコマンドを使ってランダムにセリフを選択させようと思い、開発環境をAWS上に作った際にAmazonLinux2にfortuneコマンドを入れるので8時間弱苦戦したので、メモメモです。
インフラ屋さんじゃない上に技術経験浅いのが出た個人開発（？）でした。

# 参考文献
今回の記事では下記のサイトを参考にさせていただきました。
[AWS AmazonLinux2 EPELリポジトリ設定](https://qiita.com/vesoccer13/items/2b5aa3f4bf1e1c623384)

# 導入
上記文献を参考にEPTLをインストール後、下記コマンドを実行
``` bash
yum install fortune-mod

# 動作確認
fortune
```
以上

# なんやかんやいじくりまわした結果の成果物
https://github.com/Teru1917/fortune_gundam_seed_startup

ご自由に使用いただいて問題ありませんが、READMEだけご一読を願います。
これ作るときは下記サイト参考にしました。
[Linuxのシェルログイン時、牛に格言を喋らせる](https://one-it-thing.com/4139/#google_vignette)

# 余談
AmazonLinux2はsystemdとか使われているので多分（ここは深堀してないので調べればわかるかも）CentOS7とかRHEL7を基に作られたんじゃないかという予想。
一応公式に、
> AL2 は CentOS 7 との高い互換性を備えています。その結果、多くの EPEL7 パッケージが AL2 上で動作します。
>
>https://docs.aws.amazon.com/linux/al2023/ug/compare-with-al2.html#epel
より引用

なんて文言があるのでそこからの推測です。

ちなみにここまで読まれて疑問に思った方もいるかもしれませんが、「AmazonLinux2023じゃないのはなんで？」はあると思います。
こちらは、制作過程で私も試したんですが、またしてもさっきのドキュメントにこんな文言が。
>AL2023 は EPEL または EPEL に似たリポジトリをサポートしません。
>
>ttps://docs.aws.amazon.com/linux/al2023/ug/compare-with-al2.html#epel
より引用

まじかよ。
これを見てなんか負けた気がしたので（なんで？）、意地でできないか検証もしてみてます。
[Amazon Linux 2023用追加パッケージを作ろう(立志編)](https://blog.serverworks.co.jp/create-package-for-al2023-01)

上記文献を参考に色々やってみましたが、そもそもRHELの7系→9系にベースが置き換わっていることや、依存関係のある.rpmファイルをすべて拾い上げるのは現実的に工数が足りないので断念しました...

もしご興味ある方いれば代わりにやってみて、私に効率的な方法を教えてください...（Linux版P●izaとかA●Corderみたいで面白そうではあるので今度私もチャレンジはします）

ちなみに、私は種～種死まで通して好きなキャラはノイマンさんでした。
ガンダムシリーズ随一の操舵手、重量下で360°バレルロールする戦艦なんかあるか（誉め言葉）
Lambda環境でのJavaのstaticについて

## 前提
pythonのコードでは関数外のコードは一度しか実行されないという記事を目にしたのでJavaのStaticについても同じ挙動なのか気になり検証した

## 検証
``` java
public class Cache {
    private static Integer number = null;

    public Cache(){}

    public int get(){
        if(number != null){
            number++;
            return number;
        } else {
            number = 0;
            return number;
        }
    }
}

var cache = new Cache();
logger.info("1回目の呼び出し cacheの番号: " + cache.get());
logger.info("2回目の呼び出し cacheの番号: " + cache.get());
```
上記のようにcacheクラスを用意してハンドラー関数内でインスタンス生成とgetメソッドのコールを行う。getメソッドではstaticに入れた内容を記録しておき、+1した値を返す。Nullの場合は0を入れて返す。

実行してみると、下記画像のようになった
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/893794/0262be42-db81-0707-8166-f55fd0aa52d0.png)
つまり、staticがnullで0を入れるのはColodスタートした際の1回のみだった。

## 結論
* staticのライフサイクルはLambdaが終了しても継続した値になる
* 実行環境が終了するまで(warmスタート状態が終わるまで)staticの値は継続する

## 参考
> Operating Lambda: パフォーマンスの最適化 – Part 1
>https://aws.amazon.com/jp/blogs/news/operating-lambda-performance-optimization-part-1/
Pythonで「タプルの要素を昇順または降順に並び替える」の動作を確認してみた

# 概要

Pythonで「タプルの要素を昇順または降順に並び替える」の動作を確認してみました。以下のページを参考にしました。

https://www.javadrive.jp/python/tuple/index9.html

# 実装

以下のファイルを作成しました。
```sample.py
mytuple = ("C", "A", "B")
# 並べ替えを行う
newlist = sorted(mytuple)
# リストからタプルを作成する
newtuple = tuple(newlist)
print(mytuple)
print(newtuple)

numtuple = (55, 78, 92, 82, 65)
newnumlist = sorted(numtuple)
newnumtuple = tuple(newnumlist)
print("Before:", numtuple)
print("After: ", newnumtuple)

animaltuple = ("Dog", "Cat", "Bear", "Deer")
newanimallist = sorted(animaltuple)
newanimaltuple = tuple(newanimallist)
print("Before:", animaltuple)
print("After: ", newanimaltuple)

numtuple = (5, 3.14, 4.78, 4)
newlist = sorted(numtuple)
print(tuple(newlist))

mytuple = ("80", 75, 45, "68")
#newlist = sorted(mytuple)

colortuple = ("Blue", "Red", "Green", "White", "Black")
upcolortuple = tuple(sorted(colortuple))
downcolortuple = tuple(sorted(colortuple, reverse=True))
print("Orig:", colortuple)
print("ASC: ", upcolortuple)
print("DESC:", downcolortuple)
```

以下のコマンドを実行しました。
```
$ python3 sample.py 
('C', 'A', 'B')
('A', 'B', 'C')
Before: (55, 78, 92, 82, 65)
After:  (55, 65, 78, 82, 92)
Before: ('Dog', 'Cat', 'Bear', 'Deer')
After:  ('Bear', 'Cat', 'Deer', 'Dog')
(3.14, 4, 4.78, 5)
Orig: ('Blue', 'Red', 'Green', 'White', 'Black')
ASC:  ('Black', 'Blue', 'Green', 'Red', 'White')
DESC: ('White', 'Red', 'Green', 'Blue', 'Black')
('C', 'b', 'A', 'E', 'd')
('A', 'C', 'E', 'b', 'd')
('A', 'b', 'C', 'd', 'E')
```

# まとめ

何かの役に立てばと。
簡単にNginxでfastapiをデプロイする

# はじめに
今までapacheやtomcatでデプロイすることがほとんどだったが、最近のgoやpythonのフレームワークはNginxでデプロイする方法で書かれていることが多いので、気になって調べてみた。
ついでに最近はまっているfastapiをデプロイするためのフレームワークとした。
Nginxでfastapiを自分でパソコンでデプロイする方法を書いておく。

# Version
windows 11
python: 3.9.13
```txt:requirements.txt
fastapi==0.105.0
uvicorn==0.25.0
```

# fastapi
## fastapiをインストール
- python はインストールされていることが前提
```:cmd
pip install fastapi
pip install uvicorn
```

## fastapi用のファイルを作成する
```python:main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
def mainpage():
    return "hello!"
```


## fastapiを実行する。
```:cmd
# デプロイ用
uvicorn main:app --host 127.0.0.1 --port 8000

# 開発用(リロードあり)
uvicorn main:app --host 127.0.0.1 --port 8000 --reload
```

# Nginx
## Nginxのインストール
https://nginx.org/en/download.html

- Stable Version の	nginx/Windows-1.24.0 をインストール。
- 圧縮解凍しC:/にフォルダをおいた。

```:cmd
# Nginxフォルダに移動
cd C:\nginx-1.24.0

# 実行
start nginx

# 再スタート (設定ファイル編集後)
nginx -s reload

# 停止
nginx -s stop
```

https://qiita.com/Kaisyou/items/dadf6fe9ee93fb69e76c


## Nginxの起動確認
- localhost:80

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/df34af5b-8e89-729e-5a20-ddb628aa6847.png)


## Nginxのnginx.confファイルを編集する

- C:/nginx-1.24.0/conf/nginx.conf


```tex:nginx.conf
    server {
        # 80 -> 81 に変更
        listen 81;
		listen [::]:81;
		server_name localhost;

		root /var/www/プロジェクト;
		index index.html;

        #charset koi8-r;

        #access_log  logs/host.access.log  main;

        # location / {
        #     root   html;
        #     index  index.html index.htm;
        # }

        #追加した部分
        location / {
			proxy_pass http://localhost:8000;
			proxy_set_header Host $http_host;
			proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
			proxy_set_header X-Forwarded-Proto $scheme;
			proxy_redirect off;
        }
```


- listenでportを指定し、location/ {...} を追加した。
- Nginxを再起動
- 外からport81に接続したとき、proxyでlocalで実行中のport8000と通信するようにした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2821152/70293a44-7fd1-381f-0ba3-2e071bfc7a19.png)

- port81から接続して問題なくport8000で起動しているfastapiが動作していることが見える。
- ここでスマホからWifiを切りwww.自分のドメイン:81 or IPアドレス:81に接続すれば動作を確認できる。



# おわりに
今までapacheやtomcatでサーバーを作ってきたので、Nginxを触ったのは初めてだった。少しのネット情報からコピペで簡単にデプロイできたので、かなり軽い印象は受ける。
今後はNginxでgolangのフレームワークなどがデプロイできるようにしたい。