OmniAICreator/Qiita-1.07M huggingface dataset:
Power Automate を使って Adaptive Card を別のTeams チャネルなどにコピーする

# はじめに
Teams のチャネルには Power Automate などをから Adaptive Card という形式でポストすることができます。こんなやつ：
![candidate-form.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/f93849d6-d77c-455c-6da8-bf2bae80df4b.png)
Adaptive Card では、JSON 形式で指定すると、簡単なユーザー入力を促すフォームや、画像と組み合わせたカードを表現することができます。詳細は[この辺](https://learn.microsoft.com/ja-jp/power-automate/create-adaptive-cards "アダプティブ カードを初めて作成する")（Power Automate を用いた Adaptive Card 作成）。
この記事は、この Adaptive Card がチャネルにポストされた際、別のチャネルにコピーするための Power Automate の指定方法を解説するという、多少マニアックな内容です。と言うのも、Power Automate では、「チャネルに新しいメッセージが追加されたとき」を検出し、テキストや Adaptive Card を投稿する機能はそれぞれ持っているのですが、新しいメッセージが Adaptive Card であったときに、その基となる JSON データがどのように取得できるか、ドキュメントがないのです。
Adaptive Card のコピーを実現するために、最終的には、以下のような Power Automate フローを作ることになります。メッセージを受け取り、どうにかして Adaptive Card の JSON を受け取り、それを解析、JSON 項目の内容を個別に取り出した上で Adaptive Card として再投稿します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/9535735e-423a-49d0-2360-ad2e75b1427b.png)
それでは、以下、順を追って詳細をご説明してまいりましょう。
# メッセージの投稿を検出する
それでは、Power Automate を起動し、作成 → 「自動化したクラウド フローを構築する」を選択します。フロー名は適宜設定ください。このサンプルでは、CopyAdaptiveCard とします。トリガーには「チャネルに新しいメッセージが追加されたとき」を選択、フローを作成します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/d83843fe-f47c-8262-4bce-103663c54443.png)
Adaptive Card のポストを検知したいチームとチャネルを指定しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/a6eb0502-f1c1-7856-be10-565cec385f69.png)
# JSON 解析
「＋ 新しいステップ」を押下して、操作を選択します。ここでは、JSON で検索して、アクションに「JSON 解析」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/78bd4e69-f37d-3a6f-b7af-bac28db42fad.png)
JSON の解析 アクションで、コンテンツに「メッセージ 添付ファイル 項目」を選択します。はい、そうです。**Adaptive Card は添付ファイルとして取得できる**のです！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/60bd618f-8a1a-5a3b-c47f-2430d40927c6.png)
すると、添付ファイルは複数想定されていますので、自動で「Apply to each」となります。これは添付ファイル分だけ繰り返されることになります。Adaptive Card が複数ということは一般に考えられませんが、いったん、想定しておくことにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/0f844ef1-533e-950a-3188-cd8ff7fdd43a.png)
JSON の解析のコンテンツには「現在のアイテム」、スキーマには以下の JSON を入力します。
```json:json
{
    "type": "object",
    "properties": {
        "id": {
            "type": "string"
        },
        "contentType": {
            "type": "string"
        },
        "content": {
            "type": "string"
        }
    }
}
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/d3b27aee-fdd7-093e-a66c-3d3c449f29d5.png)
# Adaptive Card の投稿
アクションの追加から、「チャットやチャネルのアダプティブ カードを投稿する」を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/dd8c49fc-da15-6486-e042-8bdb5bd1be57.png)
投稿者、投稿先をチャネル、チーム系、チャネル名を指定、Adaptive Card には content を選択します。Subject はお好みですが、「メッセージ件名」とするのが良いかもですね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/11871/e57ab312-ff48-f47c-f34a-039a48f07df7.png)
# さいごに
以上となりますが、お気づきの通り、チャネル以外にチャットに Adaptive Card を投稿することも可能です。いろいろ試してみてくださいませ！
統計検定2級を受けてみた -合格体験記-

## 統計検定を受けようと思った

現在の業務にデータをもっと活用できたりするのかなと思い、
勉強をして無事合格しましたので参考にしていただければと思います



## 統計検定とは

統計の知識があるかを測る試験です。
今回受けた2級は大学1、2年レベルの理解度で測定するそうです。

[↓公式サイトの情報](https://www.toukei-kentei.jp/about/)
「統計検定」は、統計に関する知識や活用力を評価する全国統一試験です。
データに基づいて客観的に判断し、科学的に問題を解決する能力は、仕事や研究をするための21世紀型スキルとして国際社会で広く認められています。日本統計学会は、国際通用性のある統計活用能力の体系的な評価システムとして統計検定を開発し、様々な水準と内容で統計活用力を認定しています。<br><br>・・・・<br>

といってもよくわからんと思うので、簡単にまとめてみました。

### 統計でわかること

#### 1. データの特徴を知ることができる
これは読んで字の如く、データから性質を知ることができます
皆さんがよく使う**平均**などもデータの性質を表す手段の一つです
その他にもデータがどれだけバラついているかを表す**分散**などもあります。

分散：データがどれだけバラついているか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3100685/4c06b2de-0fc4-2ff6-cd22-3d59c7a21698.png)
[参考：AI Trend](https://ai-trend.jp/basic-study/basic/variance/)

#### 2.データうちの一つが一般的なのか、珍しいのかが分かる
データの標準化（という加工）を行うとデータが全体の中でどれだけ珍しいかが把握できます<br>
ex)
・テストの全体平均から偏差値±10以内（偏差値40〜60）の点数は全体の68％を占める
・テストの全体平均から偏差値20以上(偏差値70以上)の点数は上位2.2%のかなり珍しい数値

※テストの偏差値は標準化を行ったデータなのです

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3100685/cabc414c-78f1-0b3a-e877-b866bb52c602.png)
[参考：AI Trend](https://ai-trend.jp/basic-study/basic/standard-deviation/)

#### 3.データから予測ができる
**もとあるデータから、未来のデータはおおよそこうなる**ということを予測することができます
要因が複数あっても同じ予測できたりします

ex)
折込チラシを〇〇撒くと売上がどのくらい上がるか
web広告を△△配信すると売上がどのくらい上がるか
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3100685/383d99d4-68aa-3d41-1fad-18151f67cd11.png)

[参考：インテージ](https://www.intage.co.jp/glossary/402/)

このような形で色々とわかることがあります


## 勉強について

### 筆者の学習開始前の状態
・経済学部卒、大学で統計の勉強などはしていない
・平均、分散、標準偏差がある程度わかる

### 学習期間
学習した期間：約2ヶ月
総学習時間：だいたい5、60時間

退勤後に1、2時間ちょいちょいと勉強してました

### 勉強したこと
1.統計WEB 
こちらを一周する
以前豊島さんが勉強していると言っていたこちらのサイトを利用しました
ネットに出ている統計検定2級の合格体験記のどれ見てもこのサイトは出てくるので、必須かなと思います。
無料なので助かりました
[統計WEB「統計学の時間」](https://bellcurve.jp/statistics/course/)


2.統計学の本を読む
↓こちらの本を一周しました
公式テキストは統計を初めて勉強する人には全く理解できないとのことだったので、超絶優しいものを探してたどり着きました
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3100685/3ead6593-9f77-aa3f-0696-e2fa5d02c2fa.png)
[完全独習 統計学入門 ](https://www.amazon.co.jp/%E5%AE%8C%E5%85%A8%E7%8B%AC%E7%BF%92-%E7%B5%B1%E8%A8%88%E5%AD%A6%E5%85%A5%E9%96%80-%E5%B0%8F%E5%B3%B6-%E5%AF%9B%E4%B9%8B/dp/4478820090)

3.過去問を解く
過去問集を解いてひたすら問題に慣れる！！
上の二つを勉強して大体わかった気になっていましたが、過去問を解いたらズタボロでした・・・
問題集の解説がなかなかわかりにくいですが、ネットに問題の解説を記事にしている優しい方々がいます、心強い。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3100685/33a74ec3-914d-0f8d-0a47-0e4bbe934cc7.png)
[日本統計学会公式認定 統計検定 2級 公式問題集](https://www.amazon.co.jp/-/en/%E6%97%A5%E6%9C%AC%E7%B5%B1%E8%A8%88%E5%AD%A6%E4%BC%9A/dp/4788925559/ref=pd_bxgy_img_sccl_2/358-5360492-0790261?pd_rd_w=oVGNh&content-id=amzn1.sym.918446e7-72f4-48c7-a672-af3b6ace2b19&pf_rd_p=918446e7-72f4-48c7-a672-af3b6ace2b19&pf_rd_r=PGZ44MWR6JQ7NFG9KKCZ&pd_rd_wg=pndNb&pd_rd_r=5e2c4137-e40e-42e9-872e-9d18d0f10ac6&pd_rd_i=4788925559&psc=1)

問題集を解いて、一周した後に再度解くことで慣れていきました。

### 実際に受けてみた結果
そんなこんなで試験に臨んだ結果・・・


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3100685/82ff4a16-71a0-1648-60bc-6f474f9bb777.png)
<br>
ギリギリ合格することができました！
<br>
皆さんも参考にしていただければと思います。
UE5でライトに赤いバツがついた

:::note
初心者の備忘録です。
公式ドキュメントの和訳が若干分かりづらかったのでまとめ直しているところがあります。
:::

# ライトに赤いバツがついた

![light_batsu.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/924363/8bd6d5d6-387d-7b57-9908-fc261017ed99.png)

ご覧のようにライトに赤いバツがついてしまいました。

# なぜ？

**Stationaryライトが1つのオブジェクトに対して影響を与えられるのは4つまでという制限があるため。**

# ライトアクタのMobility(可動性)

アクタ、今回は特にライトアクタのMobilityについての理解を深めることで、この事象が解決します。

## Static(静的)

Staticは、ゲームプレイ中に**移動も更新もしない**ライトアクタの状態です。

Lightmass(ライトマップを作成するシステム)によって事前計算されるライトマップに反映されます。
このライトはシーンを照らし、StaticおよびStationaryに設定されたアクタ用のライティングデータを生成しますが、Movableの場合は、Indirect Lighting Cacheに保存されたライティングデータまたは Volumetric Lightmaps によって照明され、それらを照らします。

その名の通りStaticですので、変更が生じた場合は都度ビルドをかける必要があります。
影にPreviewなどが表示されている場合、そのライティングはビルドが必要なことを示しています。
逆に言えば、一度ライティングのビルドが完了してしまえば、その後はStaticライトがランタイム時のパフォーマンスに影響を及ぼすことはありません。

## Stationary(固定)

Stationaryは、ゲームプレイ中に**変化はできますが、移動はできない**ライトアクタの状態です。

ゲームプレイ中に色や強度を変えたり、または、オフにしたりと、何らかの方法で変化させることができます。
Stationaryライトは、Lightmassによって事前計算されたライトマップに反映されますが、移動可能(Movable)オブジェクトに動的な影を生成することもできます。

そのため、Stationaryライトにはコストがかかり、1つのオブジェクトに対して同時に影響を与えることができるライトの数が最大4つに制限されています。

## Movable(可動)

Movableは、ゲームプレイ中に**追加・削除・移動が可能**なライトアクタの状態です。

このライトは、ゲームプレイ中に移動させることができ、また、色や強さなどのライトのプロパティを変更することができます。

影の生成にかかるコストが最も高いため、このMobilityを持つライトを使用するときは注意が必要です。

ただし、影を生成しないMovableライトは計算コストが非常に低く、ディスクに保存する必要のあるライティングデータがないため、Staticライトよりもコストが低くなります。

## それぞれのMobilityの関係性

|Mobility|品質|可変性|負荷|
|:-|:-:|:-:|:-:|
|Static|中|低|**低**|
|Stationary|**高**|中|中|
|Movable|低|**高**|高|

※相対的な評価です

# ライトにバツをつけさせない方法

## 方法1: ライトのMobilityを変更する

そのライトが動かず、変更の可能性がなければ、Staticに変更します。
それ以外の場合はMovableに変更します。ただ、負荷が高いので多く配置する場合は注意が必要です。

## 方法2: アクタにライトが影響しないようにする

具体的には、Stationaryライトを減らす、もしくは、ライト同士を遠ざければ良いです。
しかし、これはライティングを変えることになるので、あまり現実的な回避方法ではないかもしれません。

# まとめ

- アクタにはMobilityがある
  - Staticは移動も更新もしないライト
  - Stationaryは変更する可能性はあるが、移動しないライト
  - Movableは追加・削除・移動するライト
- 1つのオブジェクトに対して影響を与えられるStationaryライトは4つまで配置できる
  - Stationaryライトは負荷が高いため
Makefileのコマンド（ターゲット）をまとめてみよう

# 概要

- Makefile内のコマンド（ターゲット）をまとめる方法を簡単にまとめる。

# 内容

- 下記のようなMakefileがあったとする。

    ```makefile
	.PHONY: A
	A:
		echo "A"
	
	.PHONY: B
	B:
		echo "B"
	
	.PHONY: C
	C:
		echo "C"
    ```

- 上記Makefileのカレントディレクトリで下記の様にコマンドを実行すると当然下記の様に出力される。

    ```
    $ make A
    echo "A"
    A
    
    $ make B
    echo "B"
    B
    
    $ make C
    echo "C"
    C
    ```

- 下記の様に記載することでA, B, Cそれぞれのターゲットをまとめる事ができる。

    ```makefile
	.PHONY: A
	A:
		echo "A"
	
	.PHONY: B
	B:
		echo "B"
	
	.PHONY: C
	C:
		echo "C"
	
	.PHONY: all
	all: A B C
    ```

- `$ make all`を実行すると下記の様に出力される。

    ```
    $ make all
    echo "A"
    A
    echo "B"
    B
    echo "C"
    C
    ```

# おまけ

- 自身はlaravelのDocker環境構築によくMakefileを用いる。
- 特に初回環境構築時のcomposer installや.envの作成などのコマンドをまとめるために下記の様に記載する事がある。

    ```makefile
	.PHONY: init
	init:
		docker-compose up -d --build
		docker-compose exec api composer install
		docker-compose exec api cp .env.example .env
		docker-compose exec api php artisan key:generate
		docker-compose exec api php artisan migrate:fresh --seed
		docker-compose exec api php artisan storage:link
		docker-compose exec front npm install
    ```

- 基本的には初回環境構築時のみ使うコマンドたちだが、`docker-compose exec api php artisan migrate:fresh --seed`や`docker-compose exec api cp .env.example .env`なんかはもしかすると初回環境構築時以外にも使いたいことがあるかもしれない。
- ↑そうすると「initターゲットで定義して、さらに別ターゲットで定義する」必要が出てくる。
- 少し冗長かもしれないが筆者は下記の様にしてみた。

    ```makefile
	.PHONY: init
	init: init_container_build \
		composer_install_for_api \
		create_env_for_example \
		ganerate_app_key \
		migrate_fresh_seed \
		create_storage_link \
		npm_install_for_front
	
	.PHONY: init_container_build
	init_container_build:
		docker-compose up -d --build
	
	.PHONY: composer_install_for_api
	composer_install_for_api:
		docker-compose exec api composer install
	
	.PHONY: create_env_for_example
	create_env_for_example:
		docker-compose exec api cp .env.example .env
	
	.PHONY: ganerate_app_key
	ganerate_app_key:
		docker-compose exec api php artisan key:generate
	
	.PHONY: migrate_fresh_seed
	migrate_fresh_seed:
		docker-compose exec api php artisan migrate:fresh --seed
	
	.PHONY: create_storage_link
	create_storage_link:
		docker-compose exec api php artisan storage:link
	
	.PHONY: npm_install_for_front
	npm_install_for_front:
		docker-compose exec front npm install
    ```

- ↑書いてみて思ったが普通に冗長。修正前の「initターゲットで定義して、さらに別ターゲットで定義する」だけが回避できてる、、うーん、、なんか微妙・・？

# 参考文献

https://atmarkit.itmedia.co.jp/ait/articles/1106/10/news115.html

https://qiita.com/6592sho/items/44b37d43d1339fa11a68
Ubuntu + Apache2.4 で Forward Proxy を作る

ある事情でプロキシ(リバースプロキシじゃなくて普通のやつ)が必要になったので久しぶりに Apache を触ったら簡単に設定できたので書きます。試した環境は Ubuntu 18 です。

## インストールとモジュールの有効化

まず、以下のようにして apache2.4 をインストールして必要なモジュールを有効化します。このように `a2enmod` というコマンドでモジュールが有効化するようになっています。このような設定方法は `/etc/apache2/apache2.conf` に書いてあります。

```
sudo apt install apache2
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_connect
```

`apenmod` コマンドは、実際には `/etc/apache2/mods-available/` にある設定ファイルから `/etc/apache2/mods-enabled/` へのシンボリックファイルを貼る事によってモジュールを有効化します。例えば `sudo a2enmod proxy` のように mod_proxy を有効化すると proxy.load と proxy.conf の2つのシンボリックリンクができます。どちらも設定ファイルです。

``` shell
$ ls -l | grep 'proxy\.'
lrwxrwxrwx 1 root root 28 Jan 31 17:35 proxy.conf -> ../mods-available/proxy.conf
lrwxrwxrwx 1 root root 28 Jan 31 17:35 proxy.load -> ../mods-available/proxy.load
```

ここでは３つのモジュールを有効化します。次のような役割があります。

* mod_proxy: Proxy 機能の大本。
* mod_proxy_http: HTTP Proxy
* mod_proxy_connect: HTTPS Proxy (CONNECT メソッドという機能を使って HTTPS をトンネリングする)

## 設定

設定ファイルに変更が必要なのは二箇所です。

`/etc/apache2/ports.conf` に以下を追加

```
Listen 443
```

`/etc/apache2/mods-available/proxy.conf` の ProxyRequests と <Proxy *> を有効化して `Require all denied` を無効化する。

```
        ProxyRequests On
        <Proxy *>
           AddDefaultCharset off
           #Require all denied
           #Require local
        </Proxy>
