OmniAICreator/Qiita-1.07M huggingface dataset:
Azure Key Vaultの証明書をApplication Gatewayで使用する

AzureのApplication GatewayでTLS 終端を行う場合、証明書が必要です。証明書はApplication Gateway作成時にアップロードできますが、Key Vaultに事前にアップロードしてそれを利用することもできます。

#PFX証明書

Key ValutにはPEMもしくはPFXの証明書をアップロードできますが、Application Gatewayで使用するにはPFXでなければいけないみたいです。
PEM形式の証明書をApplication Gatewayから使用するとこの様なエラーが出ます。

```json
{
 "code": "ApplicationGatewaySslCertificateInvalidData",
 "message": "Data or Password for certificate /subscriptions/xxxxxxxxxxxxxxxxx/resourceGroups/xxxx/providers/Microsoft.Network/applicationGateways/test/sslCertificates/test is invalid."
}
```

#秘密鍵のフォーマット
AzureのKey Vaultに証明書をアップロードするには、秘密鍵のフォーマットがPKCS#8でないとはじかれるみたいです。
`-----BEGIN RSA PRIVATE KEY-----` で始まっているファイルはPKCS#1で、これをそのまま使うとアップロードするときにエラーが出ます。PKCS#8は `-----BEGIN PRIVATE KEY-----`で始まっています。 PKCS#1をPKCS#8に変更するには、以下のようして行えます。

```
openssl pkcs8 -topk8 -inform PEM -in ./private_v1.key -out private_v8.key -nocrypt
```

#PEMからPFX証明書を作成
PEMフォーマットの証明書からPFXフォーマットの証明書を作成するのは、以下の通りです。中間証明書がある場合はあらかじめ`public.pem`にコピーしておきます。

```
openssl pkcs12 -export -out my_cert.pfx -inkey private_v8.key -in public.pem
```

#Key Valutへアップロード
AzureのKey Valutへアップロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/a16a5351-9434-d3b5-8df0-3453cc657f3b.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/799224/7dae76c7-3e9e-42b8-a70c-61cb7b743572.png)

ここでは証明書の名前を`mycert`としておきます。

#Terraformから参照
アップロードした証明書はTerraformから以下のような感じで、参照できます。

```terraform
#証明書を使用していますが、参照するときはazurerm_key_vault_secretを使います。
data "azurerm_key_vault_secret" "my_cert" {
  name         = "mycert" #アップロードした時の証明書の名前
  key_vault_id = data.azurerm_key_vault.my_keyvault.id
}

resource "azurerm_application_gateway" "my_appgateway" {
...
  ssl_certificate {
    name                = "mycompany.com"
    key_vault_secret_id = data.azurerm_key_vault_secret.my_cert.id 
  }
}

```

https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/application_gateway


詳しくはこちらに書かれていますが、
> key_vault_secret_id - (Optional) Secret Id of (base-64 encoded unencrypted pfx)

PFX証明書のシークレットIDと指定されているので、`azurerm_key_vault_secret`を使ってIDを取得します。

これで、Key Vaultにアップロードした証明書をApplication Gatewayから使用することができます。
[1日目]AWS Clouds Practitioner の資格勉強記録

# この記事
AWS Clouds Practitioner の資格勉強の記録をしていきます。

## about me
都内で1年ちょっとウェブエンジニアをしています。
普段はPHP を使うことが多いです。

## 予定スケジュール
試験を受ける日を先に決めてから、試験勉強計画を建てました。

```
計画勉強時間：80 時間
平日 1h　休日（土日合計）6h
水曜は休み
10h /1week
必要な期間：8週間 = 2 ヶ月
試験受ける日→ 10/10(日)
```

こんな計画で進めていこうと思います。
頑張ろう。
micro:bitでハンドスピナーの回転数を計測する

#概要
micro:bitとフォトリフレクタでハンドスピナーの回転数を計測する仕組みを作りました。

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/microbit?src=hash&amp;ref_src=twsrc%5Etfw">#microbit</a><br>でハンドスピナーの回転数を測る。<br>①micro:bitの値　168ms<br>②iphone のストップウォッチ＋スローモーションカメラの値　5回転/秒　200ms <a href="https://t.co/GZ73FZwmwD">pic.twitter.com/GZ73FZwmwD</a></p>&mdash; keicafeblack (@keicafeblack) <a href="https://twitter.com/keicafeblack/status/1424302585486266368?ref_src=twsrc%5Etfw">August 8, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#使用したもの
①micro:bit v2
[②フォトリフレクタKKHMF TCRT5000](https://www.amazon.co.jp/gp/product/B07VJ9J19K/ref=ppx_yo_dt_b_asin_title_o00_s00?ie=UTF8&psc=1)

#説明
黒テープを張っている個所は幅があるため、
LastStatus、ThisStatus
の二つで、

>黒テープのの中：■■　1,1　
>黒テープの端：　■□　1,0 　計測開始　
>それ以外：　　　□□  0,0
>黒テーブの左端：□■　0,1　計測終了

上記のステータス管理をして時間を計測をしています。


#コード
https://makecode.microbit.org/_F91gdfbxUUHM
![MBハンドスピナーの回転数.JPG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/181708/bab2380e-8613-7734-2283-a45a55e7ca10.jpeg)

```javascript:HS.js
let V_IN = 0
basic.showIcon(IconNames.Heart)
basic.pause(1000)
basic.showIcon(IconNames.EigthNote)
let CNT = 0
let time = 0
let st_time = 0
let ed_time = 0
let this_status = 0
let last_status = 0
basic.forever(function () {
    V_IN = pins.digitalReadPin(DigitalPin.P0)
    this_status = V_IN
    serial.writeValue("IN", this_status)
    if (last_status == 1 && this_status == 0) {
        st_time = input.runningTime()
    } else if (last_status == 0 && this_status == 1) {
        ed_time = input.runningTime()
        time = ed_time - st_time
        serial.writeValue("TimeMS", time)
    } else if (last_status == 1 && this_status == 1) {
        st_time = 0
        ed_time = 0
    }
    last_status = this_status
})
```
install numpy, scipy, matplotlib and pandas on pyenv in M1 Mac

MacOS (Apple silicon M1; arm64) 上のPython(pyenv)でnumpy, scipy, matplotlib, pandas をインストールしたメモ。

基本的にscipy以外は苦労しない。

ref.)
https://github.com/scipy/scipy/issues/13409

# 準備
- Homebrew を使えるようにしておく
- pyenv を使えるようにしておく

## Python3.9以上をインストール 
- numpy用(本稿は3.9.6で確認)

```
$ brew install openssl readline sqlite3 xz zlib

$ pyenv install 3.9.6
$ pyenv local 3.9.6
```

- `libjpeg` は `matplotlib` のインストールに必要と思われる。
- 最後の　`pyenv local` は環境に応じて適宜変更のこと。

# numpy

```
$ pip install numpy
```

# scipy

```
$ export OPENBLAS=$(brew --prefix openblas)
$ export CFLAGS="-falign-functions=8 ${CFLAGS}"
$ pip install Cython pybind11 pythran
$ pip install --no-use-pep517 scipy
```

# pandas

```
$ pip install pandas
```

# matplotlib

```
$ brew install libjpeg
$ pip install matplotlib
```

errorやwarningが出る(詳しく見ていない)が、とりあえずimportはできる。
[メモ] Pythonで色付きprintを行うクラスを作成

# コード

