OmniAICreator/Qiita-1.07M huggingface dataset:
Java Chromium Embedded FrameworkでのJavascriptからJava呼び出し。2

# intercept

httpの通信をinterceptする。
たとえば、[http://xxx/]()といったURLを使ってローカルファイルを返すとか......

シーケンス図：
＃getResourceRequestHandlerでurlを見ることもできる。

```plantuml
@startuml
!theme aws-orange

participant "Cef\nApp" as CefApp
participant "Cef\nCallback" as CefCallback
participant "Cef\nResponse" as CefResponse

participant "Cef\nRequest\nHandler" as CefRequestHandler
participant "Cef\nResource\nRequest\nHandler" as CefResourceRequestHandler
participant "Cef\nResource\nHandler" as CefResourceHandler

hide footbox

== 初期化 ==

-> CefRequestHandler: new()
-> CefApp: addRequestHandler()

== リクエスト ==

CefApp -> CefRequestHandler: getResourceRequestHandler(browser: CefBrowser,frame: CefFrame,req: CefRequest, ...)
CefRequestHandler -> CefResourceRequestHandler: new()
CefApp <-- CefRequestHandler

CefApp -> CefResourceRequestHandler: onBeforeResourceLoad(brower: CefBrowser,frame: CefFrame,req: CefRequest)
CefApp <-- CefResourceRequestHandler: false
note right
falseで続行、trueで中断。
end note

CefApp -> CefResourceRequestHandler: getResourceHandler(brower: CefBrowser,frame: CefFrame,req: CefRequest)
alt req.getURL().startsWith("http://xxx/")
CefResourceRequestHandler -> CefResourceHandler: new
CefApp <-- CefResourceHandler
CefApp -> CefResourceHandler: processRequest(req: CefRequest, callback: CefCallback)
  CefResourceHandler -> CefCallback: Continue()
CefApp <-- CefResourceHandler
CefApp -> CefResourceHandler: getResponseHeaders(res: CefResponse)
  CefResourceHandler -> CefResponse: setStatus(200)
  CefResourceHandler -> CefResponse: setMimeType("text/html")
CefApp <-- CefResourceHandler

loop trueを返している間
CefApp -> CefResourceHandler: readResponse(data: byte[], size: int)
  CefResourceHandler -> Resource: read(data, size)
  CefResourceHandler <-- Resource: size/0
CefApp <-- CefResourceHandler: true/false
end

end

@enduml
```
toio＋カプセルトイで楽しい見た目に！

# 記事について
先にお断りを入れると一切のソフトウェアエンジニアリング要素は本記事にはありません！！！


# 初めに…
toioはレゴブロックを取り付けて装飾することが可能になっています。

しかし、レゴブロックで高クオリティの造形を作るのが難しいです。
3Dプリンターという選択肢もあるのですが…3Dプリンターで造形した場合、基本的には単色のものになり、色は自分で塗る必要がありなかなか大変です…

そこで既製品を使ってよい見た目にしちゃおうという趣旨が今回の記事です。

ガワを変えるだけで、結構新鮮な気持ちになるのでかなり良いです。
またカプセルトイは数百円程度ながらかなりクオリティの高いものも多いので、toioを様々な見た目にすることもできます。


# 1.テープでくっつけちゃえ
一番手っ取り早いのが……
toioの上のフタにテープなどで、カプセルトイくっつけてしまうことです。
両面テープで貼ってしまえばよいだけです。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">toioはガチャガチャのフィギュア載せると楽しいです。<br><br>amiibo乗せようとしたけど重心が高くなって安定しなかった。。、 <a href="https://t.co/5CdCWHsl0f">pic.twitter.com/5CdCWHsl0f</a></p>&mdash; 黒河優介(YusukeKurokawa) (@wotakuro) <a href="https://twitter.com/wotakuro/status/1254006089797914624?ref_src=twsrc%5Etfw">April 25, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

※画像では 3Dプリンターで上のフタを鋳造しています。

なおこれをやったときに問題は重心がだいぶ上目になるので、急加速・急停止をすると toio本体が倒れそうになります。
カプセルトイぐらいだとギリギリ耐えるのですが…それよりも大きなフィギュアなどは重心の高さに耐えられないのですぐ倒れてしまいます。

#2. 奇跡のフィット感

toioは3cm × 3cmなのですが…
時々、ジャストフィットアイテムがあったりします。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">カプセルトイの神輿がtoioぴったり過ぎてビックリー。<br>あと御所車もいい感じ <a href="https://t.co/bfiLtFLALv">pic.twitter.com/bfiLtFLALv</a></p>&mdash; 黒河優介(YusukeKurokawa) (@wotakuro) <a href="https://twitter.com/wotakuro/status/1449292459167469573?ref_src=twsrc%5Etfw">October 16, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

画像はこれらの商品でやっていますが、奇跡のフィット感でした。

https://www.takaratomy-arts.co.jp/items/item.html?n=Y897146

https://www.fumuo.jp/view/item/000000000967?category_page_id=sample1

#3.くりぬいてはめ込んでしまえ…

ちょっと大きめのものでも3cm × 3cm でくりぬいてしまえばよいです。
またレゴブロックで高さも調節できるので、とにかくくり抜いてしまえば何とかなります。

と言う事でやってみたのがこちら…


<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">こんな感じで動くのじゃ！！ <a href="https://t.co/YfE1OOw89j">pic.twitter.com/YfE1OOw89j</a></p>&mdash; 黒河優介(YusukeKurokawa) (@wotakuro) <a href="https://twitter.com/wotakuro/status/1443244554786770945?ref_src=twsrc%5Etfw">September 29, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


ちなみに、この商品です。
https://gashapon.jp/products/detail.html?jan_code=4549660708537000

toioとカプセルトイ、組み合わせると見た目もいろいろと変えて楽しめるのでお勧めです。
カプセルトイ以外にも食玩なんかも面白いかもしれません。

と言う事で ゆるふわ記事でした。
moldとcargo watchを併用してより快適な開発環境を作る

# はじめに
弊社では業務でActix Webを使用してバックエンドの開発を行っています。
普段は以前書いた「[actix-webのホットリロードされるDocker開発環境を作る](https://qiita.com/kyamamoto9120/items/c391f0ce5050c5ddcc87)」という記事のように `cargo watch` を使用してホットリロードされる開発環境を作って開発をしているのですが、ホッとリロードされるとは言え毎度のビルドにはそこそこの時間がかかり、地味なストレスになっています。

そんな折、「[moldを使うとRustのビルドが速くなる](https://keens.github.io/blog/2021/12/20/moldwotsukautorustnobirudogahayakunaru/)」という記事を拝読してmoldというリンカーを知ったので早速試してみたいと思います。

# 本題

前述の自筆の記事では `docker-compose.yml` で

```
/bin/sh -c "cargo watch -x run"
```

というコマンドを渡すことでホットリロードする開発環境を作成してました。
重要なのは `cargo watch -x run` の部分ですが、moldをインストールした上でこれを

```
cargo watch -s 'mold -run cargo run'
```

のように変更することでmoldを使用したホットリロードする開発環境にすることが出来ます。

手元の簡単なActix Webのプログラムで `cargo watch -x run` と `cargo watch -s 'mold -run cargo run'` の実行速度を比較した結果は以下の通りです。


**cargo watch -x run**

```
$ cargo watch -x run
[Running 'cargo run']
    Finished dev [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/actix-web-example`
[Running 'cargo run']
   Compiling actix-web-example v0.1.0
    Finished dev [unoptimized + debuginfo] target(s) in 4.35s
     Running `target/debug/actix-web-example`
```


**cargo watch -s 'mold -run cargo run'**

```
$ cargo watch -s 'mold -run cargo run'
[Running 'mold -run cargo run']
    Finished dev [unoptimized + debuginfo] target(s) in 0.05s
     Running `target/debug/actix-web-example`
[Running 'mold -run cargo run']
   Compiling actix-web-example v0.1.0 
    Finished dev [unoptimized + debuginfo] target(s) in 1.72s
     Running `target/debug/actix-web-example`
```

4.35 / 1.72 ≒ 2.5 くらいで、3倍とまでは言わないですが非常に効果は大きそうです。


# 余談

最近は `docker-compose.yml` には以下のようなコマンドを与えていて、編集すると同時にフォーマットが行われるようにしています。自動生成のコードもすぐにフォーマットされるので個人的にはなかなか便利で良いと感じています。

```
cargo watch -x fmt -x run
```

これをmoldに対応すると

```
cargo watch -x fmt -s 'mold -run cargo run'
```

となります。


# まとめ
moldは非常に簡単に導入することができ、確実に開発体験を良くしてくれそうでした。
早速プロジェクトの開発環境も改善したいと思います。
浮動小数点形式の演算結果として +0 と -0 が出てくる規則

**お断り：ここでは非数と無限大については考慮していません。**

# IEEE-754 倍精度浮動小数点形式

Python の float や JavaScript の Number は IEEE-754 倍精度浮動小数点形式となっています。

| 符号部(S) | 指数部(E) | 小数部(T) |
|:-:|:-:|:-:|
| 1 ビット | 11 ビット | 52 ビット |

式で表現すると

```math:
\left( -1 \right)^{S} \times 2 ^{E-1023} \times \left( 1 + \frac{ T }{ 2^{52} } \right)
```

になります。($E=0$の場合を除く)

# 浮動小数点演算器（FPU）の挙動

浮動小数点演算器（FPU）はどのような計算をしているのか考えます。

## 乗除算

指数部と小数部を考慮せず、符号部に注目すると

| 計算 | 被乗数 | 乗数 | 結果 |
|:-:|:-:|:-:|:-:|
| 正 × 正 = 正 | 正（S=0） | 正（S=0） | 正（S=0） |
| 正 × 負 = 負 | 正（S=0） | 負（S=1） | 負（S=1） |
| 負 × 正 = 負 | 負（S=1） | 正（S=0） | 負（S=1） |
| 負 × 負 = 正 | 負（S=1） | 負（S=1） | 正（S=0） |
| **計算** | **被除数** | **除数** | **結果** |
| 正 ÷ 正 = 正 | 正（S=0） | 正（S=0） | 正（S=0） |
| 正 ÷ 負 = 負 | 正（S=0） | 負（S=1） | 負（S=1） |
| 負 ÷ 正 = 負 | 負（S=1） | 正（S=0） | 負（S=1） |
| 負 ÷ 負 = 正 | 負（S=1） | 負（S=1） | 正（S=0） |

となります。これは、符号部（1 ビット）の XOR で済みます。

結果が "0" のとき、符号部をどちらかに決めるとなると、0 を判定するために

- 判定回路を追加する
- 判定処理を追加する

などのコストが発生し、かつ演算性能が落ちる、というデメリットまで生じかねません。

だったら、+0 と -0 はそのままにしておく方が良いです。

## 加減算

加減算では、符号を整理すると「同符号の加算」と「同符号の減算」に分けることができます。

### 同符号の加算

乗除算同様に、以下のパターン

| 計算 | 被加減算数 | 加減算数 | 結果 | 同符号の加算 |
|:-:|:-:|:-:|:-:|:-:|
| 正 + 正 = 正 | 正（S=0） | 正（S=0） | 正（S=0） | 正 + 正 |
| 正 - 負 = 正 | 正（S=0） | 負（S=1） | 正（S=0） | 正 + 正 |
| 負 - 正 = 負 | 負（S=1） | 正（S=0） | 負（S=1） | 負 + 負 |
| 負 + 負 = 負 | 負（S=1） | 負（S=1） | 負（S=1） | 負 + 負 |

では、符号部（1 ビット）だけの論理演算で済みます。これも乗除算と同様です。

### 同符号の減算

上記以外の加減算は

| 計算 | 被加減算数 | 加減算数 | 結果 | 同符号の減算 |
|:-:|:-:|:-:|:-:|:-:|
| 正 - 正 = ？ | 正（S=0） | 正（S=0） | ？ | 正 - 正 |
| 正 + 負 = ？ | 正（S=0） | 負（S=1） | ？ | 正 - 正 |
| 負 + 正 = ？ | 負（S=1） | 正（S=0） | ？ | 負 - 負 |
| 負 - 負 = ？ | 負（S=1） | 負（S=1） | ？ | 負 - 負 |

となって、結果の数値に符号部は依存します。

（正 - 正）相当の計算のイメージは「（桁合わせをした）符号あり整数の減算」です。

（負 - 負）相当の計算は 「-（正 - 正）」として同様です。

結果は 0 未満が負の扱いなので、「0」は「+0」になります。

## 比較

FPU の比較命令（アセンブリ言語の話になります）にて「+0」と「-0」が同じ「0」なのに一致しないと判断されてはプログラムを組むのが大変になってしまいます。逆に、「+0」と「-0」が一致しないと判断する比較命令はなくても困りません。

すると、比較の基本は減算結果（「<：負」、「=：0」、「>：正」）なので、FPU の比較命令は「同符号の減算」相当の処理だけでよいことになります。

これは、FPU によっては "+0"と"-0"が一致しないと判断する比較機能がないかもしれず、その場合は "+0"と"-0"は区別しないことを意味します。

# 実験

以上を踏まえて、実験してみます。実行環境は macOS 12.1 (Intel版) です。

```python:Python
Python 3.8.9 (default, Oct 26 2021, 07:25:54) 
[Clang 13.0.0 (clang-1300.0.29.30)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> a = 1
>>> while a > 0: a /= 2
... 
>>> a
0.0
>>> b = -1
>>> while b < 0: b /= 2
... 
>>> b
-0.0
>>> a == b
True
>>> [a, b]
[0.0, -0.0]
>>> a * b
-0.0
>>> a + b
0.0
>>> b - a
-0.0
>>> b + b
-0.0
```

```JavaScript:Node.js
Welcome to Node.js v16.13.1.
Type ".help" for more information.
> a = 1; while (a > 0) a /= 2; a
0
> b = -1; while (b < 0) b /= 2; b
-0
> a === b
true
> [a, b]
[ 0, -0 ]
> a * b
-0
> a + b
0
> b - a
-0
> b + b
-0
```

どの言語も FPU の機能を使っているハズなので予想通りというわけです。

---

こういう場合はあるのかな？

```JavaScript:Node.js
Y = X + 0; /* X が -0 だった場合に +0 に変換（X = Y にしちゃダメ） */
/* Y の符号で分岐... */
```
Symbol Harvest Summaryの実装方針

似たようなことを、もしかしたらやる方がいらっしゃるかもしれないのでなにかの参考になればと思い[Symbol Harvest Summary](https://twitter.com/NEM_Harvest)の実装において何をしているか、何を考えているかを記載します。
使い方の説明書や、コードの解説ではありません。ただし、後日ソースコードの一部を記事に載せる予定です。

## 何の機能を提供しているか？
- 前日のすべてのSymbolのブロック情報を取得し、
- その日のトランザクション数の合計とハーベストフィーの平均値を算出し、
- 算出した値を日々ツイートしています。

サンプルのツイートは以下の通り。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309172/6b766dcf-5fe8-f6f5-c7e9-1e4d5293a36f.png)

## Symbolのブロック情報の取得
自分でノードを立てて、1ブロックずつAPIをforループで叩きまくる力技です。他の人のノードでこれをやるのは、迷惑かもしれないのでやめたほうがいいと思います。
理論上、30秒に1ブロックであれば1日のブロック数は2880で、上記例としてあげた2021年12月18日は2878ブロックとほぼ理論通りの値です。この程度であれば、一瞬とは言いませんがせいぜい数十秒～分のオーダーで終わるので今回は問題になりません。たまにサーバーが429エラーを吐きますが、待って再接続でOKです。

次項に記載のデータベースの最も高いブロックが前日取得した最後のデータです。その次のブロックから最新のブロックまでAPIを叩く処理を1日1回forループで回します。
取得したデータはjson形式なので、必要なデータを取り出してpandasを用いて整理していきます。(黄色背景を取得すればOK)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309172/ed7b1b49-a38d-2233-5ade-c245c4fd6048.png)
最後のブロックまで完了したら次のステップのためにCSVで一旦保存します。

## 取得したデータの保存
取得したデータは用が済んだら捨ててしまってもよいのですが、後々の分析に使うことも考えてデータベースに保存します。データベースは、リレーショナル型なら何でも良いですが、無料かつメジャーで使い慣れたPostgreSQLを用いています。本当は、データベースの定義などは公開しないほうが良いのでしょうが、この程度は問題ないでしょう。データベースへの保存は、速度を考え一度CSVに吐き出してからコピーコマンドで行います。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/309172/1663f3e7-ed46-7908-3f1d-43f2af0051af.png)

### MongoDBからデータを直接取らない理由
少しSymbolのドキュメントを読んだ方であれば、Symbolのノードを建てたとき、データがMongoDBに保管されていることはご存知かと思います。当初、MongoDBからデータを読み込んで分析を行う手法を考えていましたが、結局うまくいかず断念しました。理由を以下に残します。

- MongoDBに接続できる設定にすると、データベースへのアクセスが外部から保護されず攻撃の対象となる。サーバー設定を適切に行えば解決するのだろうが、模索した結果見つけられなかった。
（参考：https://qiita.com/NEM_Harvest/items/54baa722ca39f3d96faf
- NoSQLであるため集計などの処理に向かないが、このbotでは集計処理を行うことが多い。

## 集計処理
合計や平均を算出する処理はSQLで簡単に記載できます。WHERE区の範囲を日付で指定すれば、その日の合計や平均の出来上がりです。

## ツイート処理
昔NEM Harvest Summary時代に作成したものをそのまま使いまわしています。レガシー資産なので詳細は触れません。新たにツイッターbotを作成する方は、色々と変わっている可能性が高いので調査から始めると良いと思います。

## こだわり
ツイッターで情報を提供しているところです。
確かにダッシュボードを作れば見栄えが良いしより高度な機能を提供できす。
しかしそれでは多分マニアしか見ないと思うので、より多くの人に日々気軽に情報に触れてほしいなと思っています。
Pulumi (TypeScript) で操作中の AWS アカウント ID を取得する


## はじめに

AWS のリソースへのアクセス権限 （bucket policy 等） や、ログ出力先の設定などを行うために、アカウント ID を取得する機会があり調査したメモです。

### AWS Classic (`@pulumi/aws`) の場合

AWS Classic (`@pulumi/aws`) は terraform の AWS Provider を元に作成されています

terraform の場合は `aws_caller_identity` を利用しますが Pulumi でも同様の data source を利用します
terraform で AWS アカウント ID を取得する場合は以下記事を参考ください。

https://qiita.com/gongo/items/a2b83d7402b97ef43574

AWS Classic (`@pulumi/aws`) の場合は `getCallerIdentity` を利用し取得
`getCallerIdentity` terraform 同様、 アカウント ID 以外にも ユーザー ID やその ARN を取得することが出来ます

```ts:index.ts
import * as pulumi from "@pulumi/pulumi"
import * as aws from "@pulumi/aws"

const callerIdentity = aws.getCallerIdentity({})
export const accountId = callerIdentity.then((callerIdentity) => callerIdentity.accountId)
```

`getCallerIdentity` に渡すことが出来るオプションなどは以下ドキュメントを参照してください

https://www.pulumi.com/registry/packages/aws/api-docs/getcalleridentity/

#### `pulumi preview` を実行する

以下 AWS Classic package で AWS アカウント ID を取得した結果です。

```zsh
% pulumi preview
Previewing update (xxxxxx)

View Live: https://app.pulumi.com/mziyut/xxxxxx/xxxxxx/xxxxxx/xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx

     Type                 Name                       Plan
     xxxxxx               xxxxxx

Outputs:
  + accountId    : "xxxxxxxxxxxx"

Resources:
    xxxxxx unchanged
```

### AWS Native の場合

AWS Native Packege を利用している場合は
`getAccountId` を利用することで アカウント ID を取得することができます

```ts:index.ts
import * as pulumi from "@pulumi/pulumi"
import * as awsNative from "@pulumi/aws-native"

export const accountId = awsNative.getAccountId()
```

https://www.pulumi.com/registry/packages/aws-native/api-docs/getaccountid/

#### `pulumi preview` を実行する

以下 AWS Native package で AWS アカウント ID を取得した結果です。

```zsh
% pulumi preview
Previewing update (xxxxxx)

View Live: https://app.pulumi.com/mziyut/xxxxxx/xxxxxx/xxxxxx/xxxxxx-xxxxxx-xxxxxx-xxxxxx-xxxxxx

     Type                 Name                       Plan
     xxxxxx               xxxxxx

Outputs:
  + accountId    : {
      + accountId: "xxxxxxxxxxxx"
    }

Resources:
    xxxxxx unchanged
```

## 最後に

AWS Classic / AWS Native それぞれで AWS アカウント ID を取得する方法を記載しました。
AWS のリソースへのアクセス権限 （bucket policy 等） や SNS Topic の設定などもハードコーディングせず設定できるようになるはずです。
Nullish Coalescing


#1. はじめに

　スターアプリケーションズ株式会社の吉田です。
　みなさん、strict:true やっていますか。はい、コンパイルエラーの修復ご苦労様です。TypeScriptの型チェック厳密になって大変ですね。今回、変数のnull/undefinedチェックで、AngularのNullish Coalescingを使うと、便利になるので記事にしました。
#2. 復習

　Nullish Coalescingですが、JavaScript、TypeScriptには、以前より実装済みの機能です。AngularではV12から　AngularのTemplateで使用することができるようになりました。Mark Thompson氏のブログ、[(Angular v12 is now available)](https://blog.angular.io/angular-v12-is-now-available-32ed51fbfd49)から例を見ていきましょう。

`{{age !== null && age !== undefined ? age : calculateAge() }}`

上記は以下のように置き換えられます。

`{{ age ?? calculateAge() }}`

??の左側：nullでもundefinedでもない時の表示
??の右側：null又はundefinedの時表示される値

#3. デモプログラム
　　デモと言っても、大したものではありません。主な作成部分は次の２ヶ所です。

```app.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'NullishCoalescing';

  prefecture ?: string  ;
  city : string | null = null;
  street ?: string ;
}
```

```app.component.html
<h2> Nullish Coalescing DEMO</h2>
<div>
  都道府県:<input  type="text" [(ngModel)]="prefecture">
</div>
<div>
  市区町村:<input  type="text" [(ngModel)]="city">
</div>
<div>
  町名番地:<input  type="text" [(ngModel)]="street">
</div>
<br>
<h3>住所</h3>
<span>
    {{ prefecture ?? "**都道府県名入力なし**　"}}
</span>
<span>
    {{ city ?? "**市区町村名入力なし**　"}}
</span>
<span>
    {{ street ?? "**町名番地名入力なし**　"}}
</span>
```

[プログラム全体を見る](https://stackblitz.com/edit/angular-ivy-zaj9ad?file=src/app/app.component.html)

#参考

[Angularでstrict: trueにした。（strictNullChecks, strictPropertyInitialization編）](https://qiita.com/kyokoshimizu/items/ee6c6e6b905b8aa101fa)
面倒な双一次変換の計算はPythonにやってもらおう

![dynamics-890x500.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/484973/fd71e4c1-342c-58fc-9487-9f4953e8e9c8.png)
上の写真の系について，運動方程式は，

$$ M \ddot{x} + B \dot{x} + K x = f $$

ですね．ではこの物体を人間が握るものとして，アドミタンス提示型のインピーダンス制御をかけるましょう．つまり，アクチュエータを用いて任意の$M,B,K$を表現したいのです．入力を$F(s)$，出力を$\dot{X}(s)$とすると，伝達関数$G$は

$$ G = \frac{s}{Ms^2 + Bs + K} $$

という2型になります．(本当は剛性いらないので1型にできるが...)
そろそろ本題に入りますが，目標速度$\dot{x}$はどうやって計算しますか? 僕は双一次変換を使います．今回の例の正解は，

$$ 
\dot{x}[k] = \frac{1}{2BT_s+KT_s^2+4M} \{ 2T_s(f[k-2]+f[k]) + (8M-2KT_s^2)\dot{x}[k-1] \\
+ (2BT_s-KT_s^2-4M)\dot{x}[k-2] \} 
$$

ですが，こんな面倒な計算を手でしたくはありません．そこでPythonにやってもらおうということです．ipynbファイルを以下のリポジトリに置きました．2型までですが，伝達関数を入力するだけで双一次変換を一瞬で計算してくれます．SympyはSymbolicな演算をしてくれるだけでなく，簡単にTex表記もしてくれるので非常に便利ですね．

https://github.com/RE-yura/calculate_bilinear_transformation
Flutterで検索バーを作る


最終的なイメージ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/527110/e8c5754d-7a51-2089-b325-896da1abe1fd.png)

書いたコード

```
Container(
  width: deviceWidth,
  height: 50,
  decoration: BoxDecoration(
    border: Border.all(color: Colors.grey),
    borderRadius: BorderRadius.circular(5),
    color: Colors.white,
  ),
  child: Column(
    children: [
      Row(
        children: [
          Expanded(
            child: TextField(
              decoration: InputDecoration(
                  hintText: "検索",
                  border: InputBorder.none,
                  focusedBorder: InputBorder.none,
                  prefixIcon: const Padding(
                    padding: EdgeInsets.fromLTRB(0, 4, 0, 0),
                    child: Icon(
                      Icons.search,
                      color: Colors.grey,
                      size: 20,
                    ),
                  )),
              textAlign: TextAlign.left,
              onChanged: (value) => filterController.update((state) => value),
            ),
          ),
          PopupMenuButton(
              icon: const Icon(
                IconData(0xe404, fontFamily: 'MaterialIcons'),
                color: Colors.grey,
                size: 20.0,
              ),
              itemBuilder: (context) => [
                    PopupMenuItem(
                      child: Text("hoge"),
                      value: 1,
                    ),
                    const PopupMenuItem(
                      child: Text("fuga"),
                      value: 2,
                    )
                  ]),
        ],
      ),
    ],
  ),
),
```
nixとgit submodule

# 目的

複数のレポジトリにあるプロジェクトを使って開発するときにgit submoduleを使うかと思います。
そのようなユースケースでnixとgit submoduleを組み合わせて使いたくなるかもしれません。
残念ながら、今の開発版のnix（2.6.0pre20211217_6e6e998）ではそのような使い方が難しいです。
なぜ難しいのか、今なら何ができるのか紹介します。

# パッケージ作成：nix flakes

まず、nix & git submoduleでの使い方を紹介する前にnixでのパッケージの作り方としての[nix flakes](https://nixos.wiki/wiki/Flakes)について簡単に説明します。

nixのパッケージはderivationですね。derivationはデフォルトのパッケージの集合であるnixpkgsから使用するパッケージや便利な関数、ビルドするソースとビルドするbashのスクリプトから構成されています。
nixpkgsはnixのスクリプトの中で`<nixpkgs>`となっています。これはパッケージをビルドする時の環境変数`NIX_PATH`が展開されます。
この環境変数はユーザーによって異なるため、そのまま使うと再現性のないパッケージが出来上がります。
それを防ぐために[nix flakes](https://nixos.wiki/wiki/Flakes)があります。

nix flakesでは次のような`flake.nix`ファイルとそのロックファイル`flake.lock`を使います。
見てわかる通りnixpkgsのパスが埋め込まれています。ロックファイルには具体的なgitのハッシュ値が書かれます。

今回の話はこのnix flakesとgit submoduleを一緒に使うのが難しいという話です。

```nix
# Source: https://www.tweag.io/blog/2020-05-25-flakes/
{
  description = "A flake for building Hello World";

  inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-20.03;

  outputs = { self, nixpkgs }: {

    defaultPackage.x86_64-linux =
      # Notice the reference to nixpkgs here.
      with import nixpkgs { system = "x86_64-linux"; };
      stdenv.mkDerivation {
        name = "hello";
        src = self;
        buildPhase = "gcc -o hello ./hello.c";
        installPhase = "mkdir -p $out/bin; install -t $out/bin hello";
      };
  };
}
```

# nixとgit submoduleの現状

nix flakesでは`builtins.fetchTree`関数でソースを取り込むのですが、デフォルトでgit submoduleを使わない設定になっていました。
そこで[#4922](https://github.com/NixOS/nix/pull/4922)のPRでデフォルトonにするように変更が加えられました。
しかし、パフォーマンスの問題があり、再びデフォルトoffに戻されています。（[discourseのソース](https://discourse.nixos.org/t/tweag-nix-dev-update-18/15300)）

そのため、[ユーザー定義によってgit submoduleを有効化する方法](https://github.com/NixOS/nix/issues/5312)や[デフォルトonにする方法](https://github.com/NixOS/nix/pull/5399)が模索されています。

そのうち実行可能ものが`submodules=1`というパラメータをあたえて有効化する方法です。[#5434](https://github.com/NixOS/nix/pull/5434)
これを使った方法を次に紹介します。

# nixでgit submodulesを使う方法

nixでgit submodulesを使うために`flake.nix`を編集します。
nix flakesのinputsにsubmoduleへのパスを設定します。（この機能は[#5279](https://github.com/NixOS/nix/pull/5279)で実装されています。）
例えばmy-subdirディレクトリのsubmoduleをinputsにいれるには下記のようにします。

```nix
# Source: https://www.tweag.io/blog/2020-05-25-flakes/
{
  description = "A flake for building Hello World";

  inputs.nixpkgs.url = github:NixOS/nixpkgs/nixos-20.03;
  inputs.my-submodule.url = path:./my-subdir; #ここに追加
  outputs = { self, nixpkgs, my-submodule }: {
#あと省略
```

そのあとnixでgit submodulesは有効にするために`.`を`.?submodules=1`に書き換えて各種コマンドを実行します。

パッケージのリストを出す場合は次のようになります。

```bash
# git submoduleがない通常の場合
nix flake show .
# git submoduleがある場合
nix flake show .?submodules=1
```

また、パッケージの作成する場合は下記のようになります。
この例ではhelloパッケージ（derivation）を作成します。

```bash
# git submoduleがない通常の場合
nix build .#hello
# git submoduleがある場合
nix build .?submodules=1#hello
```

# まとめ

nix flakesの簡単な紹介のあと、nixとgit submodulesを一緒に使うために、nix flakesでの設定方法と実行方法を紹介しました。
グローバルIPを確認できるサービスたち

## はじめに
何気なく、グローバルIPを表示するコマンドが便利だったので、調べると色々あることがわかった。

## コマンド
軽く調べるだけでも以下のサービスが出てきました。
自分にしっくりくるもの、覚えやすい名前などで選べば良さそうです。

```bash
curl ifconfig.io
```
```bash
curl ifconfig.me
```
```bash
curl httpbin.org/ip
```
```bash
curl ipaddr.show
```
```bash
curl checkip.amazonaws.com
```
```bash
curl https://domains.google.com/checkip
```
```bash
curl ip-api.com
```
```bash
curl inet-ip.info
```
```bash
curl globalip.me
```
```bash
curl api.ipify.org
```
```bash
curl icanhazip.com
```
```bash
curl ipecho.net/plain
```
```bash
curl ident.me
```

### そこにアクセスしても大丈夫なのか？安全なのか？
見慣れないドメイン名だと、怖いと思うこともあるかと思いますが、
`checkip.amazonaws.com`はaws、
`https://domains.google.com/checkip`はgoogle、
のサービスですので、安心して使って良いかと思います。

### その他
各サービスには、出力形式や機能が色々備わっていたりしますので、
興味があれば、調べてみると面白いかと思います！

## おわりに
まだまだ色々あると思いますので、
ここにないおすすめのサービスがあれば、教えていただけると幸いです。

ありがとうございました！
Pulumi (TypeScript) で AWS Native Package を利用する初期設定


## はじめに

Public preview 中の AWS Native Package の初期設定方法について本記事にまとめました。
AWS Native Package については ▼ 記事を参照してみてください

https://qiita.com/mziyut/items/a9f7f4db167d674a9f3c

Pulumi の project は作成済みであることを前提として記載します。
まだ、 project を作成していない方は以下記事や公式ドキュメントを参考に初期設定まで完了させてください。

https://qiita.com/mziyut/items/069c21328bbeb25d5aab

## 実行環境

```console
% sw_vers
ProductName:	macOS
ProductVersion:	12.0.1
BuildVersion:	21A559
% node -v
v16.10.0
% yarn -v
1.22.17
```

## AWS Native Package を追加

`yarn add @pulumi/aws-native` を実行し `aws-native` package を追加します

```zsh
yarn add @pulumi/aws-native
```

## region を設定する

AWS Native Package も AWS Classic と同様に region の設定を行う必要があります。
今回は、東京リージョン `ap-northeast-1` を設定します

```zsh
pulumi config set aws-native:region ap-northeast-1
```

## credentials を設定する

AWS のリソースを操作するため 対象のアカウントにアクセスできる権限を付与します。
`access_key` や `assumeRole` などサポートしていますが今回は、シンプルに `access_key` を発行して検証します。

IAM の作成や `access_key` の発行がわからない方は以下ドキュメントを参考に作成してください

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html

発行した IAM の `access_key` や `secret_key` を `pulumi config set` コマンドを用いて設定します。

設定する際は `--secret` オプションを必ず設定してください。
オプションを指定しないと、`Pulumi.stack_name.yml` に平文で記載されてしまいます。

```zsh
pulumi config set aws-native:accessKey xxxxxxxxxxx --secret
pulumi config set aws-native:secretKey xxxxxxxxxxx --secret
```

`pulumi config set` を利用しなくても 環境変数からも token を渡すことができます。

```zsh
export AWS_ACCESS_KEY_ID=YOUR_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY=YOUR_SECRET_ACCESS_KEY
```

ここまで設定すれば AWS Native Package で AWS リソースの管理を行うことができます。

## AWS Native Package で 情報を参照してみる

今回は、 Pulumi で 管理対象としたリージョン情報が取得できるか確認してみます。

```ts:index.ts
import * as pulumi from "@pulumi/pulumi"
import * as awsNative from "@pulumi/aws-native"

export const region = awsNative.getRegion()
```

`yarn preview` を実行します
region 情報が `Outputs` に表示されました。

```zsh
% yarn preview
Previewing update (xxxxxxx)

View Live: https://app.pulumi.com/mziyut/xxxxxxx/xxxxxxx/xxxxxxx/xxxxxxx-xxxxxxx-xxxxxxx-xxxxxxx-xxxxxxx

     Type                 Name                       Plan
     xxxxxxx              xxxxxxx

Outputs:
  + region       : {
      + region: "ap-northeast-1"
    }

Resources:
    x unchanged
```

## 最後に

AWS Native Package はまだ public preview ということもあり対応していないリソースも多い状態です。
今後は、AWS Native Package の利用がスタンダードになっていくことは明確なため、
新規で作成するリソースは AWS Native Package を使った構築することを検討してみてください。

## Reference

https://github.com/pulumi/pulumi-aws-native/tree/master

https://www.pulumi.com/registry/packages/aws-native/installation-configuration/
プライベートなEC2にローカルPCからアクセスする

# はじめに
Privateサブネット内で起動されるEC2インスタンスにクライアントPCからログインする機会があったため、備忘録として残しておこうと思います。

# 環境情報
- ローカルPC：Windows 10 Pro
- EC2：Amazon Linux2


# 構成図
Publicサブネット内のEC2インスタンスを経由してPrivateサブネット内のEC2インスタンスにアクセスします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2410564/cce04bfb-d158-e618-c246-8fb546dffa6f.png)


# 手順
・```~/.ssh/config```にPublicインスタンスとPrivateインスタンスの接続情報を記述します。

```~/.ssh/config
Host instance1
    # 踏み台サーバのパブリックIPを設定
    HostName xxx.xxx.xxx.xxx
    User ec2-user
    # 踏み台サーバの秘密鍵のPath
    IdentityFile =~/path/instance1.pem
    Port 22

Host instance2
    # プライベートサーバのプライベートIPを設定
    HostName xxx.xxx.xxx.xxx
    User ec2-user
    # 踏み台サーバを経由
    ProxyCommand ssh instance1 -W %h:%p
    IdentityFile =~/.ssh/path/instance2.pem
    Port 22
```

・コマンドプロンプトから以下のコマンドを実行し、プライベートサーバへアクセスする。

```
ssh instance1
```


# 最後に
今回は.ssh/configを利用してローカルPCからプライベートインスタンスへアクセスする方法を記載しました。
MySQL Workbenchでprivateサブネット内のDBインスタンスに接続する際も.ssh/configが利用できそうなので、別の機会でまとめようかと思います。


# 参考サイト
https://s10i.me/whitenote/post/42
https://dev.classmethod.jp/articles/bastion-multi-stage-ssh-only-local-pem/
【SwiftUI】SwiftUIらしくCheckBoxを使う（ToggleStyle）


SwiftUIにはCheckBoxそのものは用意されていません。
CheckBoxを作ること自体は簡単なので色々な方法で実装している人がいます。

今回はその中でもSwiftUIらしい実装方法を紹介します。

#コード
```swift
struct ToggleCheckBoxView: View {
    @State var toggle = false
    
    var body: some View {
        Toggle("Toggle", isOn: $toggle)
            .toggleStyle(CheckBoxToggleStyle())
    }
}

struct CheckBoxToggleStyle:ToggleStyle{
    func makeBody(configuration: Configuration) -> some View {
        Button{
            configuration.isOn.toggle()
        } label: {
            HStack{
                configuration.label
                Spacer()
                Image(systemName: configuration.isOn
                      ? "checkmark.circle.fill"
                      : "circle")
            }
        }
    }
}
```

#解説
ToggleはToggleStyleによって見た目の変更が可能ですが、
Protocolとして実装しModifierに渡す事で任意に定義出来ます。

makeBodyはreturnがsome Viewなので通常のViewのbodyの様に書く事が出来ます。
ここに切り替えアクションの為のボタンを置き、真偽で画像が切り替わる様にlabelを設定します。

configurationからはisOnでbool値が扱えるのでButtonで切り替えます。
configuration.labelにはToggleに設定したlabelが取得出来るので、チェックマークと並べる様にします。

これでtoggleStyle Modifierとして使用出来るので非常にSwiftUIらしい使い方が出来ます。

#余談
Modifierとして使用出来ることは利点ですが、
中身の記述はそのままViewとして使いチェックボックスに出来るから、
検索してもこの方法は上位に出てきません。

しかしToggleStyleのmakeBodyのドキュメントにはチェックボックスが例として挙げらており、
この方法を推奨しているのではないかと思います。是非覚えて行って下さい。

#ブログ紹介
ブログ記事には画像付きの解説や.toggleStyle(.button)の様に使う方法、
Toggleを使わないパターンの紹介もあります。
興味があれば見てみて下さい。

https://thwork.net/2021/12/21/swiftui_checkbox_togglestyle/
SQL入門

#SQLとは
SQLとはデータベース言語と言ってプログラミング言語ではありません。
データベースを操作するための言語です。
言い換えるとSQLを使いデータベースに命令を出す言語です。
このSQLからの命令を受け取るのはDBMS(データベース管理システム)と
呼ばれるプログラムです。
字の通りDBを管理するものです。 ※ DB（データベースの略称) これからはDBと略します。
これがSQLによりファイルを消したり書き換えたりされます。

#dokoOL
dokoOLを使うと SQLを簡単に操作できます。
https://dokoQL.com

#データベース検索 SELECT, FROM
データベースの中からデータの取得方法を簡単に説明します。

```sql
SELECT --列名(データベースの縦の部分）
FROM   --検索したいテーブル名
```

上のように***SELECT***と***FROM***を使いデータを取得します。

例えば
野球部員管理システムならFROMを使い3年生テーブルからデータを取り出し、
その中の身長とポジションのデータを取り出すならSELECTを使います。
こうすることにより３年生の部員の身長とポジションのデータを取り出すことができます。
下みたいな感じです。

```sql
SELECT ポジション,身長
FROM   ３年生
```

***３年生の全部のデータを取得する***にはどうすればいいでしょうか？

```sql
SELECT *
FROM 3年生
```

***dokoOL***を使えば家計簿のデータを取り出してSQLの挙動を確認できます。



⚫︎コメントアウト方法
https://www.dbonline.jp/sqlite/ini/index3.html

⚫︎補足
https://proengineer.internous.co.jp/content/columnfeature/6411
https://qiita.com/go_glzgo/items/046e708c05921dad7ffb

#条件検索　 WHERE
***WHERE***を使うと```条件の検索```ができます。
先程の野球部のデータベースを見てみましょう！

```sql
SELECT ポジション,身長
FROM   ３年生
WHERE 身長　　> 175  --175以上の身長の人を検索する
```
WHEREから始まる行によって身長が175センチ以上の部員のデータが取得できます。
不等号『>』や『=』などを使って175センチ以下や175センチの部員のデータも取得できます。

#データの追加　INSERT INTO , VALUES
次はテーブルにデータを追加する方法について説明していきます。
***3年生テーブルにピッチャーで身長180センチで体重が75キロの
田中君をデータとして追加します。***

```sql
INSERT INTO 3年生
VALUES ('2018-02-25','田中君','ピッチャー',180,75)
```
これを実行した後に、SELECT * FROM　3年生を実行すると田中君のデータが追加されます。
```INSERT INTO```で```追加するテーブルを指定し```、```VALUES```で```追加するデータを記述```しています。


⚫︎補足
INSERTは***挿入する***という意味です。
***単語の意味を考えながらやる***と理解が早いと思います。

#データの更新　UPDATE　
次はテーブルにデータを追加する方法について説明していきます。
***3年生テーブルの田中君の2018-02-25の体重が75キロではなく
70キロだったので70キロに更新する。***

```sql
UPDATE 3年生
SET 体重 = 70
WHERE 日付 = '2018-02-25'
```
SELECT * FROM 3年生で検索すると田中君の体重は70キロに変わります。
３年生テーブルをUPDATEしSETで体重を70キロに変更します。

#データの削除　DELETE
最後に３年生の2018-02-25の田中君のデータを削除します。

```sql
DELETE FROM 3年生
WHERE 日付 = '2018-02-25'
```
2018-02-25のデータは田中君のみなので削除されます。


#最後に　テーブル名と列名について
***テーブル名と列名には会社やプロジェクトによってルールがあります***。
この記事ではわかりいやすく日本語にしていますが、
英語やローマ字で使うことも多いみたいです。
そこだけ注意してください。








⚫︎参考資料
https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BSQL%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%83%89%E3%83%AA%E3%83%AB222%E5%95%8F%E4%BB%98%E3%81%8D-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1%E6%B8%85%E5%96%AC/dp/4295005096
Rubyの関数と引数色々

忘れがちな使い方と存在確認方法をセットでお届け

## 名前付き引数
ユースケース：
引数を必須にしたい
引数の数が多い

```ruby
# 引数がなくても許される
def greet(name, message)
  p "Hi #{name}, #{message}"
end

greet('tom') # "Hi tom, undefined"

# 引数がないと許されない
def greet(name:, message:)
  p "Hi #{name}, #{message}"
end

# 名前も渡してね
greet('tom') # expected kwargs (ArgumentError)
# 必須だよ
greet(name:'tom') # missing keyword: message (ArgumentError)
# 正解
greet(name:'tom', message: 'how are you') # "Hi tom, how are you"
```
## 可変長引数
ユースケース：
汎用的な関数を作る
引数に渡すケース、わたさないケースがある

### 配列でとる

```ruby
# 複数の値を配列でとれる
def greet(*args)
  p "args: #{args}"
end
greet('hi', 'hello', 'yo')
# "args: hi,hello,yo"

# 指定する
def greet(*args)
  p "arg[0]: : #{args[0]}"
end
greet('hi', 'hello', 'yo')
# "arg[0]: : hi"

# 存在確認する
def greet(*args)
  p args.include?('おはよう')
end
greet('hi', 'hello', 'yo')
# false
```

### ハッシュでとる

```ruby
# 複数の値をHashでとる
def greet(**args)
  p "args: #{args}"
end
greet(arg1:'hi', arg2:'hello', arg3:'yo')
# "args: {"arg1"=>"hi", "arg2"=>"hello", "arg3"=>"yo"}"

# 指定する
def greet(**args)
  p "arg[:arg1]: : #{args[:arg1]}"
end

# 存在確認する
def greet(**args)
  args[:args4].nil?
end
greet(arg1:'hi', arg2:'hello', arg3:'yo')
# true
```

### 可変長引数を併用する

```ruby
def greet(*array, **hash)
  puts "array: #{array}"
  puts "hash : #{hash}"
end

greet('tom', 'bob', message: 'hi', message2: 'yo')
# array: tom,bob
# hash : {"message"=>"hi", "message2"=>"yo"}

# さすがにこれは怒られる
greet('tom', message: 'hi', 'bob', message2: 'yo') # SyntaxError
```
なでしこ3サーバー簡単保存APIを使ってみよう

先日、なでしこから使える簡単保存API(nako3kvs)のサービスを作ったので紹介します。このAPIを使うと、クライアントから手軽にデータを保存できます。

> [なでしこ3API Key-Valueストア](https://nadesiko.net/index.php?nako3kvs)
> (URL) [https://nadesiko.net/index.php?nako3kvs](https://nadesiko.net/index.php?nako3kvs)

このサービスは、ブラウザから使えるお手軽プログラミング言語「なでしこ3」から、データを簡単にサーバーに保存するAPIを提供するものです。

![スクリーンショット 2021-12-21 22.25.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33180/d6cc791c-3b9c-4322-19e4-446f4ce8baa3.png)

そもそも、なでしこ3は、ブラウザ上で動くために、サーバーにデータを保存したい場合には、なにかしらの仕掛けを利用する必要があります。とは言え、サーバーにデータを保存するのは、なかなかハードルが高いのが現状です。

そこで、登場するのが、[なでしこ3API　簡単保存API(nako3kvs)](https://nadesiko.net/index.php?nako3kvs)です。このサービスを使うと、任意のキーとパスワードを利用して、サーバーにデータを保存できます。保存できるのは文字列のみですが、JSONデータにエンコードすれば、複雑なデータも気軽に保存できます。

# 何に使えるの？

このサービスを何に使えるのかというと、ゲームのハイスコアを記録するのに使ったり、簡単なメッセージボード、ちょっとしたユーザーデータの保存などに使えます。

# どうやって使うの？ - はじめの一歩

最初に、[こちらの管理画面ページ](https://nadesiko.net/nako3kvs/admin.php)から、新規キーを作成します。
以下の画面のように、「キー」「初期値」「パスワード」を入力しましょう。
キーの作成には、任意のパスワードが必要です。この時、忘れないようにパスワードをメモしておきましょう。

![スクリーンショット 2021-12-20 23.57.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/33180/d9abe792-35ad-6d2c-f430-05294cc74f68.png)

# プログラムを作ろう

次に、なでしこのプログラムを作りましょう。例えば、以下は上記で作成した「test」というキーの値を取得するプログラムです。

```read.nako3
# ライブラリの取り込み
!「https://n3s.nadesi.com/plain/nako3kvs.nako3」を取り込む。

# キーに対応する値を取得する
キー＝「test」
パスワード＝「abcd」
キーをパスワードでKVS取得時には
    対象を表示。＃結果
ここまで。
```

「キーをパスワードでKVS取得時には...ここまで」と記述します。すると、変数「対象」に保存した文字列が得られます。

次に、キーの値を変更するプログラムを見てみましょう。「KVS設定時」命令を使います。

```write.nako3
# ライブラリの取り込み
!「https://n3s.nadesi.com/plain/nako3kvs.nako3」を取り込む。

# キーに対応する値を変更する
キー＝「test」
パスワード＝「abcd」
パスワードでキーを「あいうえお」にKVS設定時には
　　＃変更した時
　　キーをパスワードでKVS取得時には
    　　対象を表示。
　　ここまで。
ここまで。
```

# なでしこ以外でも使えるよ？

なお、なでしこKey-Valueストアのサービスは、簡単なREST APIとなっています。
以下のように、「AJAX受信時」を使って直接Web APIを呼び出せます。

```api-read.nako3
KVS_API=「https://nadesiko.net/nako3kvs/api.php」
# キーとパスワードを指定してAPIにアクセス
KEY＝「test」
PW＝「abcd」
URL=「{KVS_API}?mode=get&key={KEY}&password={PW}」
URLからAJAX受信した時には
　　J=対象をJSONデコード
　　対象＝J@「value」
　　対象を表示。
ここまで。
```

同じように値の変更も可能です。

```api-read.nako3
KVS_API=「https://nadesiko.net/nako3kvs/api.php」
# キーとパスワードを指定してAPIにアクセス
KEY＝「test」
PW＝「abcd」
VALUE=「拾うのに時があり、諦めるのに時がある。」
URL=「{KVS_API}?mode=set&key={KEY}&value={VALUE}&password={PW}」
URLからAJAX受信した時には
　　J=対象をJSONデコード
　　対象＝J@「result」
　　対象を表示。
ここまで。
```

このように、簡単に使えるので使ってみてください。

# リンク

- [なでしこ3簡単保存API](https://nadesiko.net/index.php?nako3kvs)
Cypressを用いたE2Eテスト開発

この記事はエイチーム引越し侍 / エイチームコネクトの社員による、
[Ateam Hikkoshi samurai Inc.× Ateam Connect Inc. Advent Calendar 2021](https://qiita.com/advent-calendar/2021/hikkoshizamurai-connect) 21日目の記事です。
本日は引越し侍Webエンジニアの@nao_70が担当します！

# はじめに
長年システムを運用する中で、仕様が複雑になりすぎて、
人力だけのテストだけじゃカバーしきれない・・！
みたいな経験がある方は意外と多いのではないでしょうか。

弊社でも同じ悩みを抱えたシステムがあり、
近々Cypressを用いたE2Eテストを導入する予定です。
今回は、初めて触れる方向けに、簡単に環境構築からテスト実行までの手順を紹介していこうと思います！

# Cypressとは
Cypressは、ブラウザでのテストが自動化できるテストフレームワークです
同様のフレームワークで有名なものとして[Selenium](https://www.selenium.dev/ja/documentation/)があります

# 導入手順
## 1. node.jsを準備
Cypressはnpmを使ってインストールするため、最初にnode.jsをインストールしておく必要があります。
今回、node.jsの導入については割愛させていただきます。

## 2. インストール
テストを実装したいディレクトリ配下で、以下コマンドを実行します。

```
npm install cypress
```
これだけでインストールは完了です。

## 3. 起動
インストールが完了したら、以下コマンドを実行してみてください。
CypressのIDEが起動してきます。

```
npx cypress open
```

IDEを見ると、specファイル毎にテストが並んでいます。
テストしたいファイルをクリックすると、テストが自動で実行されていきます。
いくつかサンプルテストが準備されているので、試してみてください。

## ディレクトリ構造について
ここでディレクトリ構造について簡単に説明しておこうと思います。

Cypressをインストールしたディレクトリに「cypress」というディレクトリが作られているので確認してみてください。
🗂 cypress
   └ 🗂 fixtures: テストで使用する静的データを管理
   └ 🗂 integration: テストコードを管理
   └ 🗂 plugins: プラグインを管理
   └ 🗂 support: カスタムコマンドを管理
   └ cypress.json: cypressの設定ファイル

## 4. テストコード実装
テストコードは`cypress/integration`に配置していきます。
specファイルに以下のようにコードを書いていきます。

```
describe('大項目', () => {
  context('中項目', () => {
    it('小項目', () => {
      テスト処理を記述
    })
  })
})
```

cypressではコマンドが用意されているので、
よく使うものをいくつか紹介しようと思います。
これらのコマンドを使ってテストコードを実装していきます。

```
get() - DOMの検索
type() - DOMに対して入力
clear() - 入力をクリア
visit() - URLにアクセス
wait() - 次のコマンドに進む前に、数ミリ秒待つか。
click() - 要素をクリック
blur() - フォーカスされたDOM要素をぼかす
focus() - DOM要素にフォーカス
clear() - 入力またはテキストエリアの値をクリア
check() - チェックボックスまたはラジオをチェック
uncheck() - チェックボックスのチェックをはずす
select() - select内のoptionを選択
```

試しにGoogleで任意のキーワードを検索するテストを書いてみました。
参考として見ていただければと思います。

```:integration/hikkoshizamurai_search.spec.js
describe('Hikkoshizamurai Search', function() {
　　it('Visit Google', function() {
 　　// googleを開く
  cy.visit('https://www.google.co.jp')

  // 検索欄にキーワードを入力する
  cy.get('input[name="q"]')
  　　 .type('引越し侍')

  // Google 検索ボタンを押下する
  cy.contains('Google 検索')
  　　 .click()

  // titleが引越し侍であることを確認する
  cy.title().should('eq', '引越し侍 - Google 検索')

  // スクリーンショットを残す
  cy.screenshot();
　　})
})

```

## 5. 実行
実行方法には2パターンあります。

### IDE上で実行
specファイルを保存すると、IDEに先ほど作成したテストが一覧に出てきます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249008/23af32ff-e88d-91b6-8a75-5b321bce7a6f.png)

ファイル名をクリックするとテストが実行されます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249008/48cdde9d-dc0f-ef30-6c74-a96c7b421f21.png)

### CLIで実行
以下のようにコマンドを実行することで同様にテストができます

```
$ npx cypress run -s cypress/integration/XXXXX.spec.js
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/249008/91a39048-5a56-4b4b-a8d5-70b503359976.png)

以上で、大まかな一連の流れは完了です！

# 最後に
今回、ざっくりと導入の流れを書かせていただきましたが、いかがでしたでしょうか。
実際に書いてみると、ある程度、直感的に書くことができ、思ったよりも簡単に導入することができました。
システムテストで苦労している方は、ぜひこの機会にCypressの導入を検討してみてください！

# 明日
明日は @dia がStorybookについて書いてくれるようです！
お楽しみに！！
console.logでMac版Firefoxをクラッシュさせる。


この記事は、[OPTIMIND x Acompany Advent Calendar 2021](https://qiita.com/advent-calendar/2021/optimind_acompany)の記事です。
この記事は、OPTIMIND 吉川が記載しています。

# console.logでMac版Firefoxをクラッシュさせる

年の暮、Log4jのご対応にてご多忙の中にも活気あふれる日々をお過ごしのことと存じます。
私は、Log4jの調査の中、ロギング処理であるという共通点を持つconsole.logを利用して、Mac版Firefoxをクラッシュできることを確認できたのでキャッキャしています。

console.logは、以下のように `置換文字列`[^1] が利用できます。
これは以下のように出力をすることができます。

```javascript
console.log('Hello %s!!!', 'World'); // Hello World!!!と出力されます。
```

他にも数値や、オブジェクトの出力などができます。
数値は精度による置換処理もできるため便利(?)です。[^2]

```javascript
console.log('Tax is %.2f', 1.1); // 1.10と出力されます。 
```

つまり、console.logは文字列の状態によって、padを入れるという処理を実行しています。
これを使ってMac版Firefoxをクラッシュさせることができました。
具体的には以下のコードを実行します。

```javascript
console.log('Tax is %.101f', 1);
```

101桁で何かしらの閾値に達してエラーが発生しているためだと思われます。
また、UbuntuのChromeでは現象は確認できていません。

## 蛇足

まずやらないとは思いますが、以下のような置換文字列を含む文字列をユーザの入力から動的に作成するコードを書くことは避けた方が良いです。

```javascript
console.log(`Age ${input} %d`, age);
```

今回はMac版のFirefoxだけで確認できましたが、これがサーバサイドだった場合自体は深刻になるかもしれません。

### Ruby

```ruby
sprintf("Age is %d, I'm " + name, age) # name = '%1$999999999d %1$999999999d ....'
```

### Python

```python
("Age is %(age)d, I'm " + name) % itemMap # name = "%(age)999999999999d"
```

### PHP

```php
printf("Age is %d, I'm {$name}", $age) // $name = "%1$999999999999d"
```

このようなコードを実装することは絶対にやめましょう。
上記のコメントのような文字列を入力することで、膨大な量の標準出力をさせることができそうです。


# 宣伝

株式会社オプティマインドでは、一緒に働く仲間を大募集中です。
カジュアル面談も大歓迎ですので、気軽にお声がけください。

【エンジニア領域の募集職種】
* [ソフトウェアエンジニア](https://hrmos.co/pages/optimind/jobs/0002012)
* [QAエンジニア](https://hrmos.co/pages/optimind/jobs/0002011)
* [Androidアプリエンジニア](https://hrmos.co/pages/optimind/jobs/0002008)
* [組合せ最適化アルゴリズムエンジニア](https://hrmos.co/pages/optimind/jobs/0002013)
* [経路探索アルゴリズムエンジニア](https://hrmos.co/pages/optimind/jobs/0002014)
* [バックエンドエンジニア](https://hrmos.co/pages/optimind/jobs/0002015)
* [インフラエンジニア](https://hrmos.co/pages/optimind/jobs/0002016)
* [UXUIデザイナー](https://hrmos.co/pages/optimind/jobs/0002010)

【ビジネス領域の募集職種】

* [セールスコンサルタント](https://hrmos.co/pages/optimind/jobs/0002001)
* [採用・人事](https://hrmos.co/pages/optimind/jobs/0002002)


『オプティマインドってどんな会社？』については、[こちら](https://www.optimind.tech/recruit/)から
Wantedlyでも[こちらで募集中](https://www.wantedly.com/companies/optimind/projects)

[^1]: https://developer.mozilla.org/ja/docs/Web/API/console#outputting_text_to_the_console#using_string_substitutions
[^2]: ChromeやNode.jsでは動作しません。
パワポの中心に画像を好きな大きさで貼る(python)

# 概要
パワポの中心に画像を貼るpythonスクリプトです。
画像を１スライド１枚ずつ貼り付けたパワーポイントを作成します。
画像を任意の大きさで貼ることができます。


#コード
```python
from PIL import Image
from pptx import Presentation
from pptx.util import Cm
import os

#スライドサイズ
#4:3 (default) 9144000x6858000
#16:9 12193200x6858000
SLIDE_WIDTH, SLIDE_HEIGHT = 9144000, 6858000

#出力ファイル名
OUTPUT_FILE_PATH = "test.pptx"
#画像の格納ディレクトリ
IMG_DIR = "./image_file/"

#今回は高さ15cmで貼り付け
IMG_DISPLAY_HEIGHT = Cm(15)

#受け取ったプレゼンテーションオブジェクトにスライドを追加し、追加されたスライドオブジェクトを返す。
def add_slide(prs):
  #白紙スライドの追加(ID=6は白紙スライド)
  blank_slide_layout = prs.slide_layouts[6]    
  slide = prs.slides.add_slide(blank_slide_layout)
  return slide

#画像をスライド中心に貼り付ける
def add_picture(slide, img_file):
  #画像サイズを取得してアスペクト比を得る
  im = Image.open(img_file)
  im_width, im_height = im.size
  aspect_ratio = im_width/im_height

  #表示された画像のサイズを計算
  img_display_height = IMG_DISPLAY_HEIGHT
  img_display_width = aspect_ratio*img_display_height

  #センタリングする場合の画像の左上座標を計算
  left = ( SLIDE_WIDTH - img_display_width ) / 2
  top = ( SLIDE_HEIGHT - img_display_height ) / 2

  #画像をスライドに追加
  slide.shapes.add_picture(img_file, left, top, height = IMG_DISPLAY_HEIGHT)



#スライドオブジェクトの定義
prs = Presentation()
#スライドサイズの指定
prs.slide_width = SLIDE_WIDTH
prs.slide_height = SLIDE_HEIGHT

#img画像のファイル名を取得
img_files = os.listdir(IMG_DIR)
#jpegで終了するファイル名のみ抽出。貼り付けたい画像の拡張子に応じて変える
img_files = [name for name in img_files if name.endswith(".jpeg")]
#昇順にソート（この順番でスライドに貼り付けられる）
img_files.sort()#昇順にsort

for name in img_files:
  path = IMG_DIR + name
  slide = add_slide(prs)
  add_picture(slide, path)
#pptxファイルを出力する
prs.save(OUTPUT_FILE_PATH)
```

#参考記事

https://qiita.com/shimajiroxyz/items/4316608a01eb91543faa

スライドに目いっぱいの大きさで画像を貼りたいなら、こちらの記事が良いです。

https://qiita.com/shimajiroxyz/items/f57efa222765ac9eea39

画像の大きさ変えなくてもいいよ、という人なら是非このスクリプトを。

本スクリプトはこれらの記事の組み合わせで作成させていただきました。
ありがとうございます。

#組み合わせると良いかもしれないプログラム
https://khufrudamonotes.com/pdf-to-image-python

PDFを画像にしたい方は、このスクリプトが参考になります。


https://tat-pytone.hatenablog.com/entry/2019/03/28/233413

画像のトリミング範囲を大まかに知りたい方はこちらを使うと上手くいくかと。
アナリティクスによるサイト分析

この記事は [驚異のFANZA女優検索](https://fanza-actress-bust-search.azurewebsites.net/) Advent Calendar 2021 の 21 日目の記事です。

# アナリティクスによるページ遷移
驚異のFANZA女優検索は[google アナリティクス](https://analytics.google.com/analytics/web/provision/?hl=ja&authuser=1#/provision)を入れている。アナリティクスついて語れる程使いこなしていないし、たまにしか見ていない。ただページ毎の閲覧数が見ていくつか気づきがあったので、今日はその話。

# バズった時のアナリティクス
最初にqiitaに[記事を書いた](https://qiita.com/fabsabsfabsabs/items/e8e3b717dc311ac2176d)らちょっとバズった。大体その日は1000人ぐらいサービスを見に来てくれた。その時アナリティクスを見ると面白いことが分かった。TOPページ→年齢認証ページ→女優ページで大体ユーザー数が10分の1ずつになっていた。つまり1000人のうち年齢認証まで行く人が100人ぐらい、そして女優ページまで行く人が10人ぐらいだ。さらに女優ページはTOPページの一番先頭の女優に行った人が9人だった。つまり1000人来ても、先頭以外の女優をクリックして実際に女優ページに行った人は1人だけだった。正直1000人来たら10人ぐらいはサービスを色々見てくれると思っていたが、実際は想定の1/10だった。

# 普段のアナリティクス
その後1、2週間に1回ぐらいアナリティクスを見て、2ケ月ぐらい経ったときに再度自分なりに分析してみたが、バズった時と普段でそれ程大差なかった。やっぱり100人サービスに来たら、年齢認証まで行く人が10人、そして女優まで行く人が1人ぐらいが普通だった。別の言い方をすると2クリックしてくれる人は100人に1人。これはなかなかに考えさせられる数字だった。一概には言えないが一般的なサービスでも遠からずの部分はあるんじゃないかなと思った。つまりサービスに来てくれた人数のうち、ちゃんとさわってくれる人数は100人に1人ぐらいだと思う。

# ツイートからのアナリティクス
最近はこの傾向が少し変わってきて、PVで一番多いのは年齢認証ページとなっている。これはおそらくTwitterのツイートのリンクから驚異のFANZA女優検索へ飛んで来た人だと思う。外部ページから女優ページに飛ぶ場合は、いきなり年齢認証になる。なのでTOPページよりも年齢認証の方がPVが多いのだろう。このアプローチで来た場合年齢認証で帰らない人の数が、TOPページから来て帰らない人の5倍ぐらい多い。この理由はおそらくTwitterでツイートしている内容は既にどういうページかの想像がついているからだと思う。つまり作品のページをみたくて来ている人なのだ。このために[パンくずリストと階層表現](https://qiita.com/fabsabsfabsabs/items/5d45035bfd795fdb1034)でも書いたが、各作品ページから他のページ移動をしやすくした。こういう分析が出来るならサイト分析も価値があるかなと思った（それ以上のリサーチはしていないけれど）。

#まとめ
ページ毎に9/10ずつ人が帰っていくというはなかなか良き気づきだったと思う。今後何かを考える時に使える情報かもしれない。またアナリティクスをさらに詳細に見ていけば、別のものが見えてくかもしれない。ただ、現状の結果からさらに何か出来るかというと特に何も思いつかない。
Java Chromium Embedded FrameworkでのJavascriptからJava呼び出し。

## カスタムスキーマ

custom://xxx/xxxのような呼び出しをinterceptしてJavaの処理を行う。
シーケンスは以下のような感じ。

```plantuml
@startuml
!theme aws-orange

participant "Cef\nApp" as CefApp
participant "Cef\nScheme\nRegistrar" as CefSchemeRegistrar
participant "Cef\nCallback" as CefCallback
participant "Cef\nResponse" as CefResponse

participant "Cef\nApp\nHandler" as CefAppHandler
participant "Cef\nScheme\nHandler\nFactory" as CefSchemeHandlerFactory
participant "Cef\nResource\nHandler" as CefResourceHandler

hide footbox

== 初期化 ==

-> CefAppHandler: new()
-> CefApp: addAppHandler()

== 起動処理 ==

CefApp -> CefAppHandler: onRegisterCustomScheme(registrar)
CefAppHandler -> CefSchemeRegistrar: addCustomScheme(scheme: "custom")
CefApp <-- CefAppHandler

CefApp -> CefAppHandler: onContextInitialize()
  CefAppHandler -> CefSchemeHandlerFactory: new()
  CefAppHandler -> CefApp: registerSchemeHandlerFactory(scheme: "custom",CefSchemeHandlerFactory())

== リクエスト ==

CefApp -> CefSchemeHandlerFactory: create(scheme: "custom")
  CefSchemeHandlerFactory -> CefResourceHandler: new()
CefApp <-- CefSchemeHandlerFactory

CefApp -> CefResourceHandler: processRequest(req: CefRequest, callback: CefCallback)
  CefResourceHandler -> CefCallback: Continue()
CefApp <-- CefResourceHandler
CefApp -> CefResourceHandler: getResponseHeaders(res: CefResponse)
  CefResourceHandler -> CefResponse: setStatus(200)
  CefResourceHandler -> CefResponse: setMimeType("text/html")
CefApp <-- CefResourceHandler

loop trueを返している間
CefApp -> CefResourceHandler: readResponse(data: byte[], size: int)
  CefResourceHandler -> Resource: read(data, size)
  CefResourceHandler <-- Resource: size/0
CefApp <-- CefResourceHandler: true/false
end

@enduml
```
Forkしたリポジトリから来たPRをローカルに取り込む方法

コマンドは

```
git fetch origin pull/PR番号/head:好きなブランチ名A
```

例えば#1のPullRequestをローカルに取り込みたい場合
ローカルPCで

```
git fetch origin pull/1/head:好きなブランチ名A
git checkout A
```

> ref: [GitHubの該当ドキュメント](https://docs.github.com/ja/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/checking-out-pull-requests-locally)


ただのgit fetchでPRのブランチも取れると思っていたら、違ったので調べました。
Ubuntu20.04.2 LTSにTerraformをインストール

# Terraformをインストール
## リポジトリをアップデート
```
$ sudo apt update -y
```
## wgetとunzipをインストール
```
$ sudo apt install -y wget
$ sudo apt install -y unzip
```

## 公式サイトからzipファイルをダウンロード、インストール
こちらの[公式サイト](https://www.terraform.io/downloads)よりLinuxの64bitをインストールする。そして展開をする。

```
$ wget https://releases.hashicorp.com/terraform/1.1.2/terraform_1.1.2_linux_amd64.zip
$ unzip terraform_1.1.2_linux_amd64.zip
```

展開してできてたファイルを/usr/local/binにコピーする。

```
$ sudo cp terraform /usr/local/bin
```

以上で環境構築は終わり。バージョンも確認しておく。

```
$ terraform -v
Terraform v1.1.2
on linux_amd64
```
【Laravel】BladeからVueコンポーネント・Bladeコンポーネントへの値の渡し方

## 内容
LaravelのBladeからVueコンポーネントへの値の渡し方について。
比較）LaravelのBladeコンポーネントへの値の渡し方
比較）Vueの親コンポーネントから子コンポーネントへの値の渡し方

この違いがいつも混同するのでまとめる。

## 目次
- [Laravel・BladeからVueコンポーネントへ値を渡す](#Laravel・BladeからVueコンポーネントへ値を渡す)
- [Laravel・BladeからBladeコンポーネントへ値を渡す](#Laravel・BladeからBladeコンポーネントへ値を渡す)
- [Vueの親コンポーネントから子コンポーネントへ値を渡す](#VueからVueコンポーネントへ値を渡す)

## Laravel・BladeからVueコンポーネントへ値を渡す


### Bladeの記述
（コントローラーから変数（\$test_variable）と配列（\$test_array）を運んできていると仮定）

```html:sample.blade.php
<sample-component :test-attribute='@json($test_variable)':array-attribute='@json($test_array)'>
```
- Vueコンポーネント：ケバブケース
- 属性名：ケバブケース
- 変数名：コントローラーから渡してきた変数名
- **注意）属性名の部分は '（シングルクォート）を使うこと（エディタの保管に注意）**
- **補足１）`'@json($変数名)'`の部分は、`"'{{ $変数名(文字列) }}'"`もしくは`"{{ $変数名(数値) }}"`でもよい。文字列は`'`が必要で、数値は`'`が不要な点に注意！**
- **補足２）補足１は配列の時は使用できない。**
- **補足３）boolは数字に変換されてしまうので、書くのであれば`{{ ($boolean) ? 'true' : 'false' }}`と書く必要がある。**
- **補足４）`@json($変数名)`を使うと数値も文字列も配列もboolもそのまま渡せるので、結局のところ一番ラク。**

### Vueコンポーネントの記述

```vuejs:SampleComponent.vue
<template>
  <p>{{ testAttribute }}</p>
</template>
<script>
  export default {
    props: {
     testAttribute: String,
     arrayAttribute: Array,
    }
  }
</script>
```
- ファイル名：アッパーキャメルケース
- 変数名：キャメルケース（Bladeの属性名がここに来る）

## Laravel・BladeからBladeコンポーネントへ値を渡す

### Bladeの記述
（コントローラーから変数（$test_variable）を運んできていると仮定）

```html:sample.blade.php
<x-directory.sanmple-conponent :test-attribute="$test_variable"></x-sanmple-conponent>
```

- Bladeコンポーネント名：`<x-ディレクトリ名.ケバブケース>`
- 属性名：ケバブケース（スネークケースでも動くが、ケバブケースが良い）
- 変数名：コントローラーから渡してきた変数名


### Bladeコンポーネント

```html:resources/views/components/directory/sample-conponent.blade.php
{{ $testAttribute }}
```
- 変数名：キャメルケース（属性名の部分がここに来る）

## Vueの親コンポーネントから子コンポーネントへ値を渡す

### 親コンポーネント

```vuejs:parent.vue
<chiled-component :test-attribute='testVariable'>
```
- 子コンポーネント名：ケバブケース
- 属性名：ケバブケース
- 変数名：キャメルケース


### 子コンポーネント

```vuejs:child.vue
<script>
  export default {
    props: {
     testAttribute: String,
    }
  }
</script>
```
- 変数名：キャメルケース（Bladeの属性名がここに来る）
Node.jsのバージョンがv17の場合、Vue.jsプロジェクト起動時に'ERR_OSSL_EVP_UNSUPPORTED'エラーが出る

## 環境
- Node.js: v17.2.0
- Vue.js: 3.5.0
- OpenSSL: 1.1.1
- WSL2(Ubuntu-20,04)


## 発生したエラー
Vue.jsプロジェクト起動後、`ERR_OSSL_EVP_UNSUPPORTED`エラーが発生した

```
$ npm run serve
> sample-app@0.1.0 serve
> vue-cli-service serve

 INFO  Starting development server...
10% building 2/4 modules 2 active .../webpack-dev-server/client/index.js?http://172.22.69.55:8080&sockPath=/sockjs-nodeError: error:0308010C:digital envelope routines::unsupported
   (省略)
  this[kHandle] = new _Hash(algorithm, xofLen);
                  ^

Error: error:0308010C:digital envelope routines::unsupported
   (省略)
    at FSReqCallback.readFileAfterClose [as oncomplete] (node:internal/fs/read_file_context:68:3) {
  opensslErrorStack: [ 'error:03000086:digital envelope routines::initialization error' ],
  library: 'digital envelope routines',
  reason: 'unsupported',
  code: 'ERR_OSSL_EVP_UNSUPPORTED'
}
```
## 原因


- Node.js 17はOpenSSL 3.0を利用している。
- OpenSSL 3.0では、OpenSSL 1.1.1で利用できた鍵やアルゴリズムがデフォルトで一部制限されている。
- そのため、Node.js 17では、OpenSSL 3.0で許可されていない鍵やアルゴリズムを利用したアプリケーションやモジュールを利用しようとすると`ERR_OSSL_EVP_UNSUPPORTED`エラーが出るみたいです。


>While OpenSSL 3.0 APIs should be mostly compatible with those provided by OpenSSL 1.1.1, we do anticipate some ecosystem impact due to tightened restrictions on the allowed algorithms and key sizes.
If you hit an ERR_OSSL_EVP_UNSUPPORTED error in your application with Node.js 17, it’s likely that your application or a module you’re using is attempting to use an algorithm or key size which is no longer allowed by default with OpenSSL 3.0. 

## 解決法


- 公式にある通りに下位互換の環境設定が必要とのこと。以下設定後、無事起動できました。

```
export NODE_OPTIONS=--openssl-legacy-provider
```

>A new command-line option, --openssl-legacy-provider, has been added to revert to the legacy provider as a temporary workaround for these tightened restrictions.


## 参考

https://medium.com/the-node-js-collection/node-js-17-is-here-8dba1e14e382