```

Apache 再起動

```
sudo systemctl restart apache2
```

## クライアント側の設定

Mac の場合以下のようにします。

* Preferences > Network > Wi-Fi > Advanced... > Proxies
    * Web Proxy(HTTP)
        * Web Proxy Server: (プロキシの IP) :80
    * Secure Web Proxy (HTTPS) 
        * Secure Web Proxy Server: (プロキシの IP):443

あと、多分わざわざ Proxy 経由でアクセスしたくなるサイトには DNS にアクセスできないと思うので `/etc/hosts` に必要なエントリを足します。

```
127.0.0.1	localhost
192.168.111.222	secret.example.com
```
Web開発に挑戦! PHP入門


## 概要
PHP (Hypertext Preprocessor) は、Webサイトを作成するために使用されるサーバーサイドスクリプト言語です。

1. 環境構築
XAMPPまたはWAMPを使用して、PHPとWebサーバー（Apache）、データベース（MySQL）をインストールします。
1. スクリプト作成
PHPスクリプトを作成するには、テキストエディター（Sublime Text、Notepad++など）を使用します。
PHPスクリプトは、HTMLコードと同様にWebページに埋め込まれますが、拡張子が「.php」です。
1. PHPの構文
PHPの代表的な構文は、変数の定義、if文、for文、while文、関数などです。
PHPスクリプトは、「<?php」タグで開始され、「?>」タグで終了します。
1. データベースとの連携
PHPは、MySQLなどのデータベースと連携することができます。
MySQLと連携するための代表的な関数には、mysqli_connect、mysqli_query、mysqli_fetch_assocなどがあります。

これらが、PHPの基本的な内容です。詳細な情報は、公式ドキュメントや書籍などを参照してください。

## 環境構築
1. XAMPPを使用する場合：
XAMPPのサイトからインストーラーをダウンロードして実行します。
XAMPPをインストールし、ApacheとMySQLを起動します。
Webブラウザで「http://localhost/」にアクセスして、XAMPPのダッシュボードが表示されることを確認します。
1. WAMPを使用する場合：
WAMPのサイトからインストーラーをダウンロードして実行します。
WAMPをインストールし、ApacheとMySQLを起動します。
Webブラウザで「http://localhost/」にアクセスして、WAMPのダッシュボードが表示されることを確認します。
これで、PHPとWebサーバー、データベースが構築されました。次に、テキストエディターを使用してPHPスクリプトを作成し、「http://localhost/」にアップロードして動作確認することができます。

## スクリプト作成
PHPスクリプトを作成するには、テキストエディター（Sublime Text、Notepad++など）を使用します。
以下のような形式でPHPスクリプトを作成します。
```php
<?php
  // PHPコード
