OmniAICreator/Qiita-1.07M huggingface dataset:
プリント基板の色はなぜ緑色ですか？


#プリント基板は緑？

プリント基板って、なぜ緑なんですか？たまに赤色や黒色とかあるけど、たいてい緑ですよね。
原料から自然にああいう色になるのでしょうか、それとも何かの理由で緑にしているのでしょうか？

上記の質問はエンジニアだけでなく電子趣味の人からもよく質問されたので、ここで取り上げましょう。

基板の緑の部分は何ですか。

緑色の部分は、ソルダレジストと呼ばれ、成分は樹脂と顔料です。目的は保護、絶縁、防塵などです。具体的には、プリント基板では、両面とも銅箔付きの物です。銅は鉄、アルミ、マグネシウムに比べて、そんな活性高いではありませんが、水中で酸素と反応しやすいです。また、空気に含まれる酸素と水蒸気が常温で銅と接触することで酸化反応が発生します。それで、銅箔が酸化されたり、プリント基板の導電性もなくなります。

銅箔の酸化反応を避けるため、またPCB表面をするためもあり、ソルダーレジストの使用は始まりました。ソルダーレジストは、はんだ付けの時、不必要な部分へ付着するのを防止して。同時に、永久保護膜として、ほこりや熱、湿気などから回路パターンを保護し、絶縁性を維持します。

![レジストかける-1.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243806/84ba3f51-2290-f6fb-28fe-e29070fa10a3.jpeg)



レジストを印刷するとき、緑の顔料を加え、そうすると基板は緑色になります。 つまり、ソルダレジストの色は緑だけではなく、黄や黒、赤、紫などさまざまな色があります。




それではなぜ、黄、赤、黒、白など、カラフルなソルダレジストを使わなく、緑色だけなのでしょうか。いくつかの理由があるようです。

##理由1：緑色は目にやさしい

確かに、基板を製造する工程では、目視の検査がとても重要です。AOIと呼ばれる光学式外観検査機も使用されていますが、最終的な検査は、熟練した検査員が目視で行っています。その際に、基板がきらきらと光る黄色や赤色ですと、まぶしくて検査どころではありません。また、黒色や白色ですと、混入した異物、断線、残銅などが目立たなく、目が疲れてしまいます。そう考えると、緑色が多いのも納得できます。

##理由2：コストが安い

緑色は、汎用性が高いため、生産において広く使用されており、購入されております。また量産の時、同じ色塗料を使用して、ラインのコストを削減することができますので、緑色の塗料調達コストは他より低くなります。ですから、レジストは緑というのが最も一般的で、製造コストや納期にも有利なのです。

Seeed Studio Fusionは、ソルダレジストに緑、赤、黄、青、白、黒の6種類のカラーを提供しています。 Seeed Studio Fusionは、他の色のコストが緑色より高いにもかかわらず、Fusionはエンジニアのため、簡単なプリント基板試作できるように、追加料金なしにすべての色を提供しています。



##理由3：エラーを減らす

Gorillaの製造能力技術文書によりますと、緑の顔料はより多くの誤差を減らし、他の色より小さな面積を占めるためより高い精度を行うことができます。

![why-pcb-is-green.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243806/636a8ff0-f981-b439-5ce0-932b71870d0c.jpeg)


#黒い基板の方はレベルが高い？
　みんなもご存知だと思いますが、黒いレジストで基板製造するのは他のレジストに比べて、難易度が上がります。色々調べましたが、露光特性の違くて、難易度が上がるという観点が説得力があると考えています。、

##露光特性の違い　
レジストインク色毎に異なる顔料などの成分により、露光性も違います。露光性は良いかとうか光を吸収する能力を決めます。吸収能力は強ければ基板製造のソルダレジスト工程でインクが紫外线に照射され、一般的には、黒色の吸収能力が一番強いです。
![幻灯片2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243806/70e13d49-ec06-0880-4e26-037079a57e8d.png)
引用先:http://www.pbfree.jp/topics/c-112/
上記の二つ方法とも紫外線の照射でインクを硬化させる必要があります。露光特性の違いで、黒レジストでかけるのは他色より難しいです。例にしたら、みんなもご存知だと思いますが、ICパットの間隔にレジストをかける時、普段の緑なら0.1mmの間隔まで作れます。黄・赤なら0.12mmです。黒の場合は0.15mmにければなりません。そうしないと、間隔ルール未満のままで製造すると、レジストが剥がれて、パットに乗ってしまうかもしれません。ですので、色問わず、同じレジスト間隔で製造したら、黒い基板のコストは上がります。