一応，その他のPackage等ありますが，簡易クラスなら自分でも作成可能なのでメモ書きします．
ちなみにPackageの一つは [colorama](https://pypi.org/project/colorama/0.3.3/) です．
Color codeは[ANSI](https://en.wikipedia.org/wiki/ANSI_escape_code)に則って記述されます．

## Main code

@shiracamus さんの意見を元にクラス変数を辞書に変更しました．
@shiracamus さんから引数のpython builtin print対応とモジュール化をしてはどうか？という提案がコメントに記載されております．（元内容を維持するために本文はそのまま変更しておりません．）

```py
class pycolor:
    COLORS = dict(
        BLACK='\033[30m',
        RED='\033[31m',
        GREEN='\033[32m',
        YELLOW='\033[33m',
        BLUE='\033[34m',
        MAGENTA='\033[35m',
        CYAN='\033[36m',
        WHITE='\033[37m'
    )
    END = '\033[0m'

    @classmethod
    def print_(cls, txt: str, color='red') -> None:
        try:
            col = cls.COLORS[color.upper()]
            print(f'{col}{txt}{cls.END}')
        except KeyError:
            raise ValueError('color must be in {}, but got {}.'.format(', '.join(cls.COLORS.keys()), color.upper()))
```

## Test code

```
pycolor.print_('Can you see it?', color='black')
>>> Can you see it? # Black string

pycolor.print_('Failed', color='red')
>>> Failed # Red string

pycolor.print_('OK', color='green')
>>> OK # Green string

pycolor.print_('Warning', color='yellow')
>>> Warning # Yellow string

pycolor.print_('Should be no color', color='block')
>>> ValueError: color must be in ['BLACK', 'RED', 'GREEN', 'YELLOW', 'BLUE', 'MAGENTA', 'CYAN', 'WHITE'], but got block.
```

## その他のColor codes
前述のcoloramaで対応しているcolor codesは以下のとおりです．

```
ESC [ 0 m       # reset all (colors and brightness)
ESC [ 1 m       # bright
ESC [ 2 m       # dim (looks same as normal brightness)
ESC [ 22 m      # normal brightness

# FOREGROUND:
ESC [ 30 m      # black
ESC [ 31 m      # red
ESC [ 32 m      # green
ESC [ 33 m      # yellow
ESC [ 34 m      # blue
ESC [ 35 m      # magenta
ESC [ 36 m      # cyan
ESC [ 37 m      # white
ESC [ 39 m      # reset

# BACKGROUND
ESC [ 40 m      # black
ESC [ 41 m      # red
ESC [ 42 m      # green
ESC [ 43 m      # yellow
ESC [ 44 m      # blue
ESC [ 45 m      # magenta
ESC [ 46 m      # cyan
ESC [ 47 m      # white
ESC [ 49 m      # reset

# cursor positioning
ESC [ y;x H     # position cursor at x across, y down
ESC [ y;x f     # position cursor at x across, y down
ESC [ n A       # move cursor n lines up
ESC [ n B       # move cursor n lines down
ESC [ n C       # move cursor n characters forward
ESC [ n D       # move cursor n characters backward

# clear the screen
ESC [ mode J    # clear the screen

# clear the line
ESC [ mode K    # clear the line
```
リーダブルコードを読んでの個人メモ(2)

##メモ
・一貫性のあるコードにする
・似ているコードは似ているように見せる
・関連するコードはまとめてブロックにする


###例

以下の点に注意する

* 改行位置
* 縦の整列
* 段落分け
* 順序
 - HTMLのinputフィールドと同じ並び
* 重要度順
 - データベースのカラムの順番

以下のコードは、
*改行に一貫性がない
*縦に整列していない
*段落で分かれていない
*順序が適切でない

```
public class PerformanceTester {
    public static final TcpConnectionSimulator cell = new TcpConnectionSimulator(
           500, /* Kbps */
           80, /* millisecs latency */
           200, /* jiter */
           1 /* packet loss % */);

    public static final TcpConnectionSimulator t3_fiber = 
       new TcpConnectionSimulator(
           45000, /* Kbps */
           10, /* millisecs latency */
           0, /* jiter */
           0 /* packet loss % */);
    public static final TcpConnectionSimulator wifi = new TcpConnectionSimulator(
           100, /* Kbps */
           400, /* millisecs latency */
           250, /* jiter */
           5 /* packet loss % */);
}
```

修正後

```
public class PerformanceTester{
    // TcpConnectionSimulator(throughput, latency, jitter, packet_loss)
    //                            [Kbps]     [ms]    [ms]          [%]

    public static final TcpConnectionSimularor wifi =
      new TcpConnectionSimulator(500,   80,   200,   1);

    public static final TcpConnectionSimulator t3_fiber =
      new TcpConnectionSimulator(45000, 10,   0,     0);

    ...
}
```

コメントは1行にまとめ長いコードを改行し一貫性を保つ。
また、配列や引数にどんな値が入っているかをコメントに書いておく。
HTTP で温度と湿度を Harvest に送る

こちらのプログラムの送信プロトコルを　udp から http に変えてみました。
[UDP で温度と湿度を Harvest に送る](https://qiita.com/ekzemplaro/items/690faa6f56003272299f)


フォルダー構造

```text
$ tree harvest_http/
harvest_http/
├── harvest_http.ino
├── setupLTE.ino
└── temperature.ino
```

```text:harvest_http.ino
// ---------------------------------------------------------------
/*
	harvest_http.ino

					Aug/08/2021
*/
// ---------------------------------------------------------------
#include <WioLTEforArduino.h>
#include <ArduinoJson.h>
#include <stdio.h>

#define URL	"http://harvest.soracom.io"
#define SENSOR_PIN	(WIOLTE_D38)
#define INTERVAL	(10000)

DynamicJsonDocument doc(1024);

WioLTE Wio;
int TemperatureAndHumidityPin;

int icount = 0;

// ---------------------------------------------------------------
void setup() {
	setupLTE();

	TemperatureAndHumidityBegin(SENSOR_PIN);

	SerialUSB.println("*** Setup completed *** Aug/08/2021 PM 18:20");
}

// ---------------------------------------------------------------
void loop() {
	char data_json[128];
	int status;
	float temp;
	float humi;
	
	SerialUSB.println("*** loop ***");

	SerialUSB.println("icount = " + String(icount));
	
	if (!TemperatureAndHumidityRead(&temp, &humi))
		{
		SerialUSB.println("ERROR! *** TemperatureAndHumidityRead");
		}
	else
		{
		SerialUSB.print("Current humidity = ");
		SerialUSB.print(humi);
		SerialUSB.print("%  ");
		SerialUSB.print("temperature = ");
		SerialUSB.print(temp);
		SerialUSB.println("C");
		}

	doc["temp"] = temp;
	doc["humi"] = humi;

	serializeJson(doc, data_json);	
	 
	SerialUSB.print("Post:");
	SerialUSB.print(data_json);
	SerialUSB.println("");

	if (!Wio.HttpPost(URL, data_json, &status))
		{
		SerialUSB.println("### ERROR! HttpPost ###");
		}
	else
		{
		SerialUSB.print("Status: ");
		SerialUSB.println(status);
 		}
 
	SerialUSB.println("### Wait.");

	Wio.LedSetRGB(0, 0, 1); 
	delay(INTERVAL / 4);
	Wio.LedSetRGB(0, 1, 0); 
	delay(INTERVAL / 4);
	Wio.LedSetRGB(1, 1, 1); 
	delay(INTERVAL / 4);
	Wio.LedSetRGB(0, 0, 0); 
	delay(INTERVAL / 4);

	icount++;
}

// ---------------------------------------------------------------
```

setupLTE.ino
temperature.ino
は、元と同じです。
S3について学んだのでまとめてみた

私はzennでも[同様の記事](https://zenn.dev/mo_ri_regen/articles/amazon-s3-article)を書いているのでよろしければそちらのほうもどうぞ👋

## S3(Simple Storage Service)とは

99.999999999%[^イレブンナイン]の耐久性をもつオブジェクトストレージサービスです
保存容量の制限はなく、ストレージを自動で冗長化して保存します。

[^イレブンナイン]: 9が11コついているのでイレブンナインと呼びます。

## 保存形式について

S3ではバケット、プリフィクス、オブジェクトといった独特な用語があります。
それぞれ、下記のように対応しています。
ルートレベルのディレクトリ:バケット
バケットより下位のディレクトリ:プリフィクス
データ:オブジェクト

S3ではkey,value形式で表し階層構造はないですがわかりやすくするために
プリフィクスをディレクトリのように表します。
バケット名はすべて小文字でグローバルでユニークである必要があります。

## セキュリティについて

デフォルトではアカウント管理者またはルートユーザのみがアクセス可能です。なので、IAMでアクセス権限の管理を行う必要があります。
また、アカウント単位、バケット単位、オブジェクト単位でそれぞれACL(アクセスコントロールリスト)を設定できます。これは過去に[S3の設定ミスによる情報漏洩事故](https://news.yahoo.co.jp/byline/ohmototakashi/20171106-00077827)が起きたためにできた機能のようです。
たとえば、アカウント単位で設定するときはS3を作成するときに下記画像のように設定できます。
![アカウント単位のACL設定](https://gyazo.com/d4ed23514fdc5f979cb2f665a7a91c6b.png=100x)
パブリックアクセスをすべてブロックすることで新規でオブジェクトをアップロードするときに、非公開状態でアップロードされることになります。テスト用などの場合はパブリックアクセスをすべてブロックしたほうがいいでしょう。

## Webサイトのホスティング機能

S3にHTMLファイルのオブジェクトを保存することでエンドポイントURLが発行されるので、そのURLをアクセスすることでWebサイトを閲覧することができます。

※閲覧するためには、アカウント単位のACLの設定でパブリックアクセスをオンにする必要があります。

## イベント通知機能

S3にデータを保存したときなどのタイミングをトリガーにして他のサービス(lambdaなど)を呼び出すことが可能です。たとえば、メール通知などができます。私も過去にイベントで[Linebotの作成](https://zenn.dev/mo_ri_regen/articles/jawsdays2021-handson)をしたときに、Lambda関数を使いました。そこではS3に日本語のテキストが保存されるとLambda関数が発火して、英語に翻訳されました(記憶の範囲なので間違ってたらすみません🙇‍♀️)
イベント通知について[公式のチュートリアル](https://docs.aws.amazon.com/lambda/latest/dg/with-s3-example.html)があるので、お時間があるかたは試してみてください。

## ストレージクラス

S3では使用頻度に応じて、最適なストレージクラスを使い分けることができます。
それぞれ、料金の違いや読み出しにかかる時間などが異なります。
1ゾーンIA以外は、最低3つのAZに自動で配置されています。

- 標準
デフォルトで設定されているストレージクラスです。
- 標準IA
標準に比べてオブジェクトに格納される料金は安いが、データの読み出しに課金が必要です。
- Intelligent-Tiering
オブジェクトのアクセス頻度に応じて、自動的に最適なストレージクラスに振り分けてくれます。
- 1ゾーン-IA
標準IAよりも安価です。AZ1つ以上で冗長化していて、1つのAZにしか保存されていない可能性があります。AZ障害が起こると、データが消失するリスクがあるので、重要なデータは1ゾーン-IAは使わないようにしましょう。
- Gracier
標準のストレージクラスと比較して料金が1/5と、とても料金が安いですがデータの読み出しに課金され、データの読み出しに数分から数時間かかります。
- Gracier Deep Achive
料金がストレージクラスの中で最も安いですが、データの読み出しに課金され、データの読み出しに12時間以下の時間がかかります

## バージョニング(世代管理)

あるオブジェクトについてv1,v2,v3...etcと複数のバリアントを保持することができます。
バケット単位で有効にすると間違ってオブジェクトを削除しても簡単に復元することができます。
オブジェクトを削除した場合は完全に削除されずに削除マーカというものが付与されます。
S3に保存したオブジェクトの保存、取り出し、復元を行うことができます。
デフォルトではバージョニングは無効になっているので、明示的に[有効](https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/manage-versioning-examples.html)にする必要があります。

## ライフサイクルマネジメント

ある一定期間が過ぎると自動的にストレージクラスを移動するという設定ができます。

## 参考

AWSについてわかりやすく解説している神サービスです😇

https://aws-cloud-tech.com/

公式サイト

https://aws.amazon.com/jp/s3/

https://www.youtube.com/watch?v=G6kEtrFaEAU
IPFS + Filecoin でファイルを分散システムに保存するサービスのメモ

IPFS : ホットストレージ的. 長期に渡り使われない(アクセスされない)とデータを失うかもしれない
Filecoin : コールドストレージ的. IPFS と組み合わせ, IPFS でファイルがロストされたら Filecoin から復元する, みたいな.

IPFS のノードは立てやすいですが, Filecoin にデータ保存だと miner を建てる必要がある必要があるっぽい?で HW のハードルが高いので, 既存のサービスを使ってみます.

https://docs.filecoin.io/store/#apps

どのサービスも Filecoin マイニングなどしていて, その収益で fee プランを提供しているものと思われます.

Space.Storage が web3 アカウントで非中央集権的に扱えてよさそうですが, 現状 beta なので, Web3.Storage 使ってみます.

## Web3.Storage

https://web3.storage/

Protocol Labs(Filecoin の開発元)が作っています.

github アカウントあれば特に問題なく使えます. 合計 1 TB までファイルをアップロードできます.

ブラウザからぺろっとファイルをアップロードできます.

![Screenshot from 2021-08-08 18-15-09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/36275/85fe5117-e620-94f4-8bd8-20254da1ac37.png)



データは公開(Content ID が分かればアクセスできる)になるので注意です.
ホームページや電子公告など, 公開で長期に渡ってアクセスが必要になるものを扱うとよいでしょう.

NFT 用のストレージサービスもあります.

### ファイルはどれくらいの期間保存されるか?

Filecoin(Deals)は最低 18 ヶ月とあります.

また, web サイト(web3.storage)が終了したらファイルも消えます(保存される保証がなくなる)

https://web3.storage/about/#terms-of-service

非中央集権的にかつ永続的にファイルを保存したいのであれば, 

https://github.com/textileio/powergate

powergate などのツールが polish されるのを待つか, 自前で IPFS + Filecoin miner を建てるかになるでしょうか.
【JavaScript】「とりあえず」でjavascript:void(0)を使うな！！

# まず初めに
最近よく、

```html
<a href="javascript:void(0)" onclick="なんちゃらー">リンク</a>
```

というHTMLのコードを見かけるようになりました。
しかし、__void関数の意味を理解せずに適当に使っている人が多く__、

```html
<a href="javascript:void(0);alert('hogehoge');" onclick="~">リンク</a>
```
のような、__全くもって意味の無い使い方をしている方も見受けられます。__
なので、本記事では__void関数の仕組み、利用目的、利用方法などについて解説したいと思います__。
# void関数ってなんぞや？
まず、void関数について説明したいと思います。
__void関数は、引数に何を渡しても必ずundefinedを返す関数です。__
説明は以上です。

、というのも、__void関数は非常に単純な関数で、「真のundefined」を取得する事を目的に作られています。__
# いや真のundefinedってなんだよ
実は、__古いJavaScriptエンジンのundefinedにはreadonly属性が付いておらず、自由に上書き可能なのです。__

```js
console.debug( undefined ); // undefined
let undefined = 1234;
console.debug( undefined ); // 古いjsエンジンだと、「1234」と表示される
```

これは困りましたね。。
__「定義されていない」という事を表すundefinedを勝手に上書きされてしまったら、定義されていないかどうか判別するのにいちいちtypeof演算子を利用しないといけなくなってしまいます。__
そこで登場したのがvoid関数です。
この関数は、undefinedでは無く、本当の意味での「真のundefined」を返してくれます。
# でも何のためにaタグでJavaScriptURIを実行する際にvoid関数を使うんだよ
ここを理解していない方が多いみたいです。
> javascript: から始まる URI をサポートしたブラウザに於いて、それは、URI 内のコードを評価し、戻り値が undefined でなければ、返された値にページコンテンツを置き換えます。void 演算子は、undefined を返すために使用できます。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/void

はい、こーいう事です。
つまり、__aタグのリンク先がJavaScriptURIの時、その式がundefined以外を返した場合に、その内容をブラウザ上に表示するという仕様__なのです。
具体的には、

```html
<script>
function hogehoge() {
  // 何かの処理
  return "成功";
}
</script>
<a href="javascript:hogehoge();" onclick="alert('クリックされました！');">
  example
</a>
```

こんなコードがあった時に、IEなどの一部のブラウザでは「example」をクリックした際、__アラートが表示された上でドキュメントが「成功」という2文字だけに置き換わってしまいます。その際、「example」のボタンなども全て削除されて上書きされます。__

意味不明な仕様ですよね。
__既に、ChromeなどのChromiumベースのブラウザでは廃止されました。__
でも、今回は紹介出来ませんが、この仕様が役に立つ場合もあります。

# 誤用
冒頭でお見せした、このコード

```html
<a href="javascript:void(0);alert('hogehoge');" onclick="~">リンク</a>
```

の何がダメなのか、お分かりになりましたでしょうか？

__このaタグのhref先の式が実行された時に返される値は、最後のalert関数の戻り値の「true」です。__

なので、JavaScriptURIに対応しているバージョンのIEでこのコードを実行すると、__画面の左上に小さくtrueと表示されてしまいます。__

では、どうすれば良いのか、、。
と言われましても、__普通にundefined__を返せば良い話です。

おっと、NGワードを使ってしまいました。
NGワードとは、__「普通に」__です。

というのも、昔のJavaScriptエンジンではundefinedを上書き出来てしまうとお伝えした通り、undefinedが別の値に上書きされてしまっていたら、このコード

```html
<a href="javascript:undefined" onclick="~">リンク</a>
```

はundefinedでは無く、その「別の値」を返してしまい、__画面の左上に小さく何か表示されてしまいます。__

なので、void関数は__真のundefined__を返すためにあると考えれば、冒頭のコードは

```html
<a href="javascript:void(alert('hogehoge'));" onclick="~">リンク</a>
```

このように直す事が出来るはずです。

# 最後に
正直、__JavaScriptURIは今更使用するべきではありません。__
というのも、XSSの脆弱性の原因になりやすいからです。
XSS対策で有名な、Content-Security-Policyヘッダーを利用したりすると、もはやJavaScriptURIは評価すらされなくなります。
[JSTQB AL TM]　7. スタッフのスキル – チーム構成　を視覚的にまとめてみた

# はじめに
2021年8月のJSTQB　Advanced Level Test Manager(TM)の試験を受験予定のMa5am1nです。
[シラバス](http://jstqb.jp/dl/JSTQB-Syllabus.Advanced_TM_Version2012.J04.pdf)[^1]を読んでいるのですが、どうも文字が多くて頭に入りにくいので、図など視覚的に入ってきやすそうな形式でまとめてみます。

[^1]: 2012年度版 Advanced Level シラバス　日本語版　-テストマネージャ
**※あくまで私個人の解釈で作成したものです。内容が100%シラバスの通りであることは保証できませんので、ご了承ください。**
**※スライドの青文字、青線になっている箇所は、シラバスに記載されていない、私独自の解釈で記載した内容です。**

このページでは、7. スタッフのスキル – チーム構成について扱います。


# 7. スタッフのスキル – チーム構成
## 7.1 イントロダクション
![JSTQB AL TM （後半） (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/383cf860-a65e-b90e-4466-6d3658b890b2.png)


## 7.2 個人のスキル
![JSTQB AL TM （後半） (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/44de0995-b89b-e390-d305-759e28e5f9f3.png)
![JSTQB AL TM （後半） (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/05e8e3e1-beb7-a1a8-a34a-d567fd6b9b58.png)
![JSTQB AL TM （後半） (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/aef0fef3-b22b-a80c-51bd-2c49e96206b5.png)
![JSTQB AL TM （後半） (19).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/6368308a-1a54-3917-8fe1-36fad217968e.png)


## 7.3 テストチームの力学
![JSTQB AL TM （後半） (20).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/065a5b0d-0990-1eaa-0ae2-46ebe0dec30b.png)
![JSTQB AL TM （後半） (21).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/958e6dfb-f667-a196-4277-6ba4c73efc1d.png)


## 7.4 組織内におけるテストの適合
![JSTQB AL TM （後半） (25).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/917f78a4-0719-4387-83ea-94837424f3b7.png)
![JSTQB AL TM （後半） (26).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/e1f93df5-2d12-3b24-d7b9-e6ac3581bc1c.png)
![JSTQB AL TM （後半） (27).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/9cf18dee-c217-69f5-30eb-a062ef9b2da9.png)

## 7.5 モチベーション
![JSTQB AL TM （後半） (22).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/3b181ec7-f7c3-eca5-cfff-43abfda1be69.png)
![JSTQB AL TM （後半） (23).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/9207556e-4423-4a4b-b5c5-4d30c6bb811f.png)


## 7.6 コミュニケーション
![JSTQB AL TM （後半） (28).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/592ce746-5dcc-10b7-b1a0-de4bf3665cb6.png)
![JSTQB AL TM （後半） (29).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/79811e00-8688-b7cc-c7c9-c611424b3256.png)
![JSTQB AL TM （後半） (24).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1636570/0c7ac53b-2230-9644-69a2-d363deffecd9.png)
AWS VPCへのSSH接続方法

#概要
AWSの仮想サーバVPCへのSSH接続を行います。
SSH接続をするとネットワークを介して別のコンピュータにログインして操作ができます。
ネットワーク中でやり取りするデータが暗号化されるため、セキュリティ面で安全です。

#環境
PC：MacBook Air(2019)

##関連記事

https://qiita.com/onnov20/items/a34fad47dc7d871795b2

#1.ターミナルの起動

Macにあらかじめ用意されているターミナルを使用します。
Spotlightで検索するかアプリ一覧の中から探してみてください。
![スクリーンショット 2021-08-08 16.02.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860147/f20ec67b-a243-9b7f-986f-6f1652dc3e95.png)
起動すると画像のようなものが現れます。
![スクリーンショット 2021-08-08 16.06.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860147/5b87a40d-dfc2-9953-333f-ba5b32f4276a.png)
ここに文字を入力して、準備したVPCへの接続を行います。

#2.コマンド「ssh -i」
ログイン機能を呼び出す呪文、コマンドを入力します。
AWS VPC構築時に作成した秘密鍵を使用しますので、入力するコマンドは「ssh -i」です。
コマンド「ssh」の後ろに半角スペースを空け、オプション「-i」を入力します。
オプション「-○」は様々なものがあり、「-i」は秘密鍵を使って〜という意味になります。

```
% ssh -i /秘密鍵へのパス/秘密鍵のファイル名 ec2-user@パブリックIPv4アドレス
```
僕の場合はこんな感じです。
![スクリーンショット 2021-08-08 16.28.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860147/5396b41d-0a34-11e4-e47b-f5a5276b8342.png)
パブリックIPアドレスはAWSコンソールのインスタンスの画面で確認できます。
![スクリーンショット 2021-08-08 16.34.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860147/f8afab3e-2a09-ca4e-57c0-5f899acdeaa6.png)

#3.接続完了
無事ログインが完了すると画像のような表示となります。
![スクリーンショット 2021-08-08 16.40.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860147/b4f21695-fbfe-1784-5aff-150a887258a9.png)
初めてのログイン時には中央にEC2と表示されていることに気づくまで少し時間がかかりました。

#4.最後に
ご覧頂き、ありがとうございました。
間違い等がございましたら教えて頂けると幸いです。

ono
【Rails】Refinery を導入する時に発生したエラー対応

# はじめに

Railsエンジン```Refinery```というCMSが便利そうだと思ったので、すぐ使えるように試しに使ってみました。

その時に発生したエラーの解消方法を載せてみましたので、お困りの方は一読してみてください。



## エラー1: LoadError: incompatible library version

### 実行コマンド

```bash
$ rails new rickrockstar -m https://www.refinerycms.com/t/edge
```

### エラー内容

```bash
rake aborted!
LoadError: incompatible library version - /Users/user/.rbenv/gems/2.6.0/gems/ffi-1.15.3/lib/ffi_c.bundle
```


### 対応策

```ffi```のバージョンが不整合なため、```gem install```を実行する。

```bash
$ gem install ffi
``` 




## エラー2: wrong constant name Refinerycms-authentication-devise

### エラー内容

以下を実行すると、```rails aborted!```というエラーが発生する。

```bash
$ rails new rickrockstar -m https://www.refinerycms.com/t/edge
```


```bash
rails aborted!
Zeitwerk::NameError: wrong constant name Refinerycms-authentication-devise inferred by Module from file

  /Users/user/.rbenv/gems/2.6.0/bundler/gems/refinerycms-authentication-devise-4fbe5428ea2f/lib/refinerycms-authentication-devise.rb

Possible ways to address this:

  * Tell Zeitwerk to ignore this particular file.
  * Tell Zeitwerk to ignore one of its parent directories.
  * Rename the file to comply with the naming conventions.
  * Modify the inflector to handle this case.

....


Caused by:
NameError: wrong constant name Refinerycms-authentication-devise
```

### 対応策

```config/application.rb```へ```config.autoloader = :classic```を追加する。

```Ruby:config/application.rb
module Rickrockstar
  class Application < Rails::Application
    config.load_defaults 6.0
    config.autoloader = :classic  # この行を追加する
  end
end
```

### 参考情報

* https://github.com/refinery/refinerycms/blob/db64c6cc36fa52c59f0c6e0ce012ef672196be93/core/lib/generators/refinery/dummy/templates/rails/application.rb.erb#L14

---
### 会社紹介

**株式会社 Mosaica**  
最先端テクノロジーで社会課題を解決し、持続可能な未来を創造する IT カンパニー。
AI ソリューション、クラウド統合、DX 推進、経営コンサルティングなど包括的なサービスでビジネス変革を支援しています。  

詳しくは [公式サイト](https://mosaica.co.jp/) までお気軽にご相談ください。
公式サイト： https://mosaica.co.jp/
LeSS（Large-Scale Scrum）解説 -コンポーネントチーム vs. フィーチャーチーム-

#概要

LeSSにおける開発チームの望ましい形として「**フィーチャーチーム**」が挙げられております。
ではその**フィーチャーチーム**とは？
従来の**コンポーネントチーム**との違いとは？
これらの内容について本記事で解説させていただきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1830441/3ff6144e-ce4b-9e44-0c1c-10783133ef3e.png)

#コンポーネントチームモデルとは？

フィーチャーチームを説明する上で、まずは**コンポーネントチーム**も合わせて説明しなければならないでしょう。


>コンポーネントチームとはアーキテクチャを中心に構成されています。
例えばフロントエンドとバックエンド、JavaとPHP、あるいはモジュール・サブシステム別等、システムまたは技術の一部を専門とするチームを指します。
関連・・・[コンウェイの法則](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%83%AB%E3%83%B4%E3%82%A3%E3%83%B3%E3%83%BB%E3%82%B3%E3%83%B3%E3%82%A6%E3%82%A7%E3%82%A4)

例えばシステムA,B,Cに顧客価値のある機能（ドメイン・サブドメイン）X,Yがあった場合、それぞれの**システム**に合わせたA開発チーム,B開発チーム,C開発チームが存在するようなイメージです。
仮に顧客（及びプロダクトオーナー）がシステムA,B,C全てに変更が入る機能Xのバージョンアップ開発を要求した際には、A,B,C開発チームの開発範囲を取りまとめつつ、それぞれの開発スケジュールを合わせる等の調整を行う必要が出てきます。

すでにお気づきかと思いますが、**従来の開発チームの多くがこのチーム体制をとなっている**ことでしょう。


#フィーチャーチームモデルとは？

> フィーチャーチームとは**顧客価値**を中心に構成されており、各チームは、顧客ドメインの1種類以上の機能を専門としています。
例えば顧客管理（機能）、アイテム検索（機能）、スケジュール調整（機能）等、1つあるいは複数の顧客価値のある機能別に構成されています。



例えばシステムA,B,Cに顧客価値のある機能（ドメイン・サブドメイン）X,Yがあった場合、それぞれの顧客価値に合わせたX開発チーム,Y開発チームが存在するようなイメージです。
仮に顧客（及びプロダクトオーナー）がシステムA,B,C全てに変更が入る機能Xのバージョンアップ開発を要求した際には、**X開発チームへ当該要求を提示することでX開発チームのみでA,B,Cシステムへの改修を完結させることが可能**となります。

#コンポーネントチーム vs フィーチャーチーム

ではここからはそれぞれのチーム形式の**対になっている特徴をピックアップし比較**してみましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1830441/68d47c18-d6c6-e0bb-43ae-0b2395de85d1.png)

| No. | コンポーネントチーム               | フィーチャーチーム             | 
| --- | ---------------------------------- | ------------------------------ | 
| ①  | 明確な「コードと設計」の所有権     | 明確な「機能」の所有権         | 
| ②  | コンポーネントへの深い専門性       | 顧客価値への深い専門性         | 
| ③  | 不均衡で非同期な依存関係           | 依存関係がない                 | 
| ④  | 顧客価値 ＜ アウトプット量         | 顧客価値 ＞ アウトプット量     | 
| ⑤  | ウォーターフォールにつながりやすい | アジャイル開発につながりやすい | 
| ⑥  | 開発が容易                         | 開発が困難                     | 
##コンポーネントチームの特徴

コンポーネントチームでは、特定のコンポーネントのみが改修範囲となるため所有権（責任）は当該コンポーネントの「コードと設計」となり**顧客価値の一部にのみ所有権を持つ**ことになります。（No.①）
各チーム間は非同期となっているため、それぞれの成果物の統合には各チーム毎の或いはチーム全体の**管理者による調整**が必要となってきます。（No.③）
これを解決するために複数コンポーネントチームでプロジェクトチームを立ち上げて定例の進捗確認会議による管理等の策を講じ、結果的に**シーケンシャルな工程と長いリリースサイクルにつながりやすくなります**。（No.⑤）
また特定コンポーネントで用いられている技術や仕様への専門性が高いため、このコンポーネント内での開発における速度や品質は高くなり**多くのソースコードのアウトプット**が望め、かつ使用技術が固定されることから人事的な調整も容易となる反面、各チーム毎では顧客価値の一部しか実現することができません。（No.②,④,⑥）

##フィーチャーチームの特徴

フィーチャーチームでは、顧客価値に合わせた改修範囲となるため所有権（責任）は顧客価値を実現したもの（機能）となります。（No.①）
フィーチャーチームでは**実現したい顧客価値に合わせた所有権**を持っているためPOとしては**開発チームへ依頼するのみで良くなります**。（No.①）
複数チームでこれの実現が必要となる場合は、各チームでクロスチームプランニングを行う等の調整で済みます。（No.②,③）
また複数コンポーネントでの開発が必要となるため（コンポーネントチームに比べて）多くの技術的知識・仕様を把握する必要があり、これにより**開発速度及び設計・ソースコードの品質低下**に繋がる可能性があり、人事的な調整も困難となるため、これの克服をする必要があります。



# 結論

上記よりコンポーネントチームとフィーチャーチームのどちらが良いの？と言われれば、**顧客中心**の観点では**フィーチャーチーム**となることが良く、**アーキテクチャ中心**の観点では**コンポーネントチーム**となることが良いと言えるでしょう。

上記の特徴から**我々はフィーチャーチームを目指すべきと**感じた場合、実際コンポーネント別で違う環境、言語（他進捗管理方法等）であることも多いため、この移行についてはいくつかの課題を解決しなければなりません。

では、**これを実現するにはどうすれば良いのでしょうか**？
以下の記事で詳しく解説していきます。


[WIP]フィーチャーチームへの移行と調整についての記事作成
AtCoderログ：0062 - CODE FESTIVAL 2016 qual B B 

# 問題

https://atcoder.jp/contests/code-festival-2016-qualb/tasks/codefestival_2016_qualB_b

## 問題文
> CODE FESTIVAL 2016の予選には $N$ 人が参加しました。参加者は、国内の学生であるか、海外の学生であるか、どちらでもないかのどれかです。
> 予選は国内または海外の学生のみが通過することができ、上位の学生から順に、以下の条件を満たすときに通過します。学生でない参加者は予選を通過できません。
> ・国内の学生は、現在予選の通過が確定した参加者が $A+B$ 人に満たなければ、予選を通過する
> ・海外の学生は、現在予選の通過が確定した参加者が $A+B$ 人に満たず、さらに海外の学生の中での順位が $B$ 位以内なら、予選を通過する
> 参加者の情報を表す文字列 $S$ が与えられます。$S$ の $i$ 文字目が a のとき予選で $i$ 位の参加者が国内の学生であることを、$S$ の $i$ 文字目が b のとき予選で $i$ 位の参加者が海外の学生であることを、$S$ の $i$ 文字目が c のとき予選で $i$ 位の参加者がそのどちらでもないことを表しています。
> すべての参加者について、上位から順に、予選を通過した場合はYes、そうでない場合はNoを出力するプログラムを作成してください。

## 制約
> ・$1 \le N,A,B \le 100000$
> ・$A+B \le N$
> ・$S$ の長さは $N$ である。
> ・$S$ は文字 a と b と c のみからなる。

## 収録されている問題セット
- [[BfB-E]\(AtCoder Problems Boot camp for beginners Easy 100\)](https://kenkoooo.com/atcoder/#/training/Boot%20camp%20for%20Beginners/1) #003 

# 回答
## 回答1 (AC)
問題文に書かれていることをそのままコーディングすれば良い問題です。予選を通過した国内学生の人数を変数 na に、予選を通過した海外学生の人数を変数 nb に記録します。予選で $i$ 位の参加者が国内学生ならば、これまでに予選を通過した学生数 na+nb が $A+B$ より小さければこの国内学生は予選通過となるので、na を 1 増加します。予選で $i$ 位の参加者が海外学生ならば、これまでに予選を通過した学生数 na+nb が $A+B$ より小さく、かつ予選を通過した海外学生数 nb が $B$ より小さければ、この学生は予選通過となるので、nb を 1 増加します。コードは以下のようになりました。

```C++:cf2016qb_b-1.cpp
#include <bits/stdc++.h>
using namespace std;

int main() {
  int n, a, b;
  cin >> n >> a >> b;
  string s;
  cin >> s;

  int na = 0, nb = 0;
  for ( int i=0; i<n; i++ ) {
    string yosen = "No";
    if ( s.at(i)=='a' ) {
      if ( na+nb<a+b ) {
        na += 1;
        yosen = "Yes";
      }
    } else if ( s.at(i)=='b' ) {
      if ( na+nb<a+b && nb<b ) {
        nb += 1;
        yosen = "Yes";
      }
    }
    cout << yosen << endl;
  }
}
```

# 調べたこと
## [AtCoder の解説](https://atcoder.jp/contests/code-festival-2016-qualb/tasks/codefestival_2016_qualB_b/editorial) → [コンテスト全体の解説](https://img.atcoder.jp/data/other/code-festival-2016-qualb/editorial.pdf)
回答1と同じ方針でした。

# リンク
## 前後の記事
- 前の記事 → [AtCoderログ：0061 - AGC 012 A](https://qiita.com/RoadLynton/items/8ed2a55a001e9e4d2ff2)
- 次の記事 → [AtCoderログ：0063 - ABC 085 B](https://qiita.com/RoadLynton/items/fcdbb429c74bf7c61056)
2段 ssh 設定と root ログイン設定

## はじめに
VScode などで踏み台を経由したリモートサーバのコード管理や、そのサーバの root でのコード管理を行いたいため、
1回の ssh コマンド実施で多段の ssh を実行できるようにした
ssh の config 設定などをしたので、やったことを記載する

## 実施概要図
1段目のサーバ(ここでは bastion)を踏み台に、2段目サーバ(ここでは ansible) にログインする

さらに 2段目サーバで root ログインも可能にする
(/etc/配下などのコードを管理したいとき用. これはやりようが他にも色々あると思うが、ここでは ssh root@localhost をしている)

![スクリーンショット 2021-08-08 15.41.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/8bfb8fa4-d732-93a9-e4cd-a58c439d2937.png)


## 設定・実施

`~/.ssh/config` に設定を実施する

```config:~/.ssh/config
# 1段目
Host bastion
  HostName [踏み台サーバ(1段目)のIPまたは名前解決可能なhost名]
  Port 22
  User [踏み台サーバ(1段目)のユーザ名]
  IdentityFile ~/.ssh/id_rsa #鍵を指定して実施する場合
  ForwardAgent yes #localのsshキーを使う場合はこれをつける

# 2段目
Host ansible
  HostName [踏み台サーバ(2段目)のIPまたは名前解決可能なhost名]
  Port 22
  User [踏み台サーバ(2段目)のユーザ名]
  ProxyCommand ssh -W %h:%p bastion
  # ForwardAgent yes #localのsshキーを使う場合はこれをつける

# 2段目rootログイン (3段目)
Host ansible_root
  HostName localhost
  Port 22
  User root
  ProxyCommand ssh -W %h:%p ansible
```

2段目のサーバに root への直接SSHログインを禁止している場合は、
localhost (127.0.0.1) からは許可できるように sshd_config へ下記設定も追記する
(設定したら sshd のリスタート(`systemctl restart sshd`)も実施する)

```config:/etc/ssh/sshd_config(最後に追記)
Match Address  127.0.0.1
    PermitRootLogin yes
```

上記設定を ansible で設定すると下記のような感じ

```yaml:tasks/main.yaml
  - name: Permit localhost root login
    lineinfile:
      dest: /etc/ssh/sshd_config
      line: "{{ item }}"
    with_items:
      - "Match Address  127.0.0.1"
      - "    PermitRootLogin yes"
    become: yes
    register: sshd_config_result

  - name: restart sshd
    when: sshd_config_result is changed
    systemd:
      name: sshd
      state: restarted
    become: yes
```

上記設定により ssh コマンド 1回で直接2段目のサーバへログインが可能になる

下記が ssh 実行での出力例 (`user2`が2段目サーバユーザ名、`192.168.129.1`が2段目サーバIP例,`ansible01`が2段目ホスト名)
(ここでは 1段目にsshキーをnopassのをauthorized_keyにしているため1回しか聞かれてない)

```sh:ログイン例
% ssh ansible
user2@192.168.129.1's password: 
Last login: Sun Aug  8 15:00:47 2021 from 172.18.0.8
ANSIBLE01 /home/user2% 
```

root ログインも下記のように可能 (rootのパスワードも聞かれる)

```sh:ログイン例(root)
% ssh ansible_root
user2@192.168.129.1's password: 
root@localhost's password: 
Last login: Sun Aug  8 15:16:43 2021 from 127.0.0.1
[root@ansible01 ~]#
```

VScode でも拡張で [Visual Studio Code Remote - SSH](https://code.visualstudio.com/docs/remote/ssh) を入れていれば、
下記のように`~.ssh/config`に設定したホスト名が出てくるのでクリックして開けるようになる
(出てこない場合は、⚙歯車マークをクリックして設定した `~/.ssh/config` を指定する)

![スクリーンショット 2021-08-08 15.27.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/326183/be86ef15-ffcb-f68d-d93a-e41a6e9e118e.png)


## おわりに
多段 ssh および root ログインを ssh 設定でコマンド一回ででできるように設定した
これより VScode でもリモートのコード管理ができるようになった
【Flutter環境構築】Unable to find bundled Java version. エラーの解決方法【MacBook Air (M1, 2020)】

# flutter doctor で "Unable to find bundled Java version."ってエラー出る

ここだけエラー消えない(´・ω・`)

```
% flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 2.2.3, on macOS 11.3.1 20E241 darwin-arm, locale ja-JP)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0)
[✓] Xcode - develop for iOS and macOS
[✓] Chrome - develop for the web
[!] Android Studio (version 2020.3)
    ✗ Unable to find bundled Java version.
[✓] VS Code (version 1.58.2)
[✓] Connected device (1 available)

! Doctor found issues in 1 category.
```

# 解決方法

コマンドこれ打ったら解決した

```
% cd /Applications/Android\ Studio.app/Contents/jre
% ln -s ../jre jdk
% ln -s "/Library/Internet Plug-Ins/JavaAppletPlugin.plugin" jdk
% flutter doctor -v
```

# 参考にしたサイト

## Flutter環境構築

とってもわかりやすい

https://katsfreelife.blog/flutter-m1-mac-built-environment/

## 今回のエラー

どんぴしゃの質問＆回答
これによるとJAVA_HOMEも設定しないといけないらしいんだけど、
私のはJAVA_HOME設定しなくてもいけた(´ω`)

https://stackoverflow.com/questions/68569430/flutter-unable-to-find-bundled-java-versionflutter-doctor-after-updated-andro
Chromebookを買ってみた

#Chromebookを購入
ほぼ衝動買いに近い状態でChromebookを購入。
用途は自室からメインPC（リビングに設置）へのリモート接続。
それと以前からやってるflutterでのアプリ開発をできればと。

#機種選定
リモート接続できればってことで、以前から欲しかったchromebookというのが第１の選択理由。安いし。
しかしそれでアプリ開発するってことになるとやはりメモリ8MBは欲しいところ。
はい、安いやつはほぼ4MBなんですよね。
それとできればタッチ操作できる液晶が欲しい。
ほぼ条件としてはこれだけ。

#機種確定
ここまで数日。
目に止まったのがASUS Chromebook Flip CM5(CM5500)
完全に予算オーバーだが衝動的に買ってしまった。
SSD256MB、Ryzen5 3500C、8GBメモリ
ちょっとスペックオーバーな気もしますが。

#買ってみて・・・
重い。さすがに2kg弱もある。
まぁ持ち運び用途は考えていないからよし。
キーボードもこのサイズだと普通に打てるし。
![IMG20210804212106.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/f8972e44-a65b-2fc2-0afd-25eb361940b5.jpeg)

#さっそくLinuxインストール
さっそくLinux入れてflutter環境を構築！
ってことでやってみた。
。。。何かと問題発生でなかなか環境構築できず。
そのあたりはまた今後へ。
さすがにAMDのCPUは無茶だったか。
![Screenshot 2021-08-07 16.31.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/d8ee9a61-565a-8d57-10b1-59b3a0dc9c62.png)
pyenv cheatsheet

# pyenv cheatsheet

## Commands

### List versions available on the Internet

```console
% pyenv install --list
Available versions:
  2.1.3
  2.2.3
(...snip...)
```

### Install specific version

```console
% pyenv install 3.9.6
Downloading Python-3.9.6.tar.xz...
-> https://www.python.org/ftp/python/3.9.6/Python-3.9.6.tar.xz
Installing Python-3.9.6...
(...snip...)
```

### Uninstall specific version

```console
% pyenv uninstall 3.10.9
pyenv: remove ${HOME}/.pyenv/versions/3.10.9? [y|N] y
pyenv: 3.10.9 uninstalled
```

You can also uninstall a version by removing its directory like `rm $(pyenv prefix 3.10.9)`.

### List versions installed at local

```console
% pyenv versions
* system (set by /home/foo/.pyenv/version)
  2.7.18
  3.9.6
```

### Use specific version just for current shell session

```console
% pyenv shell 3.13.0
% python --version
Python 3.13.0
```

### Create virtualenv with specific version

Syntax:

```console
% pyenv virtualenv [version] <virtualenv-name>
```

Example:

```console
% pyenv virtualenv 3.9.6 sspa-py3.9
Looking in links: /tmp/tmpgfsv96lg
Requirement already satisfied: setuptools in /home/foo/.pyenv/versions/3.9.6/envs/sspa-py3.9/lib/python3.9/site-packages (56.0.0)
Requirement already satisfied: pip in /home/foo/.pyenv/versions/3.9.6/envs/sspa-py3.9/lib/python3.9/site-packages (21.1.3)
% pyenv versions
* system (set by /home/foo/.pyenv/version)
  2.7.18
  3.9.6
  3.9.6/envs/sspa-py3.9
  sspa-py3.9
```

### Set application specific version with virtualenv

You can specify the virtualenv version created above.

```console
% cd /path/to/your/application
% pyenv local sspa-py3.9
% python -V                       # check the python virsion
Python 3.9.6
```

### Activate/deactivate virtualenv

```console
% pyenv activate <virtualenv-name>
% pyenv deactivate
```

### Delete virtualenv

```console
% pyenv virtualenv-delete <virtualenv-name>
```

Note: Do not just `pyenv uninstall <virtualenv-name>`, although it is described in the [README](https://github.com/pyenv/pyenv-virtualenv#delete-existing-virtualenv) of `pyenv-virtualenv`. That will not delete `$(pyenv root)/versions/<version>/envs/<virtualenv-name>`. If you have done that, you will need to delete the directory manually.

## Upgrade pyenv

```console
% cd `pyenv root`
% git pull
```

see: https://github.com/pyenv/pyenv#upgrading
Liquid error: Could not find asset ****.liquid　の原因と対処法


>Liquid error: Could not find asset snippets/product-customizer.liquid


Shopifyのテーマ開発をしている際に、このようなエラーが出て困ったので、その経験を共有します。

このエラー分は「ファイルがない」と示しているのですが、実際にこのファイルを削除した記憶、記録はなく、対処に困りました。

原因は、ファイルをテーマに反映させる際に、以下のコマンドを深く理解せずに実行したことが原因でした。

  ```ruby:qiita.rb
 $ theme deploy
  ```

このコードはTheme　Kitのコマンドで、ローカル環境のファイル内容をすべてdeployする時に使います。
このコマンドを私も使用した後に、上記のエラーが表示されました。
このコマンドの注意点は、**反映先のファイルがすべてローカル環境のファイル内容に書き換わるので、ローカルにないファイル（例：アプリのファイルなど）も削除されて、ローカルと全く同じ内容のファイルしか残らない点です。**

このコマンドを実行したので、必要なファイルが意図せず消えたので、上記のエラーが表示されました。


このコマンドを実行する際は以下のように、「-n」をつけることをおすすめします。

  ```ruby:qiita.rb
 $ theme deploy -n
  ```
「-n」をつけることで、Shopifyからファイルを削除せずに、deployが実行されます。
[公式ドキュメント]（https://shopify.dev/themes/tools/theme-kit/command-reference#deploy）


一度、deployしたテーマでは、削除されたファイルは復元できないと思われます（推測）

もしローカルデータを保持したまま、テーマをdeployしたい場合は、
対象のテーマを複製し、「config.yml」のtheme_idを複製したテーマIDに変更し、「$ theme deploy -n」を実行すれば、ローカルでの作業データを維持したまま、Shopifyにアップロードできました。
（私の場合は、本番テーマを複製したテーマで今回のエラーが出て、戻せなくなったので、再度、本番のテーマを複製して、theme_idを変えるだけでうまく対処できました。）
Weakly Supervised Dataset Collection for Robust Person Detection

#Weakly Supervised Dataset Collection for Robust Person Detection

##要約
ロバストな人物検出を実現するアルゴリズムを構築するために、800万枚以上の画像を含むデータセットを公開。既存の検出器を用いた人物検出と、誤検出を抑制するためのデータ改良という2段階の収集プロセスに基づいて、870万枚の人物画像を収集。Weakly Supervised Person Dataset (WSPD)は、シンプルでありながら、人物検出の事前学習に有効であることがわかりました。事前学習された人物検出アルゴリズムの中で、WSPDで事前学習されたモデルは、完全に教師されたImageNetおよびEuroCity Personsデータセットで学習された同じモデルと比較して、Caltech Pedestrianで検証した場合、それぞれ13.38%および6.38%の精度向上を実現。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860620/3cc13f34-18af-a3c1-e3e0-d5372e1677ce.png)

##手法
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860620/5c15c043-38b8-9f7e-bf73-7e6552bba45c.png)


##定量的な評価結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1860620/908d8c47-8cfc-a9c8-ef8f-a462393c9c81.png)

##実装
https://github.com/cvpaperchallenge/FashionCultureDataBase_DLoadernee
KeePassXC を TouchID でいつでもロック解除するには

オープンソースのパスワード管理ソフト KeePassXC の小ネタです。

## TouchID でロック解除できるって本当？

Mac の KeePassXC には、ロック解除画面に『TouchID で素早くロック解除する』というチェックボックスがありますよね？
「TouchID で解除出るなら便利！」と思って使い方を調べると、ほとんど情報が見つかりません。
なんとなくロック画面で指をおいてみても TouchID が反応するわけでもなく、「使えななくない？」と勘違いされているのは私だけではきっとないはず。。。

## 正しい TouchID でのロック解除方法

かんたんです。というか、なぜこれがわからなかった自分。。。
ロック解除画面で、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252217/2145d517-6158-8080-fd67-15e0063ab046.png)

[TouchID で素早くロック解除する] がチェック状態であることを確認し、**[OK] ボタンを押す。**

> 厳密には下記手順ですが、1. と 2. はロック解除画面を開いた時点のまま確認するだけです。
> 1. パスワードには何も入力せず（何も変更しない）
> 2. [TouchID で素早くロック解除する] がチェック状態であることを確認（何も変更しない）
> 3. [OK] ボタンを押す

**すると、TouchID の入力待ちダイアログが表示されます。**

![touchid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252217/449503aa-63a1-790a-f640-499145864216.png)

**これで TouchID でロック解除できます。**

## Touch ID の入力待ちダイアログが出ないんだけど？

こんなダイアログが表示されてしまった場合、

![error.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252217/8a0cbc8d-5efd-ee3a-3513-f4e0d632da8c.png)

キーチェインに KeePassXC データベースのパスワードが登録されていません。もしくは、削除されてしまっています。
TouchID　を使用する設定にした上で、一度パスワードでロック解除する必要があります。

### ロック解除画面で [TouchID で素早くロック解除する] にチェックが入っていない場合

そもそも TouchID を使用する設定になっていません。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252217/2145d517-6158-8080-fd67-15e0063ab046.png)

ロック解除画面で、

1. パスワード入力
2. [TouchID で素早くロック解除する] にチェック
3. [OK] ボタンを押す

このあと、データベースをロックしてロック画面に戻り、再度試してみてください。

### ロック解除画面で [TouchID で素早くロック解除する] にチェックが入っているけど、たまに TouchID が使えない

アプリケーション設定の問題です。

![options.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/252217/0d5448ab-1ee5-e460-b173-7a6bfe01f5d2.png)

アプリケーション設定画面の開き方は、下記の手順です。

1. [アプリケーション設定]：上部ツールバーの ［⚙ (歯車マーク)］ をクリック
1. [セキュリティ] タブ：左の列にある［セキュリティ］をクリック

この中で２つ、TouchID を自動で削除する設定があります。

#### [未操作の時間が続いたら TouchID を消去する]

標準設定では無効（チェックなし）です。
有効になっている場合、未操作の時間が指定時間をすぎると TouchID でのロック解除ができなくなります。
未操作の時間は分単位で指定できます。

#### [セッションをロックしたりラップトップを閉じた際に TouchID を消去する]

標準設定は有効（チェック済み）です。
**TouchID でログインできなくなる場合、たいてい原因はこれです。**
有効になっている場合、再起動やログオフ、MacBook の画面を閉じるなどの動作を行うとキーチェーンから KeePassXC データベースのパスワードが削除されるようです。
結果として、TouchID でロック解除が使えなくなります。
使い勝手を優先される場合は無効にしてみてください。

## 他 プラットフォーム の生体認証機能について

KeePassXC は、Windows / Mac / Linux マルチプラットフォームで使えるアプリです。
私が KeePassXC を導入している理由は、オープンソースであるからが一番大きな理由なのですが、マルチプラットフォームであるのも１つの大きな理由です。

Windows には Windows Hello という生体認証システムがありますが、そもそも未対応のようでした。残念。
Linux にも生体認証機能が使えるディストリビューションあるみたいですが、まぁ対応していないと思います。（生体認証機能付きの実機がない）

KeePassXC には Android / iPhone の対応はありません。
ただ、 KeePassXC というか 大本の KeePass 系がオープンソースなため、それぞれ派生した別アプリを使用すれば生体認証使えます。オープンソース万歳。
Android であれば Keepass2Android、 iPhone なら KeePassTouch がそれぞれ生体認証に対応していますので、私はこれらを使用しています。

## 注意

この記事はパスワードでロック解除するケースのみを対象としています。
キーファイルやハードウェアキーを併用したケースは実験していませんのであしからず。
Qiita Markdownを理解する

# はじめに
Markdownの書き方を学んだことをこちらにまとめておきます。
＊自分の振り返り用
　
#目次
 
1.見出し
2.コードを挿入する方法
3.リンク挿入、画像埋め込み
4.引用
5.装飾
6.リスト
7.水平線
8.Markdownを無効化
 
##見出し
「#」を直前に付ける

>#見出し 
\#見出し
>##見出し
\##見出し
>###見出し
\###見出し

##コードを挿入する方法
コードを挿入する時は「```」バッククオートを使用する

> ```
<div>テキスト</div>
<p>テキスト</p>
```
\`\`\`
\<div>テキスト\</div>
\<p>テキスト\</p>
\`\`\`

コードにファイル名を挿入する場合、```html:ファイル名にするだけ

```html:practice.html
<div>テキスト</div>
<p>テキスト</p>
```
##リンク挿入、画像埋め込み
リンク挿入は[参考サイト](URL)と書く
>
\[参考サイト](URL)
[参考サイト](https://qiita.com/)

画像挿入
「!」を直前に付けるだけ
>
\!\[参考サイト]\(URL)
![1152138.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1854812/9da32ad6-65d9-5f58-3221-60291c11ba7f.jpeg)

##引用
「>」を直前につけるだけ
> \>
>>あああああ

##装飾
太文字「\*\*文字**」をつけるだけ
>
\*\*文字**
**文字**

##リスト
「|」を使用する。文字列を左揃え・中央揃え・右揃えを指定できる
>
\|赤|白|黄色|
|:---|:---:|---:|
|左揃え|中央揃え|右揃え|

>
|赤|白|黄色|
|:---|:---:|---:|
|左揃え|中央揃え|右揃え|


「*」を使用する。
>
\ *
>
* あ

「数字.」を使用する
>
\1.
>
1.
2.

##水平線
「***」「---」を使用する

>
\---
\***
>
---


##Markdownの無効化

「\」を前につける事で無効化できる

> \\#無効化

##参考

*[Qiita Markdown 書き方 まとめ](https://qiita.com/shizuma/items/8616bbe3ebe8ab0b6ca1)
Nuendoでステップ入力Undo

#はじめに
昔のLogicのステップ入力が恋しいのですが、

Nuendoに切り替えてから、ステップ入力でできないこと（できてほしいこと）があって、
なんとかしたいという備忘録。

- 最後入力の音の長さを入力ステップ長で伸ばす
（昔のLogicではサスペンドペダルやTabキーで伸ばせた・・・今どきはWindowsだとTabは編集Area切り替えがシステムで持ってるからできないかもだけど）
- 一手戻す（入力ミス時にUndo　上の音価の縮めるとかもUndoできる）
- テンキーのところに16分音符とか8分音符の切換え(6だと3連系だったかとか、ピリオドで付点入力とか・・・　　ってもともとLogicはNotatorLogicだったか 楽譜制作に近い操作系）

が欲しいなぁと思いつつ

# タイの入力

最後に入力した　音価を変える（伸ばす、縮める）という機能が欲しいのですが、
ググって見つかったのが

[Cubaseのステップ入力をグレードアップする「タイ入力」の設定](https://arynco.com/creation/cubase-step-input/)
を参考に
タイ（１６分音符伸ばす）っぽいのはできたけど・・・
たまに表示位置がおかしくなったり、

１６分音符制限がかなりきつい・・
（→クォンタイズ値で音の長さを伸ばす・縮める　とかコマンドがあればよいのだが・・・Nuendoにはないみたい）

むぅ

# Undoが欲しい

ステップ入力でUndoはできても、
ナビゲート位置（青い線）が戻ってくれない。

このミスのたびにCtr+zとカーソル←を押すのがかなり面倒・・・
（ミスをする人間なので、最小ステップでUndoしてもとに戻るかが操作性で大事なところ）

# ステップ入力を一手戻す（直前の入力を無かったことにする）

以下のようなマクロを作ってみた

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/4fc81ccd-0e49-472b-085d-bbba6c7521d5.png)

編集・削除
ナビゲート・Left

だけでも良いかもしれない・・
（Pythonとかでスクリプト書かせてほしいなぁ・・・　すべてのDAWはReaperくらいなんでもできるようにしてほしいところ・・・）
【Python】CSVファイルの内容をspaCyとGiNZAで解析してワードクラウド化

##はじめに
グーグル検索結果のタイトルとリンクをCSVファイルに保存するようにした
[【Python】グーグル検索結果のタイトルとリンクをCSVファイルに保存（ページ移動有）](https://qiita.com/sgeboku/items/058525e5ff8ddf002cbb)	

CSVファイルから文章を抜き出して、ワードクラウド化と単語の出現頻度をグラフ化していく～


##仕様
・csvファイルの処理対象のデータは"title"というヘッダーの列
・csvファイルの文字コードは"UTF-8","cp932"のいずれか
・処理対象データの単語の出現頻度はcsvファイル(①)に保存
・処理対象データの単語の出現頻度Top10はグラフ化してPNGファイル(②)で保存
・形態素解析は自然言語ライブラリspaCyと日本語NLPライブラリGiNZAを使用
・解析結果をもとにワードクラウド化してPNGファイル(③)で保存
・①～③のファイル名は「"unko"+α」※コード上の"filename"で指定

##コード

```python
import spacy
nlp = spacy.load('ja_ginza')
import pandas as pd
import matplotlib.pyplot as plt
import japanize_matplotlib # グラフの日本語が文字化けしないために必要
import collections
from wordcloud import WordCloud

### GiNZA統計モデルで分析した結果をリストにして返す関数
def analyze_by_ginza(words):
    # GiNZA統計モデルに文章を渡して分析
    doc = nlp(words)
    # 分析結果をリストに格納する
    word_list = []
    chunk_list = [chunk.text for chunk in doc.noun_chunks]
    token_list = [token.lemma_ for token in doc if token.pos_ == "VERB"]
    for i in chunk_list:
        word_list.append(i)
    for j in token_list:
        word_list.append(j)
    return word_list


### 処理対象CSVファイル読み込み処理
# ファイルパスの指定
csv_read_path = "result.csv"

# ファイル読み込み。UTF-8,cp932でだめならファイルが存在ないとしてエラー
try:
    df_r = pd.read_csv(csv_read_path, encoding="utf_8_sig")
except UnicodeDecodeError:
    df_r = pd.read_csv(csv_read_path, encoding="cp932")
except FileNotFoundError:
    print('File not found.')

# 読み込んだCSVファイルの処理対象のタグ
target_categories = ["title"]

# 処理結果を保存する際のファイル名
filename = "unko"


### 形態素分析とワードクラウド化
for target in target_categories:
    total_word = [] # 文字を入れる箱を用意
    for data in df_r[target]:
        try:
            word_list = analyze_by_ginza(data)
        except Exception as e:
            # リストではない場合は単語なので、そのままリスト化
            word_list = [data]
            # 念のためエラー内容をプリント
            print(e)
        for w in word_list:
            total_word.append(w)

    print("単語数: ", len(total_word))

    # 最頻単語を順位づけ
    count = collections.Counter(total_word)

    # CSVに書き込む
    count_data = count.most_common()
    df_w = pd.DataFrame(count_data) 
    df_w.to_csv(filename+".csv", encoding="utf_8_sig")

    # グラフ化して保存する
    fig = plt.figure()
    plt.title(target)
    plt.grid(True)
    x_list = [] # グラフのx軸となるデータの箱
    y_list = [] # グラフのy軸となるデータの箱
    rank_num = 0
    for key, value in count.most_common():
        x_list.append(key)
        y_list.append(value)
        if rank_num >= 10: # Top10までグラフ化
            break
        rank_num += 1
    try:
        # 棒グラフを作成
        plt.bar(x_list, y_list)
        # グラフの保存
        fig.savefig(filename+"_graph.png")
    except Exception as e:
        print(target, " は以下の理由でデータを描画できません↓↓↓")
        print(e)

    # WordCloud を作成して保存する
    fpath = "C:/Windows/Fonts/meiryo.ttc" # メイリオ
    wordcloud = WordCloud(background_color="white",
                          width=800,
                          height=600,
                          font_path=fpath)
    wordcloud.generate(" ".join(total_word))
    wordcloud.to_file(filename+'.png')
```
GAIA: A Transfer Learning System of Object Detection that Fits Your Needs

# 物体検出向け転移学習システム：GAIA: A Transfer Learning System of Object Detection that Fits Your Needs


## 一行で

種々の条件における物体検出の転移学習に対応したシステムを提案

## 要約

近年、実応用の開発においては事前学習を伴う転移学習が重要な役割を果たしている。しかし、処理時間の制約や特殊なデータ分布など、タスクごとに大規模な事前学習を行うことは簡単ではない。本論文では、物体検出の分野に焦点を当て，GAIAと名付けたシステムを提案。GAIAは、事前に学習された強力な重みを提供し、時間の制約や指定されたデータに適合するモデルを選択可能。GAIAでは、COCO、Objects365、Open Images、Caltech、CityPersons、そして、KITTI、VOC、WiderFace、DOTA、Clipart、Comicなどのデータセットを集めたUODBで有望な結果。

## 実装

https://github.com/GAIA-vision
【Datadog】GCP から取得したログの latency を string でなく number でパースする

GCP から アクセスログを Datadog に取り込むと、単位の`s`が付いてくる。


```json
{
 （中略）
    "http": {
        "latency": "0.0000001s",
        "protocol": "HTTP/1.1",
        "status_category": "OK",
    },
 （中略）
}
```

そうすると、Datadog は String としてパースしてしまい、定量的ファセットに登録できない。
定量的ファセットに登録できないと、数値として扱えないのでなにかと不便なことが起きる。


### サポートに問い合わせてみた

Grok パーサー という機能を使って number としてパースすることができるらしい。

https://docs.datadoghq.com/ja/logs/processing/parsing/?tab=matcher

### やってみる

Datadog Logs の画面から確認できる `http.latency` を対象にする。
![latency.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619762/e9bc6cf0-18fb-1f35-e674-f223d588b185.png)

Logs のメニューから Configuration に行く。
![Security.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619762/d17d530b-4d2a-01bd-ba6a-fa77d3d80617.png)

PIPELINES を新規作成し、その中に Processor を追加する。
(私の場合は、GCP のインテグレーションを有効化しているため ① に既成 PIPELINE があった。)
![PIPELINES 3 active 0 disabled.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619762/120825ba-8493-c720-0485-e6bf45d4eeb5.png)
￼
Processor の設定はこんな感じ。
`Extract from` に、さっき Logs の画面で確認したフィールド名を書く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619762/5e14ab4f-7a1b-758c-548c-36097fba30a9.png)

新しく取り込まれたログにフィールドが追加されており、ちゃんと number としてパースされていた。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/619762/bd91f4c2-3f9a-8b12-50fd-3ef9ff505002.png)

めでてぃ。