?>
```
PHPスクリプトは、HTMLコードと同様にWebページに埋め込まれますが、拡張子が「.php」です。
PHPスクリプト内には、変数の定義、制御構文、関数などを含めることができます。
PHPスクリプトを保存した後、「http://localhost/」にアップロードして動作確認することができます。
これらが、PHPスクリプトの作成方法の大まかな流れです。詳細な情報は、公式ドキュメントや書籍などを参照してください。


## PHPの構文
### 変数
「$」で始まり、文字列や数値などを格納することができます。
```php
$name = "John Doe";
$age = 30;
```
### 制御構文
条件分岐や繰り返しなどの制御を行います。
#### if文
特定の条件が成立する場合に実行する処理を指定します。
```php
if ($age >= 18) {
    echo "You are an adult.";
}
```
#### for文
特定の回数分の繰り返しを行います。
```php
for ($i = 1; $i <= 10; $i++) {
    echo $i;
}
```
### 関数
特定の処理をまとめて、再利用可能な形式で提供します。
```php
function greet($name) {
  echo "Hello, " . $name;
}
greet("John Doe");
```
これらが、PHPの構文についての一部です。詳細な情報は、公式ドキュメントや書籍などを参照してください。

## データベースとの連携
1. PHPでデータベースと連携するには、MySQLなどのデータベース管理システムが必要です。
1. PHPからデータベースに接続するには、「mysqli」または「PDO」といった拡張モジュールを使用します。
1. 接続後は、SQL文を使用してデータベースの操作（SELECT、INSERT、UPDATE、DELETEなど）を行います。
```php
<?php
$servername = "localhost";
$username = "username";
$password = "password";
$dbname = "database_name";

// MySQLiオブジェクトを作成
$conn = new mysqli($servername, $username, $password, $dbname);

// SQL文を実行してデータを取得
$sql = "SELECT id, name, age FROM users";
$result = $conn->query($sql);

// 結果を表示
if ($result->num_rows > 0) {
    while($row = $result->fetch_assoc()) {
        echo "id: " . $row["id"]. " - Name: " . $row["name"]. " - Age: " . $row["age"]. "<br>";
    }
} else {
    echo "0 results";
}
$conn->close();
?>
```
これらが、PHPからデータベースと連携する方法の大まかな流れです。詳細な情報は、公式ドキュメントや書籍などを参照してください。

## まとめ
この記事では、PHPの基礎的な概念と構文、環境構築、スクリプト作成、データベースとの連携について説明しました。これらの基礎知識を身につけることで、より詳細な学習をすすめることができます。また、この言語を使ったWebアプリケーション開発に挑戦することも可能です。早速、PHPを学び始めて、実践的なスキルを身につけましょう！
VSCode [WSL2:Ubuntu] をTeraTermで接続できるよう構成する

# はじめに
Windows11上のVSCode統合のUbuntuターミナル(bash)は.profileを読み込んで、文字コードはEucJPになっているっぽい（コードエディタの文字コードもVSCodeのsettings.jsonでEucJPに設定済でこちらは問題ない）けど、統合ターミナル(bash)はUTF-8のままうんともすんともいわない。（UTF-8でものもうしている。）
統合ターミナル(bash)の文字コード設定方法が確定するまでのつなぎとして、TeraTermで接続できるよう構成する。

## この記事内容の作業目的
VSCode [WSL2:Ubuntu] をTeraTermで接続できるよう構成する。
EucJPネイティブアプリの文字出力をVSCode [WSL2:Ubuntu] で確認するため。

## この記事内容の作業環境
Windows11
Windows11WSL2（Ubuntu 22.04.1 LTS）
VSCode(Visual Studo Code)　VSCodeUserSetup-x64-1.67.2
TeraTerm teraterm-4.106

## この記事内容の保証
※この記事には環境構築の手順的な情報が含まれます。本記事に書かれた手順の妥当性は保証されません

# sshdのインストール
実行環境はVSCode [WSL2:Ubuntu] です。
VSCodeが起動してWSL2:Ubuntu22.04.1 LTSが起動している状態です。

TeraTermで接続できるようになるまでは統合ターミナル(bash)で作業します。

sshdをインストールします。
WSL2:Ubuntu22.04.1 LTSには/etc/sshフォルダにssh.confはあってもsshd.confがなかったため、sshdをインストールしました。
```bash:
$ sudo apt install ssh
```

こちらの記事を参考にしました。
[How to Enable SSH Service in Ubuntu 22.04 LTS](https://ubuntuhandbook.org/index.php/2022/04/enable-ssh-ubuntu-22-04/)

# sshd構成・起動

あとはこちらにまとめていただいている手順とまったくいっしょです。この当時のWSL:Ubuntuにはsshdが入っているけど起動はしていないという想定で書かれているようです。
[WSL:【Teraterm接続】する方法（Ubuntu）](https://broaden-your-horizons.com/ai-ss/wsl/teraterm/)

```bash:
$ ps -ef|grep ssh|grep -v grep
```
上記コマンドのエコーの返りがないことが起動していないことを意味します。
```bash:
$ sudo ssh-keygen -A
ssh-keygen: generating new host keys: RSA DSA ECDSA ED25519 
$ cd /etc/ssh
$ sudo cp -p sshd_config sshd_config.bk
```
VSCodeのコードエディタは/etc/sshを開けないので古典エディタで編集します。
```bash:
$ sudo vi sshd_config
```
差分が下記のように出るよう編集します。詳しくは参考リンクに書かれています。
```bash:
$ diff sshd_config.bk sshd_config
33c33
< #PermitRootLogin prohibit-password
---
> PermitRootLogin no
57c57
< #PasswordAuthentication yes
---
> PasswordAuthentication yes
```
sshdを起動して、冒頭のコマンドで起動状態を確認します。
```bash:
$ sudo service ssh start
 * Starting OpenBSD Secure Shell server sshd 