[FusionPCB](https://www.fusionpcb.jp/fusion_pcb.html)では、色変えは無料ですが、でもそれなりのレジスト間隔設定も限られています。
緑：0.1mm  黄・青：0.12mm  　黒：0.1mm

![幻灯片3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243806/c9a2c44b-b922-17b9-49a6-709753e14f93.png)


![色変え無料.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/243806/fd0219e0-1e24-07af-a5a2-b28c348fc4bb.png)

黒いレジストで0.1mm間隔製造したい場合、弊社の[プレミアムサービス](https://www.fusionpcb.jp/premium-pcb-pcba.html)をご利用いただければと思います。


よろしくお願いします。
【Node.js】npm ls 時の deduped とは

> `node.js` の `npm` で `ls` を実行すると `deduped` が表示される。

```sh
/app $ npm ls minimist
mastogetter@0.0.1 /app
+-- ava@3.5.0
| `-- update-notifier@4.1.0
|   `-- latest-version@5.1.0
|     `-- package-json@6.5.0
|       `-- registry-auth-token@4.1.1
|         `-- rc@1.2.8
|           `-- minimist@1.2.5  deduped # ← これ
`-- eslint@6.8.0
  +-- file-entry-cache@5.0.1
  | `-- flat-cache@2.0.1
  |   `-- write@1.0.3
  |     `-- mkdirp@0.5.3
  |       `-- minimist@1.2.5  deduped # ← これ
  `-- mkdirp@0.5.3
    `-- minimist@1.2.5 # ← でも、これには付いてない
```

## `deduped` とは

> すでに同じ `npm` パッケージが読み込まれているので除外したという意味。

`npm ls` コマンド実行時に表示される `deduped` とは、`de-duplicated` の略です。

`de-` は、デフラグやデトックスとかの `de` で、「取り除く」「除外」などを意味します。つまり `duplication`（重複）を `reduce`（除外）したという意味です。

日本語で言うと<strong>「同じ `npm` パッケージ、及びバージョンのパッケージがインストール済みなので、インストールされなかった依存パッケージである」という意味</strong>です。つまり、容量を確保するための仕組みによるものです。

この除外処理は `npm install` などの後に自動実行されます。

しかし、パッケージのアーカイブを手動でインストールした場合など、意図せずパッケージが重複していることがあり、明示的に実行したいことがあります。<font color="darkorange">**`npm dedupe` もしくは `npm ddp` コマンドで、手動でも重複パッケージを削除できます**</font>。

そして、手動もしくは自動でコマンドが実行されると、`npm ls` 時に削除された依存パッケージに `deduped` と表示されます。

<img width="390" alt="node.js の npm で ls を実行すると deduped が表示される" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/78776/e01c05a5-2c23-7bdc-5c8e-738f73d89434.png">

「（なんだよ、<ruby>`deprecated`<rt>廃止パッケージ</rt></ruby> みたいな、やばちんなパッケージなのかと思ったじゃんか）ホッ」

## 参考文献

- [What is deduped in npm packages list?](https://stackoverflow.com/a/52860479/12102603) のコメント @ StackOverflow
- [dedupe](https://docs.npmjs.com/cli/dedupe) | CLI commands @ 公式 npm ドキュメント
- [インストール済みのパッケージ一覧を表示する](https://qiita.com/phi/items/9fcca3e7af5d25ff2653) @ Qiita
org-captureのhookを確認する

<table> 


<colgroup>
<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />

<col  class="org-left" />
</colgroup>
<thead>
<tr>
<th scope="col" class="org-left">symbol</th>
<th scope="col" class="org-left">実行されるタイミング</th>
<th scope="col" class="org-left">カレントバッファ</th>
<th scope="col" class="org-left">備考</th>
</tr>
</thead>

<tbody>
<tr>
<td class="org-left">org-capture-mode-hook</td>
<td class="org-left">org-capture-modeが有効化される前</td>
<td class="org-left">&#xa0;</td>
<td class="org-left">&#xa0;</td>
</tr>


<tr>
<td class="org-left">org-capture-prepare-finalize-hook</td>
<td class="org-left">ファイナライズが開始される直前</td>
<td class="org-left">キャプチャバッファ</td>
<td class="org-left">ナローイングされている</td>
</tr>


<tr>
<td class="org-left">org-capture-before-finalize-hook</td>
<td class="org-left">キャプチャプロセスが完了する直前</td>
<td class="org-left">キャプチャバッファ</td>
<td class="org-left">ワイディングされている</td>
</tr>


<tr>
<td class="org-left">org-capture-after-finalize-hook</td>
<td class="org-left">キャプチャプロセスが完了した直後</td>
<td class="org-left">ターゲットのバファ</td>
<td class="org-left">ウィンドウのクリーンアップに適している</td>
</tr>
</tbody>
</table>
Postgresql Function json用日付チェック関数

初投稿がpostgresql!
書き方慣れないので、見にくいかもしれません。。。


今ユーザー定義の入力帳票をjsonb型でデータを格納しています。
入力チェックを基本していません。
jsonは日付フォーマットに沿っていないと、普通に日付キャストして検索をかけようとするとエラーになります。

たとえば、すでに2020-3-99と日付型ではないデータが入っていた場合に下記のようにエラーがでます。（betweenで取得を試みる）

```
  "errorInfo": "22008",
    7,
    "ERROR:  date/time field value out of range: \"2020-3-99\"\nHINT:  Perhaps you need a different \"datestyle\" setting."
```

なので、日付形式に沿っているものだけ抽出するできるものが欲しいと考えて
調べたりした結果サブクエリ化しても大変なので、ファンクション化しようとおもいました。

ファンクション関数は作ったことがなかったんで、いろいろ突っ込みどころはあるかとおもいますが、下記で動きました

こちらを参考にしてカスタマイズさせていただきました。
https://postgresweb.com/post-166


betweenで検索用

```
CREATE OR REPLACE FUNCTION "public"."jsondatebetween"(text, date, date)
  RETURNS "pg_catalog"."bool" AS $BODY$
declare
 
	c_date		alias for $1;		--引数1:日付チェックする文字列
	s_date		alias for $2;
	e_date		alias for $3;
	
	c_execute	character varying;	--動的SQLの格納用
	d_temp 		bool;			    --一時変数
	
	BEGIN
	
	c_execute := 'SELECT date(''' || c_date || ''')  BETWEEN  date(''' || s_date || ''') and date(''' || e_date || ''')';
 
	EXECUTE c_execute INTO d_temp;
	return d_temp;
	EXCEPTION
	WHEN OTHERS THEN
	return FALSE;	

END$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
```

比較演算子で検索用

```
CREATE OR REPLACE FUNCTION "public"."jsondatecomparison"(text, varchar, date)
  RETURNS "pg_catalog"."bool" AS $BODY$
declare
 
	c_date		alias for $1;	--日付チェックする文字列
	comparison	alias for $2;	--比較文字列
	s_date		alias for $3;	--
	
	c_execute	character varying;	--SQL格納用
	d_temp 		bool;			--一時変数
	
	BEGIN
	
	c_execute := 'SELECT date(''' || c_date || ''') ' ||  comparison || '  date(''' || s_date || ''')';
 
	EXECUTE c_execute INTO d_temp;
	return d_temp;
	EXCEPTION
	WHEN OTHERS THEN
	return FALSE;	

END$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100
```

ネーミングセンスないです(;^ω^)
大文字は使えないとか見ました。
使う時は、ちゃんとキャストするなどしてつかわないとエラーがでてきますので気を付けてください（ちょっとハマった）
redis-railsのセッション有効期限の挙動を確かめて遊ぶ

# redis-railsのセッション有効期限の挙動をチェック
ローカルでサイトにアクセスすることで3ヶ月の期限付きセッションデータが生成される設定をしている。

redisを起動

```bash:command
redis-cli
```

DB1を選択する（設定によって変わります）

```redis-cli:redis-commands
select 1
```

サイトにアクセス、キー一覧を取得。
＝＞1件のデータが作られている

7889224とは秒数のことで、有効期限である。
![77042128-7e4ff380-69fe-11ea-86d9-fb4b7b14e5e6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/548e9187-e744-63d0-564e-8bd3d91c8d30.png)


### 【有効期限を無期限にするとどうなる？】
再度サイトにアクセス

* データは1件しかないので、セッションは新規に作られた訳ではない
* 有効期限が無期限(-1)になり、過去のセッション情報が更新されたことがわかる

![77042103-75f7b880-69fe-11ea-81d8-c4e4d54a47c0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/770b2cc0-8c58-6aaa-2d56-095dd748ade9.png)

### 【有効期限を60秒に変更してみた】
再度変更後サイトにアクセス


* 先ほど、無期限に設定したセッションデータの有効期限が60秒に更新された
* 徐々に秒数のカウントが減っていき、最後は-2（データ見つからない）になりました。

![77042331-d850b900-69fe-11ea-9164-a820664fc4c5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/ead4a4df-a4f1-c939-4dd1-a760e12020f3.png)


## 複数のユーザーがいる場合の挙動はどうなる？
プライベートブラウザと通常のブラウザの2種類を用いて、2種類のセッションを作成した


![77042611-54e39780-69ff-11ea-860a-e77a1fd9c037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/0518eaf3-5261-fb3b-fa65-efe13559954b.png)

1つ目も2つ目も、有効期限は60ヶ月に設定している
![77042805-ad1a9980-69ff-11ea-84cc-791ff88a6eb8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/33208bbf-5cdc-2de8-dfed-1ecaef0c639e.png)

### 【有効期限を60秒に変更し片方だけサイトにアクセスする】
サイトにアクセスしたセッションは有効期限が更新され、60秒後には消えることになった。
アクセスしていない方は残り続けている。

画像では残り49秒で消えると表示されている
![77042887-ce7b8580-69ff-11ea-85df-4cd428e018ce.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/bc997666-db09-7807-278b-e7722fc4376e.png)


片方のセッションは60秒が経過し、削除されました

![77042984-f9fe7000-69ff-11ea-857e-3ba23a2f6d10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/69647/6e7ed70b-74f3-462d-d5be-5e0cd4d40844.png)
PHPで現在時刻出したら8時間ずれてたお話

## はじめに
~~Unity勉強し始めたばっかですが~~ 最近PHPの勉強し始めました。
その中でつまった部分をQiitaに書き残して、これからPHP始める人たちの助けになれたらなと思ってます。


## 現在時刻を表示してみる

dateを使って現在時刻を表示するプログラムを作成してみます。
※フォーマットは以下サイトを参考につけました
https://www.php.net/manual/ja/function.date.php

```php:date.php
<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="UTF-8">
		<title>現在日付を出す</title>
	</head>
	<body>
		<?php
		print("今は".date('H')."時".date('i')."分");
		?>
	</body>
</html>
```

現在時刻が15時50分なのになぜか「今は07時50分」と表示される・・・。

##php.iniのdate.timezone
dateはphp.iniの中のdate.timezoneをもとに現在時間を取得しているそうです。
値を確認したら以下の通りになってました。

```ini:php.ini
date.timezone=Europe/Berlin
```

ベルリン＼(^o^)／

インストールしてから設定を変更した記憶が無いのでデフォルトがベルリン (ドイツ) になっているっぽい。
なので日本に書き換えます。

```ini:php.ini
date.timezone=Asia/Tokyo
```

書き換えたらapacheを再起動して再表示したら正しい時刻が取れました！

これからもつまったとこがあったらできるだけ記事にしていこうと思います。
Active Storageで画像サイズ(縦幅、横幅)を取得する

# モデル

```ruby
class Foo < ApplicationRecord
  has_one_attached :image
end
```

# 取得

```ruby
f = Foo.first

f.image.metadata[:height] # 縦幅
f.image.metadata[:width]  # 横幅
```

# 注意点

`metadata`への登録は非同期で行われるため、レコード保存直後はデータが入っていない可能性があります。[参考](https://edgeapi.rubyonrails.org/classes/ActiveStorage/Blob/Analyzable.html)。

- analyze前

```
{"identified"=>true}
```
- analyze後

```
{"identified"=>true, "width"=>320, "height"=>150, "analyzed"=>true}
```
CSSカウンターで自動ナンバリング

###CSSカウンターとは
文書内の位置に基づいてコンテンツの表示方法を調整することができます。
例えば、ウェブページ内の見出し番号を自動的に振るのに使ったりします。カウンターは本質的に、 CSS が管理する変数であり、 CSS の規則によって増加し、何回使用されたかを追跡するものです。
出典 : https://developer.mozilla.org/ja/docs/Web/Guide/CSS/Counters

ランキングや目次などで「ナンバリングしたい」って時に、CSSカウンターを使うとよい感じにできます:thumbsup:
※以下、pugとstylusで書いています

```
ul
  - for(var x = 0; x < 5; x++)
    li sample
```

```
li
  list-style: none
  counter-increment: num
  &:before
    content: counter(num) "."
```

![スクリーンショット1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174180/c2d6d43e-8751-4716-0fa8-a27b56589d74.png)



**counter-increment** : 要素の連番（カウンタ）の値を進める。値にカウンタ名を定義することでページ内にその要素が現れるたびに、定義したカウンタの値が進められます。
プロパティを適用する要素に:beforeや:after擬似要素をつけ、contentプロパティでカウンタ名を指定することで、要素の直前または直後にカウンタの値を挿入することができます。

####数字形式の表示方法の変更
```
content: counter(num, 表示形式)
```

| decimal              |       数字（初期値）          | 
|:---------------------|--------------------------:|
| **lower-roman**      |ローマ数字（小文字）（例：ⅰ、ⅱ、ⅲ）   |
| **upper-roman**      | ローマ数字（大文字）（例：Ⅰ、Ⅱ、Ⅲ）  |
| **lower-alpha**      |アルファベット（小文字）（例：a、b、c） |
| **cjk-ideographic**  |漢数字（例：一、二、三）          |
| **hiragana**         |ひらがな（例：あ、い、う）          |
| **katakana**         |カタカナ（例：ア、イ、ウ）          |
| **hiragana-iroha**   |いろは順（例：い、ろ、は）         |
| **katakana-iroha**   |イロハ順（例：イ、ロ、ハ）         |
※cjk-ideographicから下はIE非対応

####カウンターの前後に文字列を挿入する####
```
content: "第" counter(num) "章 "
```

![スクリーンショット2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174180/6ad9c124-a7a5-2ec3-9149-fa6d1f562f94.png)



####counters() 関数
**counters() 関数**を使って入れ子になったカウンターの階層間に文字列を挿入することができます。
その際、子要素に**counter-reset**プロパティでカウンタの値をリセットするのがポイント。

```
ul.parent
  - for(var x = 0; x < 3; x++)
    li sample
      ul.children
        - for(var y = 0; y < 2; y++)
          li test
```

```
li
  list-style: none
  counter-increment: num
.parent
  li
    &:before
      content: counter(num) "."  
.children
  counter-reset: num
  li
    &:before
      content: "第" counters(num, "-") "章 "
```
![スクリーンショット3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/174180/f81a11f8-369b-9edd-4271-dec668221263.png)


（編集途中で下書き保存したまま放置していた記事をようやく書き上げましたw）
Nuxt.js: i18nで多言語化 (localeファイルを分割する)

多言語化案件に携わることになり、Nuxt.js + i18nの導入を経験できたので備忘録的に残します。

ドキュメント
https://nuxt-community.github.io/nuxt-i18n/

## 要件

今回の要件は以下
1. locale: `en`, `ja` の2言語
2. url: `/en`, `/ja` ( /へのアクセスはcookie制御、デフォルト `/en` )
3. localeファイルはpage(component)ごとに管理
4. メッセージはテンプレート方式で引数を与えられるようにする

# 導入手順

1. `nuxt-i18n` のインストール
1. `nuxt-i18n.config.js` の作成
1. 言語ファイルの作成
1. `nuxt.config.js` の設定
1. Template側での呼び出し

## `nuxt-i18n` のインストール

これはドキュメントの通り。

```bash
yarn add nuxt-i18n
```

or

```bash
npm i -S nuxt-i18n
```

## `nuxt-i18n.config.js` の作成

今回は、 ページごとにメッセージファイルを管理したいので、`locales[].file` ではなく、 `vueI18n.message` を使用します。

`nuxt-i18n.config.js`

```javascript
import messages from './locales/message' <- これは次項で説明

export default {
  strategy: 'prefix',
  locales: [
    { code: 'en', iso: 'en_US' }, <- fileプロパティは使用しない
    { code: 'ja', iso: 'ja_JP' }
  ],
  defaultLocale: 'en',
  vueI18n: {
    fallbackLocale: 'en',
    messages
  },
  rootRedirect: 'en',
  detectBrowserLanguage: {
    useCookie: true,
    cookieKey: 'i18n_locale'
  }
}
```

## 言語ファイルの作成

要件#3のページごとにlocaleファイルを分けるために、このようなディレクトリ構造で管理します。
各localeごとにページ単位のjsファイルを用意して、message.jsでそれらをがっちんこしてexport。
それを `nuxt-i18n.config.js` でimport。


```bash
./locales
├── en
│   ├── top.js
│   └── sub.js
├── ja
│   ├── top.js
│   └── sub.js
└── message.js
```

./locales/ja/top.js

```javascript
export default {
    top_title: 'TOPページへようこそ',
    top_title_service: 'サービス概要',
    top_label_service: 'サービス {index}: {name}',
    top_service_price: '{0} 円',
    top_service_description: 'こんなサービスです。詳しくは<a herf="{0}">こちら</a>までどうぞ！'
}
```

./locales/en/top.js

```javascript
export default {
    top_title: 'Welcome to TOP page',
    top_title_service: 'Services'
    top_label_service: 'Service {index}: {name}',
    top_service_price: 'USD {0}',
    top_service_description: 'This is the service description. For more information, please reach out ot us <a herf="{0}">here</a>.'
}
```

./locales/message.js

```javascript
import localeENTop from './en/top'
import localeENSub from './en/sub'

import localeJATop from './ja/top'
import localeJASub from './ja/sub'

export default {
  en: {
    ...localeENTop,
    ...localeENASub
  },
  ja: {
    ...localeJATop,
    ...localeJASub
  }
}
```

これでページが量産されても管理しやすくなります。

## `nuxt.config.js` の設定

作成した `i18n.config.js` を利用して、`nuxt.config.js` のi18n設定を行います。

```javascript
import i18n from './nuxt-i18n.config'

export default {
  ...
  modules: [
    ...
    [ 'nuxt-i18n, i18n ]
  ]
}
```

## Template側での呼び出し

```javascript
<template>
  <div>
    <h2>{{ $t('top_title') }}</h2>

    <section>
      <h3>{{ $t('top_title_service') }}</h3>
      <div v-for="(item, i) in services" :key="item.id">
        <h4>{{ $t('top_label_service', { index: i + 1, name: item.name }) }}<h4>
        ...
        <p>{{ $t('top_service_price', [item.price.toLocaleString()]) }}</p>
        <p v-html="$t('top_service_description', [localePath({ path: '/contact' })])" />
      </div>
    </section>
  </div>
</template>
...
```

Cookie制御とか自前で実装しようとしていたけど、これ使えばバッチリでした。
magnific-popupで連続ポップアップ表示

※自分用メモ

■概要
最初にログインボーナスのポップアップ、次に複数件のお知らせのポップアップ表示。
・指定時間経過後、次のお知らせポップアップ表示
・閉じるボタン押下で次のお知らせポップアップ表示

Laravel+jQuery

```
@if( isset($login_bonus_flg) )
<div id="loginbonus" class="white-popup">
	<h1>ログインボーナス</h1>
	<p>{{ $login_bonus_msg }}</p>
</div>
@endif
@if( count($userinfo) > 0 )
	@foreach($userinfo as $index => $lines)
		<div id="userinfo{{ $index }}" class="white-popup disptime_{{ $lines->disptime }}">
			{!! $lines->userinfo !!}
		</div>
	@endforeach

@endif


<script async src="/js/jquery.magnific-popup.min.js"></script>
<script>
$(window).load(function(){
    var open_flg = '{{ $login_bonus_flg }}';
    if( open_flg ){
        var timerid;

        /*
         * ログインボーナスポップアップ表示のあとにお知らせポップアップ表示
         */
        $.magnificPopup.open({
            items:[{
                src:'#loginbonus',
                type: 'inline',
                modal: true
            }],
            callbacks:{
                close:function(){
                    clearTimeout(timerid);

                    /*
                     * class名から表示時間取得
                     */
                    var disptime = eval($('#userinfo0').attr('class').replace(/.+disptime_(\d+)/, "$1")) * 1000;
                    openPopup(0, disptime);
                }
            }
        });

        /*
         * 指定時間経過後、ポップアップを閉じる
         */
        timerid = setTimeout(function(){
            $.magnificPopup.close();
        }, {{ $login_bonus_disptime }});
    }
});

/*
 * 次のお知らせポップアップの表示
 */
function openPopup(id, closetime){
    if( document.getElementById('userinfo'+id) != null ){
        var timerid;

        /*
         * setTimeoutを使用することで前回のポップアップを終了させ、次のポップアップ表示に切り替える
　　　　　*/
        setTimeout(function(){
            $.magnificPopup.open({
                items:[{
                    src:'#userinfo'+id,
                    type: 'inline',
                    modal: true
                }],
                callbacks:{
                    close:function(){
                        clearTimeout(timerid);

                        /*
                         * 次のIDの表示のためIDをインクリメント
                         */
                        id++;

                        /*
                         * class名から表示時間取得
                         */
                        if( document.getElementById('userinfo'+id) != null ){
                            var disptime = eval($('#userinfo'+id).attr('class').replace(/.+disptime_(\d+)/, "$1")) * 1000;
                            openPopup(id, disptime);
                        }
                    }
                }
            });

            /*
             * 指定時間経過後、ポップアップを閉じる
             */
            timerid = setTimeout(function(){
	        $.magnificPopup.close();
            }, closetime);

        }, 1);
    }
}
</script>
```
Pythonで毎日AtCoder #10

### はじめに
[前回](https://qiita.com/taxfree_python/items/ebc42c3888ccd0e8da42)
10日目です。

### #10
[問題](https://atcoder.jp/contests/abc106/tasks/abc106_c)
2WA
**考えたこと**
まず、文字列がどのように増えていくかを考えると、文字nの長さは
$n^0,n^1,n^2,...........n^{5*10^{15}}$になります。すると末項はkの最大値よりも大きくなるので、kの範囲でindexが一番小さい1以外の文字が答えになります。ですので、forで1以外の要素を探しています。

```python
s = str(input())
k = int(input())

for i in range(min(len(s),k)):
    if s[i] != '1':
        print(s[i])
        quit()

print('1')
```

### まとめ
次のAGCもがんばるぞい。では、また
感染症流行過程の数理モデルをPythonで解く

**注意！この記事はなんとなくやってみた以上の情報を含みません。**

# 感染症数理モデル
昨今のCOVID19事情を受けて色々感染症の数理モデルの話は出ていると思うわけですが、それをPythonのodeintで解いて、そのままmatplotlibで可視化してみよう、という事です。
くどいようですがこの記事のなんかを適当に実装した結果からCOVID19に関して何かのお気持ちを表明しては駄目だぞ。

で、解くのは一番簡単なSIRモデルとしまして、

```math
\begin{align}
\frac{\mathrm{d} S}{\mathrm{d} t} & = - \beta I S\\
\frac{\mathrm{d} I}{\mathrm{d} t} & = \beta I S - \gamma I\\
\frac{\mathrm{d} R}{\mathrm{d} t} & = \gamma I
\end{align}
```
としておきます。
$\beta$は感染率(/(人x時間))で、病気にかかった人間ひとりが単位時間あたりに感染す事のできるまだ伝染していない人の人数、$\gamma$は治癒率(/時間)で、治癒までにかかる時間の逆数です。
$S$はまだ感染した事がなく、かつ感染能力も無い人間の数、$I$は感染しておりかつ他人に感染させる能力をもつ人間の数、$R$は隔離・治癒・死亡などで感染しているあるいはいたが他人に感染させる能力を失った人間の数です。

# Python code
面倒くさいので特に解説とかは無しのコードベタ貼り。

```python
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
from matplotlib.widgets import Slider, Button

def solve(value, t, foi, rr):
	# fio = force of infection (beta)
	# rr = recovery rate
	S, I, R = value
	dSdt = - foi * I * S
	dIdt = foi * I * S - rr * I
	dRdt = rr * I
	return [dSdt, dIdt, dRdt]


span = 100
t = np.linspace(0, span, 256)
initial_value = [0.9, 0.1, 0] # initial values for S, I, R
solution = odeint(solve, initial_value, t, args = (0.5, 0.5))

fig, ax = plt.subplots(figsize=(12, 6))
plt.xlim(0, span)
plt.ylim(0, 1)
plt.subplots_adjust(bottom = 0.2)

data_S, = plt.plot(t, solution[:, 0], "blue", label = "Susceptible")
data_I, = plt.plot(t, solution[:, 1], "red", label = "Infectious")
data_R, = plt.plot(t, solution[:, 2], "orange", label = "Removed")

plt.legend(loc = "best")

rr_slider = Slider(plt.axes([0.2, 0.02, 0.65, 0.02]), "recovery rate", 0, 1, valinit = 0.5, valstep = 0.1)
foi_slider = Slider(plt.axes([0.2, 0.05, 0.65, 0.02]), "force of inf.", 0, 1, valinit = 0.5, valstep = 0.1)

def update(val):
	rr = rr_slider.val
	foi = foi_slider.val
	solution = odeint(solve, initial_value, t, args=(foi, rr))
	data_S.set_ydata(solution[:, 0])
	data_I.set_ydata(solution[:, 1])
	data_R.set_ydata(solution[:, 2])
	fig.canvas.draw_idle()

rr_slider.on_changed(update)
foi_slider.on_changed(update)

plt.show()
```

# 実行結果
<img width="1051" alt="スクリーンショット 2020-03-19 16.18.58.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44457/0854a0d7-f7be-f479-d736-2039588d410f.png">
こんなのが出てくるんじゃないかなと思います。
ちなみに感染率と治癒率はどの程度の値が正しいのかよくわからなかったので、適当につまみを作って値をいじれるようにしておいたので、遊んでみてください。

# で
まあ遊んでみてください。
あなたもパラメーターをうねうねさせながら微分方程式を解きたくなったらぜひパクってください。
VSCode1.43.0以降では即時関数内でtry-catchを使うとreturnが正しく解釈されない（1.46.0で解消）

この記事で書いていたバグは、1.46.0で解消しました。

---
VSCode（1.43.0と1.43.1で確認）では、以下のコードでconsole.logの部分が「到達できないコード」として判定されてしまいます。

```JavaScript
const message = (() => {
    try {
        /* エラーが発生しそうな処理 */
        return "success";
    } catch (e) {
        return "error:" + e;
    }
})();

console.log("message = " + message);
```

<br/>しかし、Node.js（12.16.1）で上記のコードを実行すると、console.logはちゃんと実行されます。

```
message = success
```

<br/>即時関数の中でtry-catchは使うべきではないのでしょうか。
そもそもこういった処理を即時関数化すべきではないのかも知れません。
ただ、VSCode 1.42.1 以前はちゃんとconsole.logが到達可能と判定されていましたし、よく分かりません・・・。

VSCodeのissueに報告したいんですが英語苦手なんですよね。
直るまでは1.42.1を使うことにします。

## 追伸
冒頭にも書きましたが、1.46.0（May 2020）でバグが解消していることを確認しました。
4つ以上のDecorationImageをRowの中に入れるとリビルドが止まらなくなった時にみる記事

`Row` -> `ListView(scrollDirection: Axis.horizontal`
にすればいいよ！

# はじめに

タイトルのような現象が起こりました。
色々な記事を探して、解決方法を探してみましたが結局解決方法は見当たらず、今回の解決方法は `Row` で包んでいたWidgetを `ListView(scrollDirection: Axis.horizontal`になおすことでなおりましたが根本解決ではないと思います。

詳しい方がいれば意見を伺ってみたいです。

↓Android Studioで確認できるリビルドの様子。これが止まらなかった。

![スクリーンショット 2020-03-19 16.09.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190157/cd982fea-93ce-7646-a6f6-caa291fbf726.png)

# 試したこと
一応記載しておきます。
ここでの理想動作とは、画面の描画が完了後リビルドが止まり、安定している状態を指します。


- 三つ以下にする→理想動作
- DecorationImageではなく普通にImage.memoryで描画する→理想動作
- 五つ以上にする→異常動作
- Stateless, Statefulの両方を試す→それまでに従う
- precacheImageを使う→それまでに従う
FlutterでUnimplemented handling of missing static targetのエラー



## 発生した問題

Flutterで以下のエラーが出て、進行不能になった。
コードを見返しても特に問題はなさそう。

```
Unimplemented handling of missing static target
```

## 環境

- macOS Catalina 10.15.1
- Android Studio 3.6.1
- Flutter 1.12.13


## 結論

プロジェクトを再コンパイル(または以下のコマンドを入力)するだけでいけました。

```
flutter clean
flutter run
```

## 原因

`main.dart` のMyAppクラスを変更したことが原因でした。

ホットリロードが効くおかげで気づきにくいが、比較的大きな変更をしたときには再コンパイルを試していると良さそう。


## 参考記事

https://stackoverflow.com/questions/58055330/flutter-unimplemented-handling-of-missing-static-target
CentOS上にGitBucketをデプロイした時にはまったポイント

# 背景
仕事でのソース管理にGitBucketを使用しようと思い、centos８にデプロイしようとしたところ、所々で躓いたので解決策のメモ

## gitbucket.warがデプロイされない
gitbucket.warの権限をtomcatユーザに変えずにwebappsの下においてしまい、デプロイされないなーと悩んでしまった

## gitbucketにアクセスできない（ホームディレクトリの作成）
http://localhost:8080/gitbucket/
を入力したところ、アクセスできなかった
tomcatユーザのホームディレクトリが/rootになっていたので
/home/tomcatディレクトリを作成して解消
DF.INIでのコマンド登録

# DF.INIでのコマンド登録

CUIのファイラDF.exeをずっと愛用しています．
MS-DOS時代はFD.exeの愛用者だったので．
ちなみにLinuxではfd-cloneが手放せません．

DFはコマンド登録やディレクトリ登録ができて，ジャンプしたり選択ファイルに対して特定のコマンドを実行したりできます．

それにはDF.INIファイルの中にコマンドやディレクトリを登録します．

DF.INIでコマンド実行させるのは，こんな感じ．

```
[CMD]
ペイント="C:\PROGRA~1\ACCES~1\PAINT.EXE $C$R"
IE="C:\Program Files\Internet Explorer\IEXPLORE.EXE  $P$R"
DF設定="C:\WINDOWS\NOTEPAD.EXE" "C:\Program Files\DF\DF.INI $R"
```

** ※ちょっとコツ：** コマンド選択時，登録コマンド名の頭文字のキーを押すとそのコマンドを探せます．
上のメニューだと，"i"を押すとIEの行にジャンプします．
ですので，コマンド名は半角で始めましょう．全角で始めてしまうとジャンプが機能しません．たとえば上の「ペイント」だと，「p.ペイント」とかしておくと，"p"で飛びます．

## マクロ
設定値には以下の各種マクロが使用できます。上の例で"$C$R""$P$R"などです．
+ 小文字を使うと8.3形式の短いファイル名になります。
+ $Tを付けると反対側のウィンドウのパスやファイル名を使います。

```
###通常ウィンドウ

$C	カーソル位置のファイル名になります。
$c	カーソル位置のDOSの8.3形式のファイル名になります。
$F	カーソル位置のファイル名をフルパスで表現したものになります。
$f	カーソル位置のファイル名をDOSの8.3形式でフルパス表現したものになります。
$P	ディレクトリ名になります。最後の\はつきません。ルートディレクトリの場合、「C:」のようになるので注意が必要です。
$p	DOSの8.3形式のディレクトリ名になります。最後の\はつきません。ルートディレクトリの場合、「C:」のようになります。
$X	カーソル位置のファイル名になります。ただし、拡張子がつきません。
$x	カーソル位置のDOSファイル名になります。ただし、拡張子がつきません。
```

###反対側ウィンドウ

```
$Tから始めると反対側ウィンドウのファイル名を展開します。$TFは反対側のウィンドウの$Fと同じ意味になります。
$Tは$TPの省略形として使えます。

$T	反対側のウィンドウのディレクトリになります。最後の\はつきません。シングルウィンドウモードの時には$Pと同じです。
$TC	反対側ウィンドウで表示しているカーソル位置のファイル名になります。
$Tc	反対側ウィンドウで表示しているカーソル位置のDOSの8.3形式のファイル名になります。
$TF	反対側ウィンドウで表示しているカーソル位置のファイル名をフルパスで表現したものになります。
$Tf	反対側ウィンドウで表示しているカーソル位置のファイル名をDOSの8.3形式でフルパス表現したものになります。
$TP	反対側ウィンドウで表示しているディレクトリ名になります。最後の\はつきません。ルートディレクトリの場合、「C:」のようになるので注意が必要です。
$Tp	反対側ウィンドウで表示しているDOSの8.3形式のディレクトリ名になります。最後の\はつきません。ルートディレクトリの場合、「C:」のようになります。
```

###  選択ファイル

```
$Mは選択したファイルに展開されます。

$MC	選択したファイル名を展開します。それぞれのファイル名はダブルクォーテーションでくくられます。
$Mc	選択したファイル名をDOSの8.3形式で展開します。ダブルクォーテーションはつけません。
$MF	選択したファイルのフルパスを展開します。それぞれのファイル名はダブルクォーテーションでくくられます。
$Mf	選択したファイルのフルパスをDOSの8.3形式で展開します。ダブルクォーテーションはつけません。
```

### その他

```
$R	ダイアログにてコマンドを選択した後、即座に実行します。これがなければ選択後コマンドラインが表示されます。
$$	$になります。
$D	DFの存在するドライブに展開されます。X:\APPS\DF\DF.EXEを実行している場合にはX:に展開されます。
```

## DFのヘルプファイルについて

DFのヘルプファイルは旧世代のものなので，Winhelp32を自分で入れないと読めません．

ここら↓を参考に．
[Windows10用WinHlp32\.exeインストールバッチファイル \- DoldoWorkz](https://moondoldo.com/DoldoWorkz/?Windows10%E7%94%A8WinHlp32.exe%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB)

hlpファイルの関連付けなどをバッチファイルでやってくれるって寸法です．

• これが更新プログラム↓
  [Download Windows 8\.1 for x64\-Based Systems 用更新プログラム \(KB917607\) from Official Microsoft Download Center](https://www.microsoft.com/ja-JP/download/details.aspx?id=47671)

• これが上のサイトで配布するバッチファイル
   [Windows10用WinHlp32\.exeインストールバッチファイル \- DoldoWorkz](https://moondoldo.com/DoldoWorkz/?plugin=attach&refer=Windows10%E7%94%A8WinHlp32.exe%E3%82%A4%E3%83%B3%E3%82%B9%E3%83%88%E3%83%BC%E3%83%AB%E3%83%90%E3%83%83%E3%83%81%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB&openfile=winhlp32_Install_Windows10_ja-jp_x86x64_300.zip)

• 同じフォルダにファィルとバッチファイルを置き，「管理者権限で実行」すればインストールしてくれます．
NGSI-LDまとめ

# NGSIとは

もともとは日本で策定されたネットワークAPIの規格
異なるアプリケーション間で連携するためのインタフェース
これが、欧州の官民連携プロジェクトで標準規格として定めれられたFIWAREにてNGSIをベースにされたことから、世界的に標準としての時流が起こりつつある。

# NGSIのタイプ
以上の3つのバージョンが2020年1月現在、公開されている。
- NGSI v1
- NGSI v2
- NGSI-LD

# 簡単な差分

### NGSI v1
OMA-NGSIオリジナルのNGSI RESTfulバインディング

## NGSI v2
v1から改良され、単純化されたOMA-NGSIのバインディング

## NGSI-LD
v2までのメタデータ記載は不要になった。
EntityとEntityを関連付けるRelationshipが表層化された。
[NEW!]GeoProperty(v2では、geo:json)
[NEW!]TemporalProperty(v2ではDatetime)

## モデル上での違い

NGSI v2
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159589/8b909a58-97cd-78f9-cda9-be1737e4866b.png)

NGSI-LD
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159589/26cd5c54-ec54-b8e9-3f5a-6d9828da3803.png)

## NGSI-LDモデル詳細
基本的には、
Entity1-Relationship-Entity2
Entity-Property-Value
Relationship-Property-Value
Property-Property-Value
の法則でInformation Modelを形成していく。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159589/ee2f7306-bc13-64d7-7434-23acef5d9885.png)

## NGSI-LD JSONモデル詳細
Entity単位で形成される。
Entity内にRelationship、Property、Valueを記載する。
最後尾の@contextでNGSI-LDであることを定義
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/159589/dd69fae7-74d8-76ba-e518-197f1a5ba823.png)

## 違いまとめ
NGSI-LDは
・PropertyGraphModelである→v2は、Entity-Attribute-metadata構造であり、データ同士のLinkは意識しない(表層化しない)
・EntityIDがURI(URL,URN)であること→v2はentity内のid属性値
・metadata dictはなくなり、メタデータ系はPropertyのネスト構造で表現されている。
・ただし、いくつかのメタデータはある(unitCodeやobservedAtなど)
・Entity間を結ぶためのrelationshipという属性がある。(object間で使われる)
・Geospatial(地理空間)はGeopropertyという属性で扱われる
・属性の型はProperty,Relationship,GeoPropertyでのみ扱われる
・@contextで一意なURLを作ることができる。
・RESTfulな定義はv2とほほ同じ



### 参考資料
https://fiware-tutorials.letsfiware.jp/Linked-Data/
https://fiware-datamodels.readthedocs.io/en/latest/ngsi-ld_faq/index.html#q-what-are-the-main-essential-differences-between-ngsi-v2-and-ngsi-ld
LT用: 20200319

![スライド1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/1597a570-7bc6-ddff-1e5b-e51f7ae1f47c.png)
![スライド2.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/e6203c3f-a074-6cb3-fdbf-06e4fedbddd0.png)
![スライド3.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/c62afc9f-4c86-b711-8394-35d4d41b157c.png)
![スライド4.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/d3f9dea7-c66c-c42a-9c13-2c6596fe50db.png)
![スライド5.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/f57752e4-d077-ce09-5a51-10c7d6fceb14.png)
![スライド6.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/a6474a73-8745-4f8d-e8ff-b37ebb701e58.png)
![スライド7.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/33af19d0-17db-3837-dae8-f7af9c1cbb46.png)
![スライド8.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/4b067452-7105-ed92-7a37-2c958719938c.png)
![スライド9.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/ff8a98e7-cec0-34ae-9224-20fda5dd33d9.png)
![スライド10.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/920ccebb-4ab5-d605-2009-8013bd08e70e.png)
![スライド11.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/91819f16-b4aa-89f1-7a95-b001851937e5.png)
![スライド12.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/99231e34-8de7-41a3-d695-2b83ee9ce857.png)
![スライド13.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/be786c2f-0d2b-c31b-32c7-6e82405222b0.png)
![スライド14.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/ad45a9e9-b7d8-389e-83a2-9388ad5d4f8b.png)
![スライド15.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/565bc70e-6bd5-a51e-d1f3-18baf8ce9409.png)
![スライド16.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/e2a02493-6ea1-b7b6-2cd5-8015f0131ef0.png)
![スライド17.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/69d97e4a-c911-6bac-0193-07203d5d4b29.png)
![スライド18.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/7d5e3869-334a-3f2f-0969-01fb66cead70.png)
![スライド19.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/420547/7f59e894-3f6f-ba98-2c19-1a6e2fae8a1f.png)
[dart] mapでもindexがほしい - asMapは便利 -

# この記事は
配列をmapで展開したときに、本来は拾ってこれない要素番号(index)をどうにか取得しようとした結果、foreachとasMap()を使えば取得できました。という記事です。


# コード
```
List _sample = ['a','b','c'];

   _sample.asMap().forEach(
    (index, value) => print("$index : $value")
  );
```

### asMap()について
リストをマップ化できます。
`_sample = ['a','b','c']` を`asMap()`することで、`{0: a, 1: b, 2: c}`に変化します。

### mapの代わりにforEachを使う
indexを取得するためにmapの代わりにforEachを使います。


# 参考
[Flutter DartでIndex付きのmapを簡単に行うExtension](https://qiita.com/_mogaming/items/0f6dce3695960bb681e4)
[Enumerate or map through a list with index and value in Dart
](https://stackoverflow.com/questions/54898767/enumerate-or-map-through-a-list-with-index-and-value-in-dart/54899730)
マイコン（ESP）の技適について調べてみた

WiFiやBluetoothなど、無線機能を持ったマイコンモジュールを自作する場合、ベースとなるモジュールに技適がついていてほしいものです。実際に、ESP-WROOM-02などは商品自体に技適マークがついてますが、一部ついていないものも。そんな時どうすればいいのか調べてみました。


#今回の調査対象
今回調査したのは、深センのAi-Thinker Technology社が作っている「ESP-12F」という製品です。この商品は、基板製造を請け負ってくれるSeeedStudioのオープンライブラリにもある製品で、Seeedに発注して基板を作る場合に重宝する商品です。しかしこれは、見ての通り商品に技適マークがありません。
![ESP-12F](https://sc02.alicdn.com/kf/H77433e38bf234af98ed4124fd39fa733r.jpg)

#技適が取れているかのチェック
技適がとれているかどうかは、総務省の電波利用ホームページから確認できます。
https://www.tele.soumu.go.jp/giteki/SearchServlet?pageID=jk01&NUM=&NAM=thinker&FOM=wifi&PC=&YAR_FROM=&MON_FROM=&DAY_FROM=&YAR_TO=&MON_TO=&DAY_TO=&RAD=00-00-00-00&TEC=1&TEC=2&TEC=3&TEC=4&TEC=5&TEC=6&TEC=7&SK=0&DC=0&SC=1&as_fid=567625e6482b664c4c26463f96780d1d6345986e#searchlist

こちらで確認したところ、2019年9月に「相互承認(MRA)による工事設計認証」が取得されていることがわかりました。したがって、技適は取得済みの製品になります。
<img width="697" alt="image.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/164437/e3d55768-8f92-b0ae-85f1-f8efced11455.png">

#技適の表示方法
技適に表示方法について、こちらに記載があります。
http://www.jate.or.jp/jp/radio/about-r.shtml

+ 工事設計認証の場合、適合表示は工事設計認証を受けた者(認証取扱業者)が製造後に付すことになります。
+ 適合表示無線設備を組込んだ製品の取扱い業者は、製品に組込まれた適合表示無線設備に付されている表示と同一の表示を上記の方法により当該製品に付することができます。
+ 適合表示の様式は特定無線設備の技術基準適合証明等に関する規則の様式第7号により、適合マークに記号Rマーク(補助マーク)及び技術基準適合証明番号又は工事設計認証番号を付加したものとされています。 

適合表示の表示方法については、以下のように書かれています。

1. <b>無線設備の見やすい箇所</b>に付す方法
2. 体内に植え込まれた状態等で使用される特定無線設備、その他の当該表示を付すことが困難又は不合理である特定無線設備については、当該特定無線設備(<b>取扱説明書及び包装又は容器を含む</b>)の見やすい箇所
3. 特定無線設備に電磁的方法により記録し、当該表示を特定の操作によつて当該特定無線設備の<b>映像面に直ちに明瞭な状態で表示</b>することができるようにする方法
4. 特定無線設備に電磁的方法により記録し、当該表示を特定の操作によつて<b>接続した製品の映像面に直ちに明瞭な状態で表示</b>することができるようにする方法

つまり、製品本体に記載するか、例えば小さすぎて表示できない場合などは、取説やパッケージの見やすい箇所に貼る。またはディスプレイなどを持つ/接続できる機器の場合は、そこで表示できるようにすればよい、ということですね。


#念のため、総合通信局に聞いてみた

Q.技適が取得済みのマイコンのプログラムを書き換えて使っていいのか？

A.
電波の質に影響を与えないのであれば、認証を取り直す必要はないが、もとのモジュールから電波の質に影響がないかどうかは、メーカーに確認するなど、十分な確認をすること。

Q.技適が取得済みなのに表示されていないマイコンを使って基板を作ったらどうなるのか？

A.
技適マークは基本的に製品自体に表示をするのが大原則だが、モジュールが小さいなどで読み取れない場合は、取説や包装に表示する措置が認められている。既存モジュールを組み込んだ別製品を作る場合は、そうした措置をすれば問題ない。
超かんたんなWordPressサイト公開（EasyWP/SSL対応）

# モチベーション
qiita含め技術系のサイトでは、ギークな話が多いんだけど、

`「で、結局どうやってやんの？」`

みたいなことが多くて、意外とスタックする。

みんな意外と書かないけど、個人でWordPressサイトささっと作りたい時とかに**一番かんたんな手順・サービス**をまとめてみた。

# EasyWPとかwスケールアップとか細かい設定どうすんのwww
→ その時はちゃんと環境作って移行すればいいだけ。
移行ツール↓
https://ja.wordpress.org/plugins/all-in-one-wp-migration/

# やること => 使用サービス
1. ドメインとる => **namecheap**
2. サーバーたてる => **EasyWP**
3. テーマさがす => **Themeforest**
4. SSL対応 => **sslforfree.com / Let's Encrypt**

すごくかんたん。

# 手順

## 1. ドメインとる（namecheap）
初年度のディスカウントとか抜きにすると、**だいたいのドメインでnamecheapが一番安い**。UIもお名前.comよりはマシ。
https://www.namecheap.com/

ここで欲しいドメインをさがして、購入画面でEasyWPがセット割（初月1ドル、2019年11月現在）で買えるので、そのままGo。

<img width="1380" alt="スクリーンショット 2019-11-21 22.36.39.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/804427b1-bf72-f95b-d7be-37fa205e457f.png">

誰だkantanwp.com取ってるやつ

## 2. サーバーたてる（EasyWP）
EasyWPは**namecheapと連携したWordPressのホスティングサーバー**。なのでドメイン購入したらすぐ管理画面に飛ばされるので、対象ドメインを設定して少し待つだけでWordPressが立ちます。

## 3. テーマ入れる
これはただのおすすめです。無料テーマがしょぼいので、**ここで好きなテーマを探す**と幸せになれそう。
https://themeforest.net/

## 4. SSL対応
意外と面倒なのがここ。証明証を買うのはだるいし、Let's Encryptも設定が面倒そう（サーバーの中に入れれば別だけど）。

**最低限の手間でできるのが「SSL for free」というサイト。**
https://www.sslforfree.com/

① まずはドメイン名を入力

<img width="1036" alt="スクリーンショット 2019-11-21 22.44.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/199fc5a4-5d74-b127-0439-f32f4b6d20fb.png">

② EasyWP側で、SFTPの接続設定をだす

<img width="1036" alt="スクリーンショット 2019-11-21 22.45.08.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/df366ea4-688d-4c41-8c92-42474c907537.png">

③ Automatic FTP Verificationを選択して、↑のSFTPの接続情報を入力。

<img width="1036" alt="スクリーンショット 2019-11-21 22.44.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/897c49cc-c20e-632a-7db9-e6bc8dbfdb5c.png">

④ **!!!ここ重要** SSLの証明書をダウンロード・解凍したら、certificate.crtとca_bundke.crtを一つのファイルにする必要がある（これやらないと中間証明書が認識されない？）。ca_bundke.crtの内容を全部コピーして、certificate.crtの末尾に貼り付ける。
↓こんなイメージ

```
-----BEGIN CERTIFICATE-----
...
MIIFWjCCBEKgAwIBAgISBNI9kxZLPkE18B6HiVZTKZX/MA0GCSqGSIb3DQEBCwUA
MEoxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MSMwIQYDVQQD
...
-----END CERTIFICATE-----

-----BEGIN CERTIFICATE-----
...
VAYDVR0gBE0wSzAIBgZngQwBAgEwPwYLKwYBBAGC3xMBAQEwMDAuBggrBgEFBQcC
ARYiaHR0cDovL2Nwcy5yb290LXgxLmxldHNlbmNyeXB0Lm9yZzA8BgNVHR8ENTAz
...
-----END CERTIFICATE-----
```

⑤ EasyWPにアップロードしてSSLを有効化
<img width="1036" alt="スクリーンショット 2019-11-21 22.57.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/114895/6317609d-77d4-6cb6-6ec3-35fce1f1c0b3.png">

# まとめ
慣れると10分くらいでできるようになります。これ以上にかんたんな方法があったら教えてくださいm(_ _)m
WSL2でUbuntuのデスクトップGUIを表示する

# 概要

WindowsのWSL2を使って、WindowsマシンにUbuntuのデスクトップGUIを表示する方法です。
WSL2のインストール自体は他のサイトに情報があるのでリンクを貼り省略します。

# WSL2のインストール

WSL2のインストール方法は下記のサイトに記載があります。

* [Installation Instructions for WSL 2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-install)
* [WSL2入れてみた](https://qiita.com/TsuyoshiUshio@github/items/947301bd9317610572fc)

前提としてWindows Insider Programに参加し、Windows 10 バージョン 2004をインストールする必要があります。（2020年3月時点）

# VcXsrvのインストール

下記サイトからVcXsrvをインストールします。

* [https://sourceforge.net/projects/vcxsrv/](https://sourceforge.net/projects/vcxsrv/)


# デスクトップの表示

Xlaunchを開き、`Select display settings`画面で、One window without titlebarを選択し, Display number 0を入力します。`Select how to start clients`はデフォルト設定のまま次へを押します。`Extra settings`でDisable access controlにチェックを入れます。（他の項目はデフォルトでチェックが入っている。）次へを押し、完了します。

次に、Ubuntu 18.04 LTSアプリを開きubuntu-desktopをインストールします。これは時間がかかります。

```
sudo apt-get install ubuntu-desktop
```

下記のコマンドを入力すると、Xlaunchにデスクトップ画面が表示されます。

```
sudo chmod 777 -R ~/.cache/
sudo service dbus restart 
DISPLAY=$(grep -m 1 nameserver /etc/resolv.conf | awk '{print $2}'):0.0 XDG_SESSION_TYPE=x11 gnome-session
```

![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/602996/13dc7bdb-5672-3a55-e0de-fc7b2f2c505d.png)

デスクトップのデザインは`gnome-tweaks`をインストールすることでカスタマイズできます。
Vagrantの流れ

# box作成
⚠︎どのディレクトリからでもOK

`$ vagrant box add ○`

# boxを使用する
⚠︎作業ディレクトリで実行

`$ vagrant init ○`
↑Vagrantfileが追加される！

# 環境に合わせて、Vagrantfile編集

`config.vm.network ~~~~~~~など`

# Vagrant起動・接続
⚠︎Vagrantfileがあるディレクトリで実行

`$ vagrant up`
↑Vagrantfile読み込み

`$ vagrant ssh`
↑仮想環境にアクセス

`[vagrant@ ~]$ `
になっていたらOK！！！！！！！！
VueのRouterでURLのパラメータの型をstringから変更する


例えばユーザーデータ更新APIリクエストでURLのIDとか使って引数に渡す時に,

```js
this.$route.params.userId
```
↑みたいに取得するとstringでしか受け取れず
毎回number型に変更するのが冗長な気がしてたので
router側で変更する方法ないかなぁって調べたけど
なかなか出てこなかったけどやっと見つけたのでメモ


### 修正前

修正前のrouterでの設定が↓だとして,

```js
{
  path: 'userEdit/:userId',
  name: 'userEdit',
  component: () => import('./views/UserEdit.vue'),
},
```

### 修正後

propsという項目でパラメータの型を変更することができる
routerから先にparamsを取り出して,キャストしてpropsにセットするというやり方


```js
{
  path: 'companyList/:companyId',
  name: 'companyEdit',
  component: () => import('./views/CompanyEdit.vue'),
  props: (route) => ({userId: Number(route.params.userId)}),
},
```

### コンポーネントでの受け取り方

後はコンポーネントでPropで受け取るだけ
自分の環境だと↓で受け取れる


```js
@Prop()
private userId!: number;
```


意外にもクソ簡単だった。。。。。

### おわり

## 参考資料

[VueRouter基本ルーティング記法まとめ](https://www.ritolab.com/entry/181)
コンピュータ関係の図記号等

ある研究室の扉のステッカー。

![90503786_3563430140393689_1375261627829452800_o.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51423/6fbd800a-4fdf-ab58-3f6a-a3b5189d625a.jpeg)

コンピュータ関連のものを記録

左上から

misora*
https://www.misoca.jp/

nifty cloud*
https://pfs.nifcloud.com

マスプロ電工*
https://www.maspro.co.jp

電波・空中線の教科書の誤植かどうか、正しい式は何かを教えていただきました。

ESC*: Electronic stability control
http://www.advics.co.jp/eng/csr/safety/esc.html


SDK/: Software Developer Kit: 旧Borland

eXe: ういろMUG(macintosh user group)を開催していた団体・場所*
https://exe-nagoya.net/archives/tag/ういろmug

UNIX/:GNU*
https://www.gnu.org

Toppers*
https://www.toppers.jp/

電総研（産総研）
http://www.itri.aist.go.jp

Apple*
https://www.apple.com

現在も存続している組織またはロゴには*
AWS Lambdaのカスタムランタイムを開発する際、失敗したこと

# 概要

とある作業にてAWS lambdaで今度はperlを動かすことになりました。
その際、perlのライブラリ`/usr/share/perl5`などが見えなかったり、コマンドが実行できなかったりしたので、いろいろ調べたことをメモしておきます。

~~用意されているランタイム使えば余計な苦労しないのにね~~

# 結論

さっさと結論だけ記載すると、以下の環境のカーネルとlibcなどの基本的なライブラリが乗っているものになります。

- Amazon Linux
    - イメージ – amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2
    - Linux カーネル – 4.14.154-99.181.amzn1.x86_64
    - ami-00a5245b4816c38e6

注意点として、このイメージは、EC2インスタンスを作るときに、クイックスタートとして表示される、Amazon Linuxのイメージとは別物ということです。

- Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type
    - ami-02ddf94e5edc8e904

# EC2でカスタムランタイム用のコードを作ってアップしたかった

カスタムランタイムを作成するにあたって、開発環境も含め、今回はAWS上のサービスに構築しました。
EC2でコードを開発、zipにまとめてawscliでlambdaにコードをアップロードする、まあ標準と思われる方法を使おうと思いました。

# 自分のやった間違い

以下、公式マニュアルに記載があります。
[AWS Lambda ランタイム](https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/lambda-runtimes.html)

ここに、ランタイムのイメージが以下2種類あり、それぞれランタイムのバージョンごとに分かれていることがわかります。

* Amazon Linux
* Amazon Linux 2

|名前|識別子|AWS SDK for Python|オペレーティングシステム|
|:------------------:|:------------------:|:------------------:|:------------------:|:------------------:
|Python 3.8|python3.8|boto3-1.10.34 botocore-1.13.34|Amazon Linux 2|
|Python 3.7|python3.7|boto3-1.10.34 botocore-1.13.34|Amazon Linux|

さて、ここでカスタムランタイムの開発用にEC2のイメージを作るときに、クイックスタートの候補で、以下のようなものが羅列されると思います。

* Amazon Linux 2 AMI (HVM), SSD Volume Type
* Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type

カスタムランタイムのマニュアルでは、オペレーティングシステムの指定が見当たらなかったので、`Amazon Linux 2 AMI (HVM), SSD Volume Type`を選んで作ってしまいました。

### ２だとダメなところ

そもそも、２はカーネルバージョンが違うようです。このため、libcなどのバージョンが異なり、lambdaにアップロードしたアプリケーションがそもそも起動すらしませんでした。
ここで、最初の間違いに気づき、インスタンスを`Amazon Linux AMI 2018.03.0 (HVM), SSD Volume Type`に変更します

### コマンドもなにも見つからない

さて、カーネルバージョンについてはこれで一致し、コンパイルしたアプリケーションが動くようにはなりました。
しかし、開発環境では実行できるコマンド、`perl`や`aws`が見つからないし、`perl`のコマンドをもっていってもライブラリが全く見つからなかったりしました。
そのため、足りないのを探すという作業をしつつ、最終的にはあきらめてすべてアップロードするコードの中にコピーすることとなりました。

# 振り返りつつ、次はうまくやるために

ちゃんと指定されたイメージから開発用インスタンスを立ち上げましょう

### 再掲

- Amazon Linux
    - イメージ – amzn-ami-hvm-2018.03.0.20181129-x86_64-gp2
    - Linux カーネル – 4.14.154-99.181.amzn1.x86_64
    - ami-00a5245b4816c38e6

そのうえで、perlのパッケージコントロール`cpanm`やpythonのパッケージコントロール`pip`などを活用し、追加したライブラリはできるだけ手元に作成したフォルダに保存し、コードとして一緒にアップロードできるように管理することが必要です。

# 最後に要望

せめて`aws`コマンドくらいlambda上で標準で使えてもいいんじゃないかなという素人考えな要望で締めたいと思います。
文章を特徴量ベクトルに変換する日本語の学習済みモデルまとめ

## 概要

1. input:日本語の文章、output:実数で回帰したい。
2. そのためにまず、文章を特徴量ベクトルに変換したい。
3. アンサンブル学習で性能を高めるために、異なるモデル、異なるデータセットで学習した、学習済みモデルがたくさん欲しい
4. 学習済みモデルを探した。

## 文章

### Universal Sentence Encoder (multilingual)

https://tfhub.dev/google/collections/universal-sentence-encoder/1

### BERT (multilingual)

https://tfhub.dev/google/collections/bert/1

### nnlm

https://tfhub.dev/google/collections/nnlm/1

### doc2vec

https://yag-ays.github.io/project/pretrained_doc2vec_wikipedia/

## 単語

### Word2Vec

#### Wikipediaで学習

https://github.com/Kyubyong/wordvectors

### FastText

#### Wikipedia + Common Crawl (mecab)

https://github.com/facebookresearch/fastText/blob/master/docs/crawl-vectors.md

#### Wikipedia (mecab NEologd)

https://qiita.com/Hironsan/items/513b9f93752ecee9e670

### Byte-Pair Encoding

#### Wikipedia

https://github.com/bheinzerling/bpemb

### Wikipedia2Vec

#### Wikipedia

https://wikipedia2vec.github.io/wikipedia2vec/pretrained/

## その他文章特徴量

### 品詞、ひらがな、カタカナ、英数字の回数または割合

https://www.jstage.jst.go.jp/article/jjske/12/1/12_15/_pdf

### エントロピー

### 単語長

### 文章難易度

https://waseda.repo.nii.ac.jp/index.php?action=pages_view_main&active_action=repository_action_common_download&item_id=35923&item_no=1&attribute_id=162&file_no=1&page_id=13&block_id=21

帯はrubyのファイルがダウンロードできなくなっていた。

### ネガポジ

https://qiita.com/yukinoi/items/46aa016d83bb0e64f598

## kaggleで見つけたテクニック

### [kaggle: Toxic Comment Classification Challenge まとめ](https://copypaste-ds.hatenablog.com/entry/2019/02/01/174135)

やはり、埋め込みベクトルのアンサンブルが重要らしい。

あと、翻訳によるdata augmentation。

## 参考リンク

- https://github.com/Hironsan/awesome-embedding-models
- https://blog.statsbeginner.net/entry/2017/05/07/091435
Macの仮想音声デバイスを使って音声認識でオンラインミーティングの自動字幕作成


英語でのオンラインミーティングの議事録を作るのが面倒なので，オンラインミーティングの音声を，自動字幕生成の入力にしてしまい，発言をリアルタイム自動字幕で残すことを考える．

# 準備

- 仮想音声デバイスBlackHoleのインストール
 - https://github.com/ExistentialAudio/BlackHole
 - 以前にはsoundflowerがあったがもう開発されてない
- 自動英語字幕作成サービス otter.ai
 - アカウント作成しておく
- 日本語の音声認識ならGoogle DocでもOK
 

# BlackHoleのインストール，設定

- githubのreleasesからBlackHole.vx.x.x.pkgをダウンロード，インストール
- githubの説明に従って複数デバイス作成 https://github.com/ExistentialAudio/BlackHole/wiki/Multi-Output-Device
 - 参考：[[Mac] 仮想オーディオデバイス BlackHole Virtual Audio Driver](https://note.com/wacw/n/n5fd75f7edc67)

こうなればOK

<img width="780" alt="スクリーンショット 2020-03-19 14.28.37.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44835/91fab1e2-c31c-1dc6-bea0-2982700852b1.png">

サウンドで出力先を，作成した「複数出力装置」に設定

<img width="780" alt="スクリーンショット 2020-03-19 14.30.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44835/af30c562-768e-5616-0c50-ce55ebbc19f7.png">

音声の入力先はBlackHole．

<img width="780" alt="スクリーンショット 2020-03-19 14.30.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44835/01540ced-8505-85d4-2887-1476c1f495d2.png">

なにか動画を再生して，
- 内蔵スピーカーから音が出る
- サウンドの入力レベルが動く
ならOK

# otter.aiで自動字幕

オンラインミーティングの代わりにyoutubeの動画を再生して，その音声に自動字幕をつけてみる．


<img width="768" alt="スクリーンショット 2020-03-19 14.32.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44835/0c54a6da-9f1d-5117-06d4-6ca25314fafb.png">

動画は，OxfordSparksの[What is Machine Learning?](https://www.youtube.com/watch?v=f_uwKZIAeM0)．ライセンスはCreative Commons．英語字幕がもともと付いているので，自動字幕と比較ができる．

以下がotter.aiの自動字幕．きれいな動画音声なので，ほぼほぼ正確．

<img width="1055" alt="スクリーンショット 2020-03-19 14.32.21.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44835/4d44ea2e-3557-4e2a-7ebf-39b8503c5c0e.png">



# 終了

使い終わったら入力・出力デバイスを内蔵デフォルトに戻しておく．

<img width="780" alt="スクリーンショット 2020-03-19 14.32.56.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44835/4e48fc19-a416-a92e-d244-405640290c44.png">
<img width="780" alt="スクリーンショット 2020-03-19 14.33.02.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44835/a8d7d76d-7873-224c-7f62-dea0572e0117.png">



# 問題

- たまに音が聞こえない．何度かデバイスを切り替えるとなぜかできる．．．
- たぶんマイクの音を拾わないので，聞いているだけのミーティングならOK．発言する場合には，別デバイスを使うのが早い（設定すればできそうだけど）．


# misc

- macの音声認識に流すときにサウンドが消えないようにする [How to keep sound from muting while using dictation?](https://apple.stackexchange.com/questions/110839/how-to-keep-sound-from-muting-while-using-dictation)
Ruby on Rails チュートリアル学習記録 第6章

第4、5章については特に書く内容がなかったため学習記録は付けませんでした
# 6.1
特になし
# 6.2
特になし
# 6.3
`heroku run rails db:migrate`を`bash: heroku: command not found`というエラーメッセージ。
[3章](https://qiita.com/okbiz07/items/7cb45e325ae4afd0c549)の時と同じ方法で解決
`nvm install node`
`npm install -g heroku-cli`
を実行後、あらためて`heroku run rails db:migrate`を実行
# 6.4
特になし
ApatchでSetEnvを設定したらエラーが出た時の対処

#何が起きたの？
ApachでSetEnvを利用しようとしたら以下のエラーが発生しました。

```
Invalid command 'SetEnv', perhaps misspelled or defined by a module not included in the server configuration
```

#どんな内容のエラー？
Google先生の翻訳内容は↓

無効なコマンド「SetEnv」。スペルが間違っているか、サーバー構成に含まれていないモジュールによって定義されている可能性があります。

#原因
env_moduleってのが存在しないために発生していたエラー
以下に記載されていました。
https://httpd.apache.org/docs/2.2/ja/mod/mod_env.html

#対処方法
私の環境では、コメントアウトされてました。
対処手順は以下の通りです。

```
cd /etc/httpd/conf/
vi httpd.conf
(検索)/env_module
#LoadModule env_module modules/mod_env.so
↓
LoadModule env_module modules/mod_env.so
```
SharePoint PnP PowerShellで同時に複数のサイトを取り扱う

PowerShellでサイト管理を行う上で、同時に複数サイトを取り扱うケースが少なからずあるかもしれません。
しかし、扱うサイトを切り替える毎に`Connect-PnPOnline`と`Disconnect-PnPOnline`を実行するのはあまりよろしくないように思えます。
上記の問題を解消する方法がありますので、以下に記載します。
## 接続方法
普段接続に使用している`Connect-PnPOnline`の引数に`-ReturnConnection`を追加し、任意の変数に格納します。

```PowerShell:connect.ps1
$SiteA = Connect-PnPOnline -Url <site url> -ReturnConnection
$SiteB = Connect-PnPOnline -Url <site url> -ReturnConnection
```

## 各コマンド実行方法
例えば各サイトに対して`Get-PnPList`を発行したい場合は引数に`-Connection <接続情報変数>`を追加します。
以下の例では、上記接続方法で用意された`$SiteA`と`$SiteB`を使用しています。

```PowerShell:get.ps1
Get-PnPList -Connection $SiteA
Get-PnPList -Connection $SiteB
```

## 接続解除方法
普段、接続解除に使用している`Disconnect-PnPOnline`の引数に`-Connection <接続情報変数>`を追加します。
(各コマンド実行方法と同じですね)

```PowerShell:disconnect.ps1
Disconnect-PnPOnline -Connection $SiteA
Disconnect-PnPOnline -Connection $SiteB
```

## 余談
[Connect-PnPOnline](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/connect-pnponline)に引数として`-ReturnConnection`は記載されていますが、サンプルは特にありません…。
[Get-PnPList](https://docs.microsoft.com/en-us/powershell/module/sharepoint-pnp/get-pnplist)などのParameters欄の`-Connection`に

> Retrieve the value for this parameter by either specifying -ReturnConnection on Connect-PnPOnline

と書いてあるくらいです。

`Connect-PnPOnline`のサンプルにチラっとでも書いててほしかったなぁという気持ちではあります。