$ ps -ef|grep ssh|grep -v grep
root      2244  1282  0 23:20 pts/4    00:00:00 sudo vi sshd_config
root      2245  2244  0 23:20 pts/5    00:00:00 sudo vi sshd_config
root      2246  2245  0 23:20 pts/5    00:00:00 vi sshd_config
root      3818   874  0 23:28 ?        00:00:00 sshd: /usr/sbin/sshd [listener] 0 of 10-100 startups
```

# TeraTermでssh接続

 TeraTermを起動してSSHポート22のlocalhostで接続します。
パスワードの設定が求められるので設定しましょう。

![teratermmind.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3118036/9de59375-c632-9138-dd7b-2c82fe3b1d0e.png)

無事に接続できました！

# 参考リンク

[How to Enable SSH Service in Ubuntu 22.04 LTS](https://ubuntuhandbook.org/index.php/2022/04/enable-ssh-ubuntu-22-04/)

[WSL:【Teraterm接続】する方法（Ubuntu）](https://broaden-your-horizons.com/ai-ss/wsl/teraterm/)
Django から S3 へ画像をアップロードする Example

:::note info
Githubで公開している内容（READMEの内容）です。
ソースコード → https://github.com/takux/example-django-s3
:::

:::note info
Django関連コースを出しているのでこちらもぜひ
→ https://www.takux.one
:::


## Django プロジェクトの作成

必要に応じて仮想環境作成。

```
python3 -m venv venv
```

Django プロジェクトの作成。

```
django-admin startproject myconfig .
```

Django App の作成。

```
python manage.py startapp myapp
```

## 必要なライブラリのインストール

```
pip install Django django-environ boto3
```

Django: フレームワークとして使用
django-environ: 環境変数読み込み用に使用
boto3: S3 へのアップロードに使用

## AWS S3 の設定

Google 検索などで設定の方法を探すと出てくるので割愛。

## 環境変数の設定

.env ファイルを作成し、以下のように設定。
（Github などに公開しないように注意）

```
# DjangoのSECRET_KEY（今回のExampleとは直接関係ないが、Github上にSECRET_KEYは公開すべきでないので設定）
SECRET_KEY=xxx

# AWS S3で設定したアクセスキーやバケット名など
AWS_ACCESS_KEY_ID=xxx
AWS_SECRET_ACCESS_KEY=xxx
AWS_STORAGE_BUCKET_NAME=xxx
```

## Django の設定

今回変更したファイルは以下の通り。

- [myconfig/settings.py](https://github.com/takux/example-django-s3/blob/main/myconfig/settings.py)
- [myconfig/urls.py](https://github.com/takux/example-django-s3/blob/main/myconfig/urls.py)
- [myapp/views.py](https://github.com/takux/example-django-s3/blob/main/myapp/views.py)

## 画像の準備

今回は仮に用意したプロジェクト直下の `screenshot.png` の画像を使用。

## 実行

`python manage.py runserver` して http://localhost:8000/upload/ にアクセスで、S3 に画像（screentshot.png）がアップロード。

![S3に反映された様子](https://user-images.githubusercontent.com/53621441/214451133-bfcec997-e319-4c10-b467-c0704fba7151.png)
同じ項目のカウントと、同じ項目の最初と最後のデータをとる

# はじめに
Twitterでフォロワーの方が困っていらしたので、
似た悩みを抱えた誰かに届きますようにと願い、記録として残します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/fb5b212e-df4f-7f0d-bd14-1d1f4af23fce.png)

# 結論
LINQ使って最初のデータ、最後のデータ、同じ項目のカウントができます。
* 最初のデータ取得
```
どうぶつひょうdt.AsEnumerable().Where(Function (animal) animal("動物名").ToString = "ごりら").First
```
* 最後のデータ取得
```
どうぶつひょうdt.AsEnumerable().Where(Function (animal) animal("動物名").ToString = "ごりら").Last
```
* カウント
```
どうぶつひょうdt.AsEnumerable().Where(Function (animal) animal("動物名").ToString = "ごりら").Count.ToString
```
# 実際にやってみた
例として、こんな表を作りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/de3301f9-59fa-bf92-26db-ed994a548793.png)

改めてみるとやべー表ですが、ご容赦ください。
この中から
* 最初のゴリラのデータ
* 最後のゴリラのデータ
* ゴリラのカウント
を行いたいと思います。
最初と最後のデータがわかりやすくなるように、備考に最初のデータ、最後のデータの旨と、ゴリラに対する無駄知識を記載しました。
## 実装
こんな感じで実装しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/2fcbff41-c530-7eac-21fc-14c45b035f44.png)

## うごかした結果
ちゃんと最初と最後のデータ、
それからゴリラが何頭いるかが出力できました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/abe5c790-1750-7a66-71a0-7470c7a0e899.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/c35338e2-d05c-088f-7216-1126cc8d7fa4.png)

## 備考
抽出したDataRowは元のDataTableに属しているため、そのまま普通に別DTに行追加しようとするとエラーが出ることがあります。（この行は既に別のテーブルに属しています。）

今回はそれを回避するために、ImportRowメソッドを使っています。
参考に、プロパティを記載しておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1846796/847a11ea-95c9-c924-f2b6-05d850e85a77.png)

また、今回は単純にFirst、Lastで実装しましたが、
FirstOrDefault、LastOrDefaultのほうがいい場合もあるかと思いますので、ケースバイケースで対応いただくといいかもしれません。

# 参考文献
https://aftp.tokyo/rpa/uipath/erroor-datarow/

https://learn.microsoft.com/ja-jp/dotnet/api/system.data.datatable.importrow?view=net-7.0

# おわりに
データテーブルの操作はハマると結構時間とられるので、
何かの役に立てていただければ幸甚に存じます。
stripe（connect）の連結アカウントの支払いスケジュールを手動に変更する方法

``` controller.rb 
Stripe::Account.update(
    "attr_×××××××", # 連結アカウントID
    {
        settings: {
            payouts: {
                schedule: {
                    interval: "manual"
                }
            }
        }
    })
```

``` controller.rb
# 上記を１行で表現
Stripe::Account.update(
    "attr_×××××××", # 連結アカウントID
    {
        settings: { payouts: { schedule: { interval: "manual" } } }
    })
```
stripe（connect）においてプラットフォームで作成したcustomerと支払い情報を連結アカウントに複製・コピーする方法

今回はプラットフォームで登録しているサブスクリプション情報をもとに、連結アカウントに顧客情報と支払い情報をコピーしていく。

``` controller.rb 
#　サブスクリプション情報を取得
@sub = Stripe::Subscription.retrieve(
    "sub_××××××××××", # サブスクリプションID
)

# 支払い情報の複製
@payment_method = Stripe::PaymentMethod.create({
    customer: @sub.customer, # カスタマーID
    payment_method: @sub.default_payment_method, # paymentMethodのID
}, {
    stripe_account: "attr_××××××××××", # 複製先の連結アカウントID
})

Stripe::Customer.create({
    email: "text@example.com", #　顧客のメールアドレス
    invoice_settings: {
        default_payment_method: @payment_method.id # paymentMethodのID
    },
    payment_method: payment_method.id # paymentMethodのID
},{
    stripe_account: "attr_××××××××××", # 複製先の連結アカウントID
})

```  
【メモ】
invoice_settingsのdefault_payment_methodに「paymentMethodのID」を設定することで、一括販売・定期販売を作成するときにcustomerを設定するだけでデフォルトの支払い方法で支払いが行われる。

```  controlle.rb
Stripe::Subscription.create({
  customer: 'cus_×××××××', #　デフォルトの支払い方法で支払いが行われる
  items: [
    {price: 'price_×××××××'},
  ],
})

```
SORACOM LTE-M Button for EnterpriseからLINEに通知してみた

元々はSORACOMのモバイル回線利用の流れを体験したかったのだけど、とりあえずボタン押したらLINE通知が来るまでやってみたメモ。

# 環境
MacOS Ventura 13.1
LTE-M Buttion for Enterprise

# やったこと 
結論から言うとネットに転がっている手順とハンズオンをそのまま使えばできたので、何か作ったわけでもない。。
なのでとりあえずやったことをフローとして残すのみ。

1. SORACOMアカウント作る
1. LTE-Mボタンを買う
1. ボタンを使えるようにする
1. LINE Notifyの設定する
1. SORACOM Orbitを設定する
1. SORACOM Beamを設定する

5,6についてはSORACOMハンズオンの手順に従い、唯一のコードもハンズオンにて配られていたWASMファイルをそのまま利用させてもらった。。

唯一のハマりポイントは、SORACOM管理画面をFirefoxで操作してしまっていたため、OrbitでSoraletを作っても正しく表示されなかったというしょぼいもの。。サポートに問い合わせたら丁寧に回答いただいてChromeで操作したら問題なくできた。

それ以外に、SoracomのCLIとかも使えるようにしようとしてたら、Macの開発環境が古くて無駄に時間を使ってしまった。。
おまけでやったこと

- XcodeのCommand Line Toolsのインストール
- home brewのUpdate
- Soracom CLIのインストール

# ボタンを使えるようにするまで
基本的にSoracomの管理画面にて、ユーザマニュアル(Getting Start)に従い進めるのみ。よくできてる。
https://users.soracom.io/ja-jp/guides/getting-started/

実際購入した翌日にボタンは届き、その日のうちに開通して使えるようになった。早い。
なお細かいところだが、

- 単４電池が２本同梱されており、すぐに使えた（嬉しい）
- SORACOMショップから購入したので、SIMの登録もほぼ自動（楽チン）
- ボタン押してメール送信、まですぐ試せる（達成感得られる？）
- SORACOM ButtonはeSIM内蔵なので他の機器にSIM付け替えるものではない

# LINE notifyの設定
1. LINE notifyと友達になる（携帯端末にて）　　
1. PCより管理画面にログインし、Token発行　https://notify-bot.line.me/ja/　　
QRコードでログインが楽チンだった。
3. Tokenをコピーしとく

# SORACOM Orbit, Beamの設定
ハンズオンの途中から。https://soracomug.github.io/soracom-arc-button-simulator-handson/#8

- WASMファイルのDL
    1. ハンズオンのバイナリファイルをDL。これはボタンを押したパターンによって通知メッセージの文章が少しだけ変わるプログラム。https://github.com/soracomug/soracom-arc-v-button-handson/raw/main/soracomOrbit/soralet-wasm.zip
    ソースコードはこちら　https://github.com/soracomug/soracom-arc-button-simulator-handson

- Orbitの設定
    1. Soraletの作成（Chromeでやろう）
    1. WASMファイルをアップロード
    1. SIMグループにSoraletを紐付け
    1. SIMグループにて詳細設定

- Beamの設定
    1. SIMグループにてBeam設定（エントリポイントなど）
    1. ヘッダー操作→カスタムにて詳細設定、ここで一つだけハマりポイント。「値」にLINEのTokenを入れるのだが、先頭に「<b>Bearer </b>」を入れ忘れて最初通知がこなかった。
    
以上、で無事ボタン押すとLINE通知まで完了。

次はGoogleCloudのFunctionから通知ができるようにしようと妄想中。
Ruby timesメソッドで繰り返し処理を行う

# timesメソッド
指定した数値の回数だけ、繰り返し処理を行います。

```ruby
数値.times do
  # 繰り返す処理
end
```

5回繰り返し処理を行う場合は、5times. do~endとなります。

```ruby
10.times do |i|
  puts i + 1
end
```

```
# ターミナル出力
1
2
3
4
5
6
7
8
9
10
```

|i|　これはブロック変数と言います。iは任意の変数です。
##ブロック変数とは、do~endで囲まれた処理のまとまりの言います。

```ruby
数値.times do |ブロック変数|
  # 繰り返す処理
  # 繰り返しの回数を使う場合、ブロック変数を使用する
end
```

# timesメソッドを使って繰り返し処理を行う

timesメソッドを使って、1~100の数字を足し合わせていくための、コードを考えてみる。

```ruby
sum = 0
100.times do |i|
  sum += i + 1
end
puts sum
```

```
5050
# ターミナル出力
```

sum = 0　これは、合計値を保存しておく場所になります。
変数sumに1~100までの数値を順番に足していきます。
順に足していく処理をtimes文の繰り返しで置き換え、puts sumで変数sumの値をターミナルに出力。
setodaNoteCTF - Mistake 100

# 問題

https://ctf.setodanote.net/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/f865b6a6-35fa-f50d-ffbf-6896f56e8904.png)

# 解いてみた

サイトにアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/2bbc0b2c-81cc-0b68-8781-17db5462c145.png)

オープンディレクトリっぽい感じの書きっぷりなので、ソースを開いてcssの場所などを確認します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/f5bad5d6-267c-ad8f-c796-699e695a0b54.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/7b04035e-6b38-4ddc-70b1-f694fa3a0ac8.png)

https://ctf.setodanote.net/web003/ 配下にassetsとimagesがあることがわかりました。
ひとまず、assetsにアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/bde84fb4-bd82-6e57-4188-8be5a98ab43f.png)

やはりオープンディレクトリでした。
全部のフォルダを確認してみましたが、フラグっぽいのはありませんでした。

次にimagesにアクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/56c2792c-294d-242f-03b3-3b1b0f3bc2f1.png)

「pic_flag_is_here.txt」確実にこれでしょう！アクセスしてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/13854c08-2ec5-d351-dd52-747288756aa0.png)
Python3 キーボード入力


Python3 で、キーボード入力があるまで待って、押されたキーを取得する。
簡単でかつよく使いそうな機能なのに、ネットを探してもなかなか見つからないので書いておきます。

何か画面出力をした後にキーボードが押されるのを待って、押されたらまた次の処理を始めたい場合とか、逐次的に、キーボード入力を見たいときってありますよね。
そういう時は、getkeyモジュールのgetkey関数を使いましょう。
しかし、あくまでこの関数は、Terminal入力を受け付けているときのみで、例えばpygameなどを使っていて、別のウィンドウがアクティブになっている時は使えません。

# インストール

```
$ python3 -m pip install getkey
```


# コード

```kb.py
#!/usr/bin/python3
from getkey import getkey,keys

print("Hit any key")

key=getkey() # wait key until keyboard is hit and input with no echoes

if key == keys.UP:
  print("Up key pressed.") # Handle the UP key
elif key == keys.DOWN:
  print("Down key pressed.") # Handle the DOWN key
elif key == keys.F1:
  print("F1 key pressed.") # Handle the F1 key
elif key == chr(10):
  print("Enter key pressed.") # Handle the Enter key
elif key == chr(27):
  print("Escape key pressed.") # Handle the ESCape key
else:
  print(key,"pressed.") # echo back

```
setodaNoteCTF - puni_puni 80

# 問題

https://ctf.setodanote.net/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/3275dec2-c186-f6dc-b80d-20da1b6c943a.png)

# 解いてみた

これは問題文の通りプニコードなので、cyberchefで解きます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/57d96118-1a36-be4d-894a-727554247da8.png)
githubでほかのブランチからmainのブランチに戻れない時にはどうしたらいいの？

githubでmainブランチから枝をはやして、別のブランチで作業していたのですが、main以外のブランチにCommitしてもgithubに草が生えない(Margeすると生える)ので、mainに戻りたのですが、戻れなかったので解決方法をメモ。
### 解決方法
→ただの勘違いでした。
```terminal
git checkout -branch名
```
で、そのブランチから抜け出せると思っていたのですが、実際はcheckout の後のブランチへ移動するコマンドだったんですね。

なので、mainブランチへ移動したい場合は、
```terminal
git checkout main
```
とすればOKでした。
【Swift】インポート範囲を制限

# はじめに
https://github.com/wmorgue/OnflowStatus

このリポジトリのコードを見ていたら以下のようなコードを見つけました。

```swift
import struct SwiftUI.AppStrage
```

気になったので記録しておきます。

# やりかた
```swift
import struct SwiftUI.Color
import class UIKit.UIColor
```

Viewなどにエラーが出ていることから実際にインポート範囲が制限されていることがわかります。
<img width="937" alt="スクリーンショット 2023-01-31 21 36 45" src="https://user-images.githubusercontent.com/84154073/215761689-180855b7-d485-482f-be03-c3ad1b01efd2.png">

# おわり
インポート範囲を制限すると平均ビルド時間が増えるそうです笑

# 参考記事
https://qiita.com/uhooi/items/42787508d85a3df736c8
setodaNoteCTF - Header 50

# 問題

https://ctf.setodanote.net/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/8f0b31ed-cd96-65b6-7b86-4f7fa6756a58.png)

# 解いてみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/341e59de-05d6-0c1d-2662-c7fa70c6dfcf.png)

headを見れば良さそうなので、見てみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/183abf87-f694-bbd2-1c29-0b1a7d0692c1.png)

違いました。HTTPヘッダーのことでしょう。
F12を押して、ネットワークにしてから再度ページを開いてみます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/6a1cc655-9da8-b862-2be9-08f5218a5a33.png)

フラグがありました。
setodaNoteCTF -  Body 30

# 問題

https://ctf.setodanote.net/

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/3e39e8cc-b176-a63f-1133-ce49fc7451f2.png)

# 解いてみた

指定されたサイトを開いてみる。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/3ebaf378-af74-e6b6-b994-24c563d0183d.png)

内面を見るということで右クリックしてソースを表示します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17681/1e296280-88b9-0b95-9a18-290ee890eef6.png)

flagで検索すると答えがありました。
【Rails】Rakeタスク「task xxx: :environment do」の意味


# 結論

`environmentタスク`　→　`xxxタスク(実行する処理)`の順に処理が実行される。

```rb
task xxx: :environment do
    実行する処理
end
```

# 仕組み

- taskの引数にはハッシュが渡っており、key-value相当(`{ xxx: environment }`)の関係にある。
- rakeが提供する`Prerequisites`機能によって、valueのタスクを事前に実行できる。
- Hashリテラルのため、以下のように書いても動作する。

```rb
task :xxx => :environment do
    実行する処理
end

task xxx: [:environment] do
    実行する処理
end
```

# environmentタスク呼び出しの流れ

```
railties/lib/rails/application.rb
  run_tasks_blocks 呼び出し
  ↓
  task :environment を実行
  ↓
  require_environment! 呼び出し
  ↓
  config/environment.rb をrequire

↓

config/environment.rb
  config/application.rb をrequire

↓

config/application.rb
  ENVで環境に応じた変数等を展開する(*)

```


(*)の内容はプロジェクトに依存するが、
上記の場合、実行環境(prd, stage, dev, test等)ごとの値を展開してからメインタスクを実行させることが可能になる。

# 参考

- [Rake Task の定義記法がよくわからなかったので調べた](https://zenn.dev/waddy/articles/ruby-task-syntax)
- [Rails における rake タスクの :environment について \- Qiita](https://qiita.com/FumiyaShibusawa/items/11035fc640bb36a615ad)
【UiPath】グローバル例外ハンドラーでエラー元のアクティビティの種類を取得する

グローバル例外ハンドラーの引数 `errorInfo`の`ActivityInfo.TypeName`からアクティビティの種類を判断することができます。

### 例
まず、エラーが発生したらログを出力してエラーを再度スローするグローバル例外ハンドラーを作ります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/e46952f4-7a9c-2dde-6ab8-90ccea7b2734.png)

次に、`Trueか確認`アクティビティからエラーをスローするだけのワークフローを実行します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/4a537de3-88e1-ab32-60d3-49d0f402676f.png)

結果は以下のようになります。
`Trueか確認`のエラーを拾ってログが出力できてるのはいいですが、囲ったシーケンスの数だけに再度スローされ同じログが表示されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/48384dad-01f8-7e59-8b9e-74f2f898a84d.png)

これを防ぎ、シーケンスからのエラーはログを表示しないようにしたのが以下のグローバル例外ハンドラーです。
条件分岐アクティビティを使い、`errorInfo.ActivityInfo.TypeName`が`System.Activities.Statements.Sequence`だった場合はログを表示しないよう変更しています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/efd036d9-7c85-de26-aae6-3bb05e882970.png)

結果は以下のように、シーケンスからのエラーログを無くし、`Trueか確認`のエラーログだけに出来ています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/578020/5df50501-5f90-6d39-e618-5289d77585b2.png)

## 参考
https://docs.uipath.com/studio/lang-ja/docs/global-exception-handler

## 動作環境
UiPath.System.Activities 22.10.3
method refference of particular type

# type::methodのメソッド参照
instance::methodではなく、type::methodを渡すタイプ。
instanceを渡さないので、method発行する側が
first argumentにtypeのinstanceを指定する。
下記のsampleで、SampleClass#apply(String u)は、single argumentだが
SampleClass::applyのようにメソッド参照指定した場合、apply発行側が
SampleClassのinstanceを指定する。instanceは、first argumentに追加される
もともとfirst argumentであるString uは、押し出される形でsecond argumentになる。最終的にapply(SampleClass s,String u)。
そして、methodは、double argumentとなり、発行側としてはBiFunctionとなる
Supplier(noarg,exist return)であればFunction(one arg,exist return)となる。

この仕組みはqiitaで以下のQ&Aを起票し、@uasi氏より回答をいただき、理解することができた
https://qiita.com/Natukasi/questions/38e42198c0a558b48e34

```java
class SampleClass {
    String str;
    SampleClass(String str) {
        this.str = str;
    }
    public String apply(String u) {
        return str + ":" + u;
    }
}
public class Outer {
    public static void main(String[] args) {
        List<String> l = List.of("sato-a","sato-b","sato-c");
        for(String str:l) {
            String ret = method(SampleClass::apply,str);
            System.out.println(ret);
        }
    }
    static String method(BiFunction<SampleClass,String,String> f, String str) {
        return f.apply(new SampleClass("xxx"),str);
    }
}
```
```
xxxsato-a
xxxsato-b
xxxsato-c
```
PHP Fatal error:  Uncaught PDOException: could not find driver in index.php

エラーのためメモ
```bash
PHP Fatal error:  Uncaught PDOException: could not find driver in /home/kudu/PhpstormProjects/project/index.php:1
Stack trace:
#0 /home/kudu/PhpstormProjects/project/index.php(3): PDO->__construct()
#1 {main}
  thrown in /home/kudu/PhpstormProjects/project/index.php on line 1
```


# php-mysqlをインストール

```bash
sudo apt install -y php-mysql
```
Ubuntu22.04/メモリ不足対応のためスワップ領域を追加する

Ubuntu22.04/メモリ不足対応のためスワップ領域を追加する

# はじめに
以前使っていたPCにUbuntuを入れてみました。  
ブラウザやIDEなどを開いているとちょいちょい固まるので、メモリ不足が疑われました。
メモリ不足に対しては、スワップ領域を追加すると良さそうなので、手順をまとめておきます。

# そもそもスワップって何
メモリが足りないときに、メモリの中身をハードディスクに移すことで、実際のメモリよりも大きなメモリを扱えるという機能です。

# 手順
## 1. スワップ情報を確認
```console
$ sudo swapon --show
```
上記コマンドで、出力がない場合、現在使用可能なスワップ領域がないということになります。手順3のスワップファイルの作成に進んでください。  

下記のような出力が出る場合は、現在スワップ領域があるということになります。  

```console:結果
NAME      TYPE SIZE USED PRIO
/swapfile file   8G   0B   -2
```

スワップ領域を変更する場合は
- 現在のスワップ領域を一度削除して新しく作り直す
- 新しいswapfileを作り、そちらのswapfileを適用させる
という2つの方法があります。  
削除する場合は手順2を、新しく作る場合は手順3を参照してください。  
尚、新しく作る場合は、すでにswapfileがあるため、swapfile2など違う名前で作ってあげればOKです。


## 2.スワップファイル削除  

**不要な方はこの手順スキップ**

1.スワップの解除をする  
```console
$ sudo swapoff -v /swapfile
```

2.`/etc/fstab`のswapの情報を削除
`/etc/fstab`の中に下記のような行があるため、削除する
```
/swapfile none swap sw 0  0
```
  
3.スワップファイルを削除する
```console
$ sudo rm /swapfile
```

## 3.スワップファイルの作成  
1.ハードディスクの空き領域を確認
```console
$ df -h
```

上記コマンドを打って、Mounted onの列が「/」のものがのAvailが空き容量です。  
下記の例だと200Gが空き容量となります。
```console:結果
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           768M  2.4M  765M   1% /run
/dev/nvme0n1p2  234G   23G  200G  11% /
tmpfs           3.8G  118M  3.7G   4% /dev/shm
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
/dev/nvme0n1p1  511M  5.3M  506M   2% /boot/efi
tmpfs           768M  4.7M  763M   1% /run/user/1000
```
　　
2.スワップ領域の割当  

環境のメモリの半分~同じくらいのメモリが目安みたいです。  
メモリが8GBなら4~8GBです。

```console
$ sudo fallocate -l 8G /swapfile
```

3.確認
```console
$ ls -lh /swapfile 
```

```console:結果
-rw-r--r-- 1 root root 8.0G  1月 30 00:13 /swapfile
```
4.パーミッション変更
```console
$ sudo chmod 600 /swapfile
$ ls -lh /swapfile
```

```console:結果
-rw------- 1 root root 8.0G  1月 30 00:13 /swapfile
```

5.スワップファイルへの変換
```console
$ sudo mkswap /swapfile
```

```console:結果
スワップ空間バージョン 1 を設定します。サイズ = 8 GiB (8589930496 バイト)
```

6.スワップファイルの登録
```console
$ sudo swapon /swapfile
```

```console:結果
スワップ空間バージョン 1 を設定します。サイズ = 8 GiB (8589930496 バイト)
```

7.確認
1つ目
```console
sudo swapon --show
```

```console:結果
NAME      TYPE SIZE USED PRIO
/swapfile file   8G   0B   -2
```

2つ目
```console
free -h
```

```console:結果
               total        used        free      shared  buff/cache   available
Mem:           7.5Gi       4.2Gi       851Mi       1.2Gi       2.4Gi       1.8Gi
Swap:          8.0Gi          0B       8.0Gi
```

## 4．スワップファイルの永続化
再起動するとスワップの設定が消えてしまうため、変更を永続化させてあげる必要があります。

1.`/etc/fstab`のバックアップ
`/etc/fstab`を変更しますが、何が問題が起きてもいいようにバックアップをとっておきます。

```console
$ sudo cp /etc/fstab /etc/fstab.bak
```

2.スワップ永続化の設定
```console
$ sudo sh -c "echo /swapfile none swap sw 0 0 >> /etc/fstab"
```
時間を分にする方法

経路時間を表にまとめる際「1時間18分」など日本語入力されているものを
時間が長い・短い順にしようとしてフィルタをつけると **「思う感じに並び替えられれない」**
そこで分に直して計算した列をつけようと思って調べたのでメモ。

#### #計算工程
セルに「1時間18分」と、半角数字と漢字で時間、漢字で分が入ってる場合、分に戻すには
１. セルに入力されてる文字列から「時間」と表示される前までの数値をとってくる
２. １の後、『「時間」の後ろ』から『分』が出てくるまでの数値をとってくる
３. １に60かけて2と足し合わせる
といった工程をすれば良い。

#### #前提として
大前提として例外処理は考えずにスタートする。とりあえず関数組み合わせてみてその後に考えられる入力パターンを考慮する
**1つ目** 文字列の左からX文字をとってくる関数はLEFT()。
引数は２つで第一引数は対象の文字列、第二引数は文字数。
LEFT("1時間15分",2)
とすると「1時」がとってこれる。なお、LEFT(1時間,2)とするとエラーとなるので、文字列は""でかこっておく必要がある。
**2つ目**　右からX文字をとってくる関数はRIGHT()。
使い方はLEFTと同じで引数の指定も（対象文字列,文字数）
なお、LEFTとRIGHTの第二引数は省略可能だが省略したときに得られるのはLEFTは先頭１文字、RIGHTは最後１文字。
**3つ目**「時間」「分」が出てくるまでを指定しないといけないのでFIND()を使う
FINDの引数は3つで第一が指定したい文字列、第二が対象文字列(分に戻したい対象セル)、第三引数が開始位置
第三引数は省略でき、デフォルトは１が指定されている。
FIND("時間",A2)とする「２」と返ってくる。

#### #本題
セルA2に「1時間18分」と入っているとする。
・工程１「時間」までの数値をとる
B2を計算結果が表示されるセルとする。セルB2に
LEFT(A2,FIND("時間",A2)-1)
と入力すると1が返ってくる。
・工程２ 時間の後ろから分までの数値をとる
1文字目から考えると「"時間"が出てから文字をとっていって"分"が出る前までの文字をとる」だが、
工程２でやりたいのは単純に考えると **「分の部分の数値をとりたい」** なので右から3文字とって分を消せばいい
そこでB2に
LEFT(RIGHT(A2,3),2)
と入力する。RIGHTで右から3文字とってとってきた「XX分」の左2文字をとる。
そうすると18が返ってくる。
・工程３ とってきた時間と分を足して計算
B2に
LEFT(A2,FIND("時間",A2)-1)*60+LEFT(RIGHT(A2,3),2)
とすれば78が得られる。
【応用分野】各プログラミング言語は何ができるかを見てみよう

多くの人がプログラミングを学ぶのは常に頭が熱くなってからネットで資源を探して勉強を始めます。学んでみると今学んでいることは自分が一番好きなものではなく、別の技術をもっと好きなようで、間違っていると感じて、また別のことを勉強するようになった。
![代替テキスト](https://jp.scrapestorm.com/wp-content/uploads/2022/12/%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80.png)
プログラミング言語を学ぶ前に、どの分野に適用されるかを明らかにしなければなりません。本文は、いくつかのプログラミング言語の応用分野を説明し、何ができるかを見てみましょう。
## 1.C言語
C言語の主な応用分野は、オペレーティングシステム、組み込みシステム、およびサーバーであり、底辺で広く使われている強力な高級言語です。たとえば、世界のオペレーティングシステムの90%以上を占めているMicrosoftのWindowsシステム、そのコアはC言語で書かれています。しかし、C言語は習得が難しいことでも有名で、C言語に精通していれば、収入は決して低くはありません。
## 2.Java
Java は主にエンタープライズレベルのアプリケーション開発、ウェブサイトプラットフォーム開発、モバイルゲームやAndroid 開発に使用されており、例えば、数多くの取引サイト(Taobao、Tmallなど)の開発にはJavaが使用されています。C言語に比べてJavaは学びやすいです。Javaは現在、市場で最も多くの雇用機会がある言語であると同時に、競争が最も激しいです。
![代替テキスト](https://jp.scrapestorm.com/wp-content/uploads/2022/12/java-2327538-1500x848.png)
## 3.Python
Pythonの主な応用分野は、クローラー、データ分析、機械学習であり、一部の中小企業ではバックエンド開発に使用され、比較的学びやすくて開発効率が高い言語です。但し、ソフトウェア企業の製品開発には、効率的で完全な開発ワークフローソフトウェアのサポートが不足しているPythonは、すべてのプログラミング言語のランキングで1位を占めていますが、依然として議論されています。
## 4.C++
C++は主にゲーム分野、オフィスソフトウェア、グラフィック処理、Webサイト、検索エンジン、リレーショナルデータベース、ブラウザ、ソフトウェア開発、統合環境IDEなどに使用されています。C++の現在の求人状況では、Javaに次いで求人数が多く、学習難易度も低くありません。C++で書かれたゲームエンジンの代表作を見てみましょう。
![代替テキスト](https://jp.scrapestorm.com/wp-content/uploads/2022/12/C.png)
## 5.JavaScript
JavaScriptは以前は主にフロントエンド開発に使用され、Webのフロントエンドでも揺るぎない地位を確立しましたが、現在では JavaScript はフロントエンドだけでなく、バックエンドの Node.js にも使用されています。フロントエンド、バックエンドの開発にはJavaScriptの習得が必須と言えます。
Flutter - サイコロを振るアプリ

Flutterでようやく実用的なアプリが作れるようになってきたので、次のアプリ開発の参考までに開発したアプリのコードをメモしておきます。サイコロをタップしてランダムな目を出すことができるアプリです。

![スクリーンショット 2023-01-31 204536.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/337578/c1c03fed-17d1-506e-5e2e-5f3410b43fac.png)


## pubspec.yamlの記述
画像ファイルを読み込むための記述を描きました。
55行目の`flutter:`以降に画像ファイルが入っているフォルダをしているすればオッケーです。

```dart
flutter:

  # The following line ensures that the Material Icons font is
  # included with your application, so that you can use the icons in
  # the material Icons class.
  uses-material-design: true

  #imagesフォルダーを依存関係に追加する
  assets:
    - images/
```

## main.dartのコード
```dart
//Mathをインポートする
import 'dart:math';
import 'package:flutter/material.dart';

//ダイスを振ってランダムで表示するアプリ
//スカフォールドウィジェットの中にステートフルウィジェットをオーバーライドして埋め込む
void main() {
  return runApp(
    MaterialApp(
      home:Scaffold(
        backgroundColor: Colors.red,
        appBar: AppBar(
          title: Text("Dicee"),
          backgroundColor: Colors.red,
        ),
        body: DicePage(

        ),
      ),
    ),
  );
}

//変数を操作するタイプのアプリを作る場合は、ステートフルウィジェットにする
//ステートフルにすると、変数が更新された際にステートフルウィジェット全体が更新される
class DicePage extends StatefulWidget{
  @override
  _DicePageState createState() => _DicePageState();
}

//ウィジェットの中のクラスをオーバーライドする
class _DicePageState extends State<DicePage> {
  int leftDiceNumber01 = 1;
  int leftDiceNumber02 = 6;

  //変数の更新は関数を使って簡略化する
  void changeDiceFace(){
    setState((){
      leftDiceNumber01 = Random().nextInt(6) + 1;
      leftDiceNumber02 = Random().nextInt(6) + 1;
    });
  }

  @override
  Widget build(BuildContext context){
    //サイコロを表示するロウを作成する

    return Center(
      child: Row(
        children: <Widget>[
          Expanded(
            child:Padding(
              padding: const EdgeInsets.all(10.0),
              child: MaterialButton(
                //イメージを変更する
                onPressed: (){
                  changeDiceFace();
                },
                child: Image(
                  image: AssetImage("images/dice$leftDiceNumber01.png"),
                ),
              ),
            ),
          ),
          Expanded(
            child:Padding(
              padding: const EdgeInsets.all(10.0),
              child: MaterialButton(
                onPressed: (){
                  changeDiceFace();
                },
                child: Image(
                  image: AssetImage("images/dice$leftDiceNumber02.png"),
                ),
              ),
            ),
          ),
        ],
      ),
    );
  }
}

```

Flutterではステートフル・ステートレスという概念があり、ステートレスなウィジェットはウィジェット内のクラスの変数が変更されるとそれに伴いウィジェット自体がすべて更新される、という処理を行えるようになってます。変数を変更するたびに画像や表示するウィジェットを更新する関数を駆動しなくても良い設計ができる訳ですね。
【コマンドライン | Elixir 】コマンドラインからパイプ処理をする

コマンドラインの結果パイプでつないで、Elixirで処理をしたいと思います

# お題
・dmesgからCPUの文字列の行を取得する
・今回はgrepは無しね

# メモリに書き込んで処理をする　/dev/shm　
駄目な例　私の案（思いつかなかったので強引）

```
sudo dmesg > /dev/shm/hoge.txt; elixir -e ' File.read!("/dev/shm/hoge.txt") |> String.split("\n") |> Enum.filter(fn x-> String.match?(x, ~r/CPU/) end) |> IO.inspect()'
```

# IO.read(:stdio, :all)
@GeekMasahiroさんの案
頂いたヒント
```
echo aaaa | elixir -e 'IO.read(:stdio, :all)|>IO.inspect()'
```

それを元に
```
sudo dmesg | elixir -e 'IO.read(:stdio, :all) |> String.split("\n") |> Enum.filter(fn x-> String.match?(x, ~r/CPU/) end) |> IO.inspect()'
```

`IO.read(:stdio, :all)`でいける

# そもそもdmesgって
@pojiroさんの案

`/var/log/dmesg`を直接読む
これを知らなかった
dmesgの結果を取得して加工するが目的であればベストアンサーだと思います
この方法のメリットは管理者権限がなくてもできる

```
elixir -e 'File.read!("/var/log/dmesg") |> String.split("\n") |> Enum.filter(fn x-> String.match?(x, ~r/CPU/) end) |> IO.inspect()'
```

ちょっとしたコマンド遊びでした
PROMPTに2byte文字が入る際のエスケープ

- MacOS Ventura (13.1 22C65), 2023
- zsh 5.8.1 (x86_64-apple-darwin22.0)

# シェルのプロンプト
`.zshrc`を弄っていたら、[TAB]キーでの補完結果の表示がおかしくなりました。
具体的に言うと、
```sh
> ls␣ 
```
の時に[TAB]を押すと、
```sh
> ls␣ls␣
Applications/ Downloads/   ...
Desktop/      Library/     ...
Documents/    Movies/      ...
```
のようになってしまいます。
ただ、表示がおかしいだけで、実行は正しく行えます。

# 原因と対処法
色々と弄った結果、`prompt_subst`ではなくzshの`PROMPT`に要因があると分かりました。

**PROMPT内で2byte以上の文字**を表示させているのが良くないみたいです。
**アルファベットと数字と記号のみを表示**するように変更しても良いですが、気に入っている今のPROMPTを変えたくないです（苦労して調節した表示ですし）。

そこで対処法を調べたところ、その文字の周囲を`%G`でエスケープすると良いらしいことが分かりました。
具体的には、
```zsh:.zshrc
PROMPT='aaa→bbb'
```
の`→`をエスケープしたいなら、
```zsh:.zshrc
PROMPT='aaa%{%G→%}bbb'
```
のように`%{%G`と`%}`で囲んでエスケープ。
当環境ではこれでうまくいきました。

色々やった際に久々に使った`locale`コマンドですが、`LANG`の設定の`C`と`ja_JP.UTF-8`では違いがありませんでした…

# 最後に
シェルの環境設定(rc,profile)を弄って作業の快適度を上げることはかなり重要です！
問題解決ではStackOverflowを活用することも多いですが、シェル設定ならQiitaに大量の先達の記事があります。
ということで、自分の環境を弄る際に参考にしたQiita記事などを貼っておきます。

- [zshプロンプトのカスタマイズ](https://qiita.com/yamagen0915/items/77fb78d9c73369c784da)
- [zshでプロンプトをカラー表示する](https://qiita.com/mollifier/items/40d57e1da1b325903659)
- [お前らのターミナルはダサい](https://qiita.com/kinchiki/items/57e9391128d07819c321)
- [可愛いzshの作り方](https://itchyny.hatenablog.com/entry/20110629/1309355617)
【RISC-V・Ubuntu】QemuでRISC-Vシミュレータを構築する

## 背景
　前回までの記事で、IntelのIntrinsic関数をRISC-VやARMにポートする技術のアイディアを書いてきました。

https://qiita.com/daisukeokaoss/items/c0b94eb86a42c28dcce8

 さて、ここで必要になるものがあります。RISC-Vの機械語を動かせるマシンです。この記事では、Intel上でRISC-Vのエミュレータをインストールする方法について記述します。エミュレータは実機とは異なるので、エミュレータを使う場合は、ポートにおけるバグとともに、エミュレータのバグにも対処しなければなりません。その問題はありますが、RISC-Vの実機がなくてもポートの作業ができるということで、それなりの利点はあると思われます。

今回は、Ubuntu 22.01 LTSを使用しました。

## インストール
まずは、適当なディレクトリをmkdirで作成し、ディレクトリ内に入って、以下のコマンドを実行します。

以下のコマンドでRISC-Vのqemuをインストール

```
sudo apt install qemu-system-riscv64
```

以下のコマンドで、RISC-V版のUbuntuをディレクトリにダウンロードします。
```
wget https://cdimage.ubuntu.com/releases/22.04/release/ubuntu-22.04.1-live-server-riscv64.img.gz
```

リンクが効かなくてダウンロードできない場合は、以下のページよりリンクを拾い直してください。
https://cdimage.ubuntu.com/releases/22.04/release/

以下のコマンドで解凍する。
```
gzip -d ubuntu-22.04.1-live-server-riscv64.img.gz
```

別のバージョンをダウンロードした場合は、適宜読み替えてください。

以下のコマンドで、設定
```
qemu-img resize -f raw ubuntu-22.04.1-live-server-riscv64.img +5G
```

```
dd if=/dev/zero bs=1M of=disk count=1 seek=16383
```



以下のコマンドで、OpenSBIを起動
```
qemu-system-riscv64 \
-machine virt -nographic -m 512 -smp 1 \
-device virtio-rng-pci \
-drive file=ubuntu-22.04.1-live-server-riscv64.img,format=raw,if=virtio
```

OpenSBIは閉じてしまって構いません。

以下のURLからUbuntu Server 22.04.1をダウンロード
https://ubuntu.com/download/risc-v


以下のコマンドにより、Ubuntu Server 22.04.1を解凍
```
xz -dv ubuntu-22.04.1-preinstalled-server-riscv64+unmatched.img.xz
```

以下のコマンドを実行
```
wget https://cdimage.ubuntu.com/cdimage/ubuntu-server/jammy/daily-live/pending/jammy-live-server-riscv64.img.gz
```

以下のコマンドを実行
```
gzip -d jammy-live-server-riscv64.img.gz 
```

ファームウェアのインストール
```
sudo apt install u-boot-qemu opensbi
```

以下のコマンドにより、インストールプロセスが始まります。
```
/usr/bin/qemu-system-riscv64 -machine virt -m 1G -smp 1 -nographic \
-bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.bin \
-kernel /usr/lib/u-boot/qemu-riscv64_smode/u-boot.bin \
-netdev user,id=net0 \
-device virtio-net-device,netdev=net0 \
-drive file=jammy-live-server-riscv64.img,format=raw,if=virtio \
-drive file=disk,format=raw,if=virtio \
-device virtio-rng-pci
```




インストールが終わったら、以下のコマンドにより、再び起動します

```
qemu-system-riscv64 -machine virt -m 1G -smp 1 -nographic \
-bios /usr/lib/riscv64-linux-gnu/opensbi/generic/fw_jump.bin \
-kernel /usr/lib/u-boot/qemu-riscv64_smode/u-boot.bin \
-netdev user,id=net0,hostfwd=tcp::60022-:22 \
-device virtio-net-device,netdev=net0 \
-drive file=disk,format=raw,if=virtio \
-device virtio-rng-pci
```

C言語を使いたければ、build-essentialを入れます。

```
sudo apt install build-essential  
```
esp-idf: mqtt5 の使い方

esp/esp-idf/examples/protocols/mqtt5 のプログラムを改造します。
M5Stack Core2 で動作確認をしました。
次にパブリッシュするのを確認しました。
>ブローカー　mqtt.eclipseprojects.io
>トピック　/topic/qos1

## プログラム

プロジェクトのコピー

```bash
cd ~/esp
cp -r ~/esp/esp-idf/examples/protocols/mqtt5 .
```

tcp/sdkconfig を作成

```bash
idf.py build
```

変更する場所

```text:mqtt5/sdkconfig
（省略）
CONFIG_EXAMPLE_WIFI_SSID="****"
CONFIG_EXAMPLE_WIFI_PASSWORD="****"
（省略）
```

"こんにちは Hello data_3" を publish するようにします。

```c:mqtt5/main/app_main.c
（省略）
        esp_mqtt5_client_set_publish_property(client, &publish_property);
        msg_id = esp_mqtt_client_publish(client, "/topic/qos1", "こんにちは Hello data_3", 0, 1, 1);
        esp_mqtt5_client_delete_user_property(publish_property.user_property);
        publish_property.user_property = NULL;
（省略）
```

## コンパイル、実行

```bash
idf.py -p /dev/ttyUSB0 flash
```

## テスト結果

サブスクライブするスクリプト

```bash:go_sub_mqtt.sh
mosquitto_sub -d -t orz -V mqttv5 -h mqtt.eclipseprojects.io \
    --topic /topic/qos1
```

スクリプトのけっか

```text
$ ./go_sub_mqtt.sh 
Client (null) sending CONNECT
Client auto-2DA00A77-2CB7-79CF-4E0D-3B787C09A084 received CONNACK (0)
Client auto-2DA00A77-2CB7-79CF-4E0D-3B787C09A084 sending SUBSCRIBE (Mid: 1, Topic: orz, QoS: 0, Options: 0x00)
Client auto-2DA00A77-2CB7-79CF-4E0D-3B787C09A084 sending SUBSCRIBE (Mid: 1, Topic: /topic/qos1, QoS: 0, Options: 0x00)
Client auto-2DA00A77-2CB7-79CF-4E0D-3B787C09A084 received SUBACK
Subscribed (mid: 1): 0, 0
Client auto-2DA00A77-2CB7-79CF-4E0D-3B787C09A084 sending PINGREQ
Client auto-2DA00A77-2CB7-79CF-4E0D-3B787C09A084 received PINGRESP
Client auto-2DA00A77-2CB7-79CF-4E0D-3B787C09A084 received PUBLISH (d0, q0, r0, m0, '/topic/qos1', ... (28 bytes))
こんにちは Hello data_3
```