OmniAICreator/Qiita-1.07M huggingface dataset:
[Unity] SRP Batcher を検証してみました


本記事はCraft Egg Advent Calendar 2021の12/16の記事です。
前回の記事は@ce_gassyさんの [新卒エンジニアが業務を行う上で意識したこと](https://qiita.com/ce_gassy/private/3c4b4bb4f460ae89d8da) でした。

## ◆ 概要

- Built-in な RP, URP, SRP Batcherの適用とで比較検証を行ってみました。

## ◆ 環境

- Unity : 2020.3.24f1
- Universal RP(com.unity.render-pipelines.universal) : 10.7.0
  - 依存パッケージ
    - com.unity.render-pipelines.core : 10.7.0
    - com.unity.shadergraph : 10.7.0
    - com.unity.mathematics : 1.1.0
  - 簡易的な測定を行うために[Graphy](https://github.com/Tayx94/graphy)を利用しています。
- ほか
  - Windows11
  - Core i9-10900F
  - GeForce GTX 1050 Ti

## ◆ 検証の流れ

1. Build-in な Render Pipeline で測定環境を構築し測定する。
   1. Unlit Shaderをメニューから生成する。
   1. MeshRendererを持つ Prefab(Sphere) と 生成したシェーダを参照する Materialを用意する。
   1. MonoBehaviour.Start で指定数分 Prefabと Materialを Instantiateさせる。(雑に30000オブジェクトほど Instantiateしてみています)
1. URPに切り替えるのみの対応を施し測定する。
   1. UniversalRenderPipelineAssetをメニューから生成する。
   1. 生成した UniversalRenderPipelineAssetをデフォルトのまま Graphics設定に反映する。
1. Unlit Shaderに対して URPならびに SRP Batcher対応を行い計測する。

## ◆ 検証結果

- 対応前のベース状態 : 約15fps
  - Render.OpaqueGeometryに大きく時間がかかっている状態。(41.2msほど)
  ![LegacyRPProfiler.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/35fa2c6c-8465-c337-2399-003d3c7ed4b6.png)
  ![LegacyRP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/43a9c612-0d27-c2da-48f8-69d8404abf05.png)

- URPに切り替えるのみ : 約15fps
  - DrawOpaqueObjectsに大きく時間がかかっている状態。(44.6msほど)
  ![URPProfiler.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/a6092813-aef3-daf5-892f-d4754f2810a3.png)
  ![URP.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/8791dd23-063a-442c-1f2c-261fbfe42ccf.png)

- SRP Batcher対応 : 約30fps
  - URPへ切り替えただけと比べDrawOpaqueObjectsの負荷が大幅に軽減されている。(9.8msほど)
　　![SRPBatcher2Profiler.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/8df0cf65-89e4-fb99-b495-92a51b370b28.png)
　　![SRPBatcher2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1059896/bd4640cd-17be-c6b7-8ced-2581d433f475.png)


## ◆ 対応内容

- SPARKCREATIVE Tech Blog [シェーダーをUniversal Render Pipelineに対応させたかった覚書](https://tech.spark-creative.co.jp/entry/2021/01/13/130743) を参考にさせていただきました。
  - 対応毎に測定しておりましたが、1番負荷が軽減されたのは ```CBUFFER_START```〜```CBUFFER_END```の記述追加による SRP Batcher対応でした。

## ◆ まとめ

- 今回はひとまずPCエディタ上で測定しました。
- 検証条件を整理、見直した上でモバイルも測定し効果的であることが実証されたなら、まだ対応していないシェーダーの対応検証を進めようと思います。


明日は@Tomy_0331の記事です！
【AWS】基本ネットワーク設計

AWSでステージング環境、本番環境を作成する際に必ず知っておく必要があるのがAWSのネットワーク周りです。(知らないと環境作れない。)
今回は、本当に基本的なネットワークの設計を勉強のアウトプットがてら記述します。

この記事の対象読者は、AWSを勉強し始めてまもない方対象です。(筆者も勉強し始めてから1週間)
1年間の無料枠がAWSで用意されているので、勉強する際は、概念を理解し、そこから手を動かしたらより理解が深まると感じています。
(無料枠でないものを使うと課金されます、NATゲートウェイ使ったら課金されました。。。。。。。。。)
## 出現用語
* VPC
* サブネット
* ルートテーブル
* アベイラビリティゾーン
* インターネットゲートウェイ(IGW)
* NATゲートウェイ

## 今回のネットワーク構成
![Untitled Diagram.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669831/ea6d7d23-e7ca-8781-7375-6767edbb4db6.jpeg)

今回は、このようなネットワーク構成を軸に説明していきます。

### VPC
なにはともあれ、一番初めに環境を作るにあたって作成するものはVPC(Virtual Private Cloud)になると思います。
**AWS上であるサービスのネットワーク領域を確保するもの。**
です。
基本的には、このVPC内で作業を行なっていきます。
![スクリーンショット 2021-12-10 10.37.02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669831/8e8b4625-7586-6c63-91de-fa6f39863b8d.png)

### サブネット
サブネットは、
**VPCの中をさらに細かく分ける単位**

以下のような特徴があります。

* VPCを作成した以上サブネットは1以上必要。
* Privateサブネット、Publicサブネットがある。
* EC2などのサーバーを立てるための場所
* VPCで確保したIPアドレス内に収まるIPアドレスを指定する必要がある。

ですので、EC2などのサーバーを立てる際は、サブネットを立てる必要があります。(EC2立てるときに選択するようになる。)

また、VPCのIPアドレス範囲が、172.16.1.0/24(172.16.1.0 ~ 172.16.1.255まで使用可能)の場合、サブネットのIPアドレスその範囲に収まる必要があるので、172.16.1.0/26たいを4つ、172.16.1.0/25たいを2つetc...置けることができます。(ここら辺自信ないです、間違ってたらすいません。)

また、サブネットにはPrivateサブネットとPublicサブネットという2つの種類が存在します。
Privateサブネット ・・・ 外部とのインターネットとの通信が可能
Publicサブネット ・・・  外部とのインターネットとの通信が不可
(厳密な話をすると、サブネットの通信先がInternet gateway(後述)に向いているものがPublicサブネット、それ以外をPrivateサブネットといいます。)
![スクリーンショット 2021-12-10 11.15.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/669831/980689f2-8fbc-fc93-2e2e-672b660c7c60.png)

※画像はあくまでイメージです。
基本的に、データベースやサーバーなどの外部に公開したくないものはprivateサブネットに配置することで外部からの攻撃から守れるようになります。

### インターネットゲートウェイ(IGW)
外部のインターネットと、AWS上で作成した個人のVPCネットワークを繋げる役割を持ちます。
VPCひとつにIGWをひとつだけアタッチ(つける)ことができます。

### ルートテーブル
ルートテーブルは、
**サブネットの通信先を定めたもの。**

特徴としては、

* 1つのサブネットに対して、1つのルートテーブルを設定できる。
* サブネットを作成したときにデフォルトで作成されている。(デフォルトの通信先は、VPCのIPアドレス)
* 後から通信先を追加することができる。

サブネットの通信先をルートテーブルできめるのですが、サブネットの説明で「Privateサブネット、Publicサブネットがあり、インターネットゲートウェイ(IGW)に通信先が決まっていればそのサブネットはPublicサブネットになる」と記述しました。
そのIGWに通信先を設定するのもルートテーブルで設定します。
(送信先:0.0.0.0/0、ターゲット:igw)

### 最後に
今回は、本当に基本的なAWSネットワークでした。
実際に実務で使用する際は、サブネット内に、ES2インスタンスなどを立てて、セキュリティーグループを設定し通信できる範囲を制御したりするようなので、またキャッチアップした後ご紹介できたらと思います。
CloudRunの実行環境とCPUのお話

エイチームフィナジーアドベントカレンダー16日目は私 @NMura3 が担当します。

# 概要
GCPのサービスの一つである、CloudRunについて今年の9月10月とプレビュー版で公開された、実行環境とCPUの新しい機能について検証した内容を投稿します。

# CloudRunとは
CloudRunはGCPで提供されているフルマネージドなコンテナの実行環境です。
AWSでいう、LambdaとECSの中間のようなサービスです。
Lambdaのように実行環境はフルマネージドで、ECSのようにコンテナを実行できます。
フルマネージドなので、スケールアウトも自動で行ってくれるので、運用も非常に楽になります。

また、課金は実行時間とリクエスト数などで課金されます。

### CloudRunのCPU
CloudRunのCPUはリクエストが発生すると割り当てられます。
そのため、リクエストが終わったのちに非同期で処理を行いたいユースケースには対応できませんでした。
しかし、9月の発表にて、CPUを常時割り当てる機能(AlwaysCPU)が追加されました。

https://cloud.google.com/blog/ja/products/serverless/cloud-run-gets-always-on-cpu-allocation

画面から設定するか、下記コマンドで割当が可能です。

```
gcloud beta run services update SERVICE-NAME --no-cpu-throttling
```
* プレビュー版のため、betaのインストールが必要です。

### CloudRunの実行環境
こちら[Goreplayを入れた話 \- Qiita](https://qiita.com/NMura3/items/48e220ee5ed69fdfe991)にも書きましたが、実行環境に第二世代がプレビュー版でリリースされました。

https://cloud.google.com/run/docs/about-execution-environments

## CloudRunで処理を高速化できるかもしれない！？
実行環境の第二世代の機能に前回はシステムコールの件に触れましたが、今回目をつけたのは
> - CPU パフォーマンスの高速化
> - ネットワーク パフォーマンスの高速化（特にパケットロスがある場合）

です。

これにより、第二世代でCloudRunを動作させる方が速くなるかもしれません。
CPUの方でもAlwaysCPUにしていれば、CPUが常に割り当てられるので高速が期待できるかもしれません。
また、AlwaysCPUでは料金体系が追加され、リクエスト課金が発生せず、単価も15-20%安くなります。

つまり、この2つの組み合わせで、CloudRunを高速に経済的に動かせるのではないかという仮設のもと検証しました。

# 動作検証
動作検証は下記のパターンをjMeterを用いて行いました。
- 第一世代で通常のCPUとAlwaysCPU
- 第二世代で通常のCPUとAlwaysCPU
で行いました。

また、jMeterでは
1ユーザーのリクエストを3種類を合計12リクエストで行い、スレッドを10で10ループ行いました。
合計1200リクエストが20-30秒で終了するので、秒間50ぐらいのアクセスです。

その検証結果が以下になります。

### 第一世代で通常のCPUとAlwaysCPU

|| 通常CPU AVG  | AlwaysCPU AVG  |
|---|---:|---:|
|1回目  |682ms  |683ms  |
|2回目  |684ms  |674ms  |
|3回目  |676ms  |684ms  |

これはほぼ差がない感じです。


### 第二世代で通常のCPUとAlwaysCPU

|| 通常CPU AVG  | AlwaysCPU AVG  |
|---|---:|---:|
|1回目  |575ms  |578ms  |
|2回目  |596ms  |575ms  |
|3回目  |581ms  |571ms  |

若干AlwaysCPUの方が高速に動いているようにみえますが、あまり差がない感じです。
ですが、先程の結果と比べると明らかに実行環境が第二世代の方が速くなっています。

### 第二世代はスケールアウトが遅い？
第二世代を使用するとスケールアウトが遅くなるということがドキュメントに書いてありました。
> プレビュー版で第 2 世代の実行環境は、一般に持続的な負荷の下では迅速に動作しますが、第 1 世代よりもコールド スタート時間が長くなります。

これがどれほど遅くなるかも調べてみたところ約2倍遅くなっておりました。

![スクリーンショット 2021-12-11 13.53.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17939/52f62ff6-94c2-ea6a-8e98-f18ed86060d6.png)

第一世代は16秒で起動していましたが、第二世代は32秒ほどで起動しました。
これは検証に使ったプログラムの特性もあると思うので、この値は相対的に捉えてください。

ドキュメントには
> コールド スタートは第 2 世代よりも第 1 世代のほうが高速ですが、第 2 世代のプレビュー版が終了するまでに、このパフォーマンスのギャップは小さくなります。

とあるので、正式版になればもっと高速になることを期待しております。

# GoReplayを用いて
上記の検証はjMeterを用いた検証なので、ある程度高負荷な状態での検証しました。
また、AlwaysCPUではリクエスト数が多ければ、料金が安くなるので、運用時のリクエスト数で検証するのが良いかと思います。

こんな時に便利なものがGoReplayです。
本番環境と同じリクエストを流せるのでそれで検証しました。

![スクリーンショット 2021-12-11 14.04.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/17939/5f9c7f87-96c3-0129-c3c6-97cd80a2c846.png)

これを見るとAlwaysCPU(緑の線)が1.5から2倍ほど遅くなっております。
これには理由があり、インスタンス数が1だったためです。
インスタンス数を2で検証してもよかったのですが、この間の料金を見ると通常のCPUとAlwaysCPUではほとんど料金の差がありませんでした。
つまり、検証したサービスではAlwaysCPUでのコスト削減は期待できないという結論になりました。

# まとめ
いかがだったでしょうか？

個人的にCloudRunのサービスは手軽にコンテナを実行できて、フルマネージドなため運用が非常に楽になります。
そのサービスの新しい機能がが今年の9月10月とプレビューされたので、早速検証してみました。

今回この検証をしてみて思ったのは、こういったプラットフォームな部分の検証は本来やりにくかったり、検証用の環境の構築に手間がかかったりしますが、CloudRunを使っているとGoReplayやjMeterで非常に簡単にできると感じました。
テスト自動化 OSSかSaaSか

打ち上げ花火を下から見るか横から見るかは、議論の分かれるところだと思いますが、ちなみに、私は花火を上から見下ろしで見たことがあります。

冒頭から話がそれましたが、ミクシィのQAチームはE2Eテストの自動化に取り組んでおります。そう、「取り組んでいる」という言葉がぴったりで、まだまだ試行錯誤しながらやってる段階です。目に見える成果が出るのは、もう少し後になるかな、という感触です。


さて、現在、自動化を2つの方法で取り組んでいます。
ひとつはseleniumやAirTestといったオープンソース(OSS)を利用したもの。
もう一つは、mabl、magicpod、autifyなどのテスト自動化支援のSaaSを利用したものです。
この記事では、OSSとSaaS、それぞれの特徴を書いてみたいと思います。

## OSSをつかった自動化
■メリット
・すぐに始められる
・スキル次第でやりたいことはなんでもできる。
・無料(といっても、ツール費用が無料というだけで、環境構築に時間やスキルが必要。そこにコストが掛かっているのは無視してはならない)

■デメリット
・プログラミングスキルが必要となり、非エンジニアにはハードルが高い。
・また、上記と連動しますが、限られた人しかできなくなるので、属人化しがち。担当者が去ると自動化も終わってしまいがちです。

## SaaSをつかった自動化
■メリット
・環境構築のコストが安い。Webページのテストであればテスト対象のURLさえあれば良い。
・ノーコード・ローコードで自動化のスクリプトを書くことができるため、スクリプト作成のハードルが低い。30分レクチャーすれば、だいたい誰でもスクリプトを書けるようになる
・自動化に携わる人を増やせる。メンテナンスコストや属人性を下げることができる

■デメリット
・ツールの利用料が発生する。自動化の規模が大きくなるほど、利用料も増えていく。
・OSSと比較すると、出来ることが限られる。テストのカバレッジがツールの機能次第になる。
・現状、各種SaaSはゲームアプリとの相性は良くない印象。

## まとめ
私が所属しているQチームでは「全員が自動化のスクリプトを書けるようになる」を第一目標にしているため、SaaSを利用し自動化を進めております。一方で、自動化専門のチームを作って、OSSでゴリゴリやってるQAチームもあります。

みんな違ってみんな良い。
ドメイン設定のよくあるミス

[ペライチアドベントカレンダー](https://qiita.com/advent-calendar/2021/peraichi)の13日目です。

誰でも簡単にホームページが作れる[ペライチ](https://peraichi.com)では有料プランに契約いただくと、ホームページに独自ドメインを設定することができます。ペライチで独自ドメインを利用していただくには、ドメイン販売サービスなどでユーザーさまが購入したドメインにAレコードを設定していただく必要があります。（DNS設定が不要なペライチ内でドメインを購入するオプションもあります）

慣れないユーザーさまがDNSを設定する場合、どうしても設定ミスをしてしまうことがあり、これまでに数多くのドメイントラブルのお問い合わせをいただいてしまっています。集まった事例からドメイン関連のトラブルシューティングのヘルプページを作成しています。

- https://support.peraichi.com/hc/ja/articles/360022515333
- https://support.peraichi.com/hc/ja/articles/360023852853

今回はその中で印象に残っている設定ミスについていくつかご紹介しようかなと思います。

## 1. Aレコードが複数設定されている
ペライチで独自ドメインを利用するには、ドメインのAレコードに `13.112.187.226` のIPアドレスを設定していただく必要があります。
以前に同じドメインでホームページを公開しており、ペライチに移行された場合に、以前の古いAレコードの設定が残ったままになっていることが多くあります。

特に旧ホームページがしばらく運用されていなかったなどエラー画面が表示される状態になっていると、ペライチで障害が発生しているのではないか、というお問合せを受けることがあります :innocent: 

dig で一瞬で判別できるので四天王の中でも最弱の難易度です。

```
$ dig +short example.com     
93.184.216.34
13.112.187.226
```

## 2. IPv6の罠
ペライチで独自ドメインを利用するには、ドメインのAレコードに `13.112.187.226` のIPアドレスを設定していただく必要があります。IPv6にはまだ対応ができていません。

ブラウザで確認すると「1. Aレコードが複数設定されている」かのような挙動をするが、digを見ても問題ないように見える場合があります。

```
$ dig +short example.com
13.112.187.226
```

この時、Aレコードと同じドメインに AAAA レコードが設定されている場合があります。digコマンドではデフォルトでAレコードのクエリになっているので、明示的にAAAAレコードで問い合わせないといけません。罠でした。

```
$ dig +short example.com AAAA
2606:2800:220:1:248:1893:25c8:1946
```

## 3. メールが受信できなくなった
「Aレコードを変更したらメールが受信できなくなった」というお問い合わせを受けることがあります。
これはWEBサーバーとメールサーバーが同じサーバー（同じIPアドレス）で運営されているサービスを利用されている場合に多いです。

MXレコードに以下のように「WEBサーバーと同じドメイン」が設定されていると、Aレコードの設定を変更することでメールサーバーへの向き先IPアドレスも変更されてしまいます。

```
dig +short exampel.com MX
10 example.com.
```

- `mail.exmaple.com` などメール用のサブドメインでメールサーバーのIPアドレスを設定し、MXレコードにこちらのドメインを設定する。
- MXレコードに元のAレコードのIPアドレスをそのまま設定する。

などの対策が考えられます。
基本的にはご利用中のメールサービス側にどのように設定すべきかを確認していただくご案内になります。

## 4. 操作しているDNSサーバーが違う
ドメインを購入したサービスでDNSサーバーを設定してAレコードを正しく設定したのに、一向にペライチのページに接続することができない、というお問い合わせを受けることがあります。

DNSにはTTLというキャッシュ設定があり、設定が反映されるまでしばらく時間がかかりますが、いくら待っても設定が反映されません。

```
$ dig +short example.com
```

ヒアリングを進めていくと、Aというサービスでドメインを購入して操作したとのことだが、digでNSレコードを確認するとBというサービスのNSレコードが設定されていることがあります。

```
$ dig +short example.com NS
b-ns.exampel.com
```

digでAのドメインサービスのDNSサーバーに対して直接問い合わせると、ちゃんと正しいAレコードが設定されていたりします。

```
$ dig +short @a-ns.example.net example.com
13.112.187.226
```

ここでDNSサーバーをAのものに切り替えていただくと解決しそうですが、BのDNSサーバーには他にもレコードが設定されている場合があり、DNSサーバーの切り替えは慎重になる必要があります。ペライチでは基本的にBのDNSサーバーにてレコードの設定をしていただくようにご案内しています。

## 5. ドメインをそもそも購入していない
お問合せをいただいたドメインをdigでもwhoisでも情報が取れないことがあります。
ほとんどの場合はスペルミスです。英語のスペルミスも多いですが、稀に「ハイフン」が全角になっているなど見た目ではものすごく分かりにくいミスもあったりします。

オチに持ってきてしまっていましたが、ドメインを購入することを失念してしまっている場合も実際にあり、1つ1つの事象に対して丁寧に向き合い、多角的に可能性を探っていく必要があります。 :innocent:
AWS認定ソリューションアーキテクトプロフェッショナル再認定試験に合格した

2回目のAWS認定ソリューションアーキテクトプロフェッショナル再認定試験に合格しました。
今後のために記録を残しておきます。

前回の再認定の記事：[AWS認定ソリューションアーキテクトプロフェッショナル再認定試験に合格した - Qiita](https://qiita.com/mechamogera/items/2088b8e1ed5ba79cd26f)
初回の認定の記事：[AWS認定ソリューションアーキテクト - プロフェッショナルレベルにリベンジして合格した - Qiita](https://qiita.com/mechamogera/items/b9b658369918290d0889)

# 試験勉強

## 勉強開始時のAWS知識

ここ数年は業務でAPI Gateway、Lambda、S3ホスティング、CloudFrontあたりの限定した範囲をさわっているくらい。

## 勉強時間

勉強期間は10/4から勉強開始、12/11に受験したので2ヶ月とちょっと。
休日は家事育児があるので平日業務時間中に1時間ほど勉強。

## 勉強内容

以下のUdemyの演習問題をChromeで日本語翻訳して解いて間違ったところを中心に見直し、知識が不足しているところを調べてメモに残す。
https://www.udemy.com/course/aws-solutions-architect-professional-practice-exams-amazon
勉強期間中に演習問題4セットを１回半（第3セットの演習問題を2巡目完了したところまで）実施。

# 試験について

## 試験日時

一応不合格時の再試験も考慮して認定期限の1ヶ月半前くらいに設定

## 試験場所

自宅でリモートで受けようかとも思ったが調べてみると1駅のところで受験ができるようになっていて部屋の片付けも面倒だったのでテストセンターで受験。

## 当日の流れ

1. テストセンターに移動
1. 15分前まで待機
1. 15分前に受付、署名、身分証明書提示、顔写真撮影、荷物預ける
1. 席まで移動して試験開始
1. 75問190分を受験、残り15～20分時点で全問回答、残り時間で見直し、前回試験時は監視員とチャットでやり取りしたが今回はそういうのはなかった（試験会場全体の監視のみ？）
1. 試験終了後アンケート回答、最後に結果表示
1. 受付で結果は最大5営業日以内に確認できます(結果は書いてない)という紙をもらって退出

## 試験の日本語

日本語で受験したが翻訳が結構ひどかった。
「でで」みたいなちょっとした間違いや「ロール」→「役割」みたいな個所があった。
英語表示もできるので表示を切り替えて確認すればよかった。

## 試験の結果

スコア777(合格基準750)で合格
5分野のうちの組織の複雑さに対応する設計の分野で改善が必要(受験者に期待される知識、スキル、および能力が備わっていない)

# 所感

* 合格はしたものの結果はギリギリだったので3カ月くらい演習問題が3巡目途中くらいで受験できると良かった。再試験まで14日間なので最初の受験をもう少し遅らせてもよかったかも。
* 集中力の限界時間を大幅に超えている190分の試験時間はつらい。落ちても二度と受けたくないという気持ちになった。
* 試験前にレッドブルを飲んで集中でき排尿も我慢できたが試験後に謎の腹痛に襲われた。
* 前回までとは違って試験後に合否結果を含めたスコアレポートが手渡されないので、試験の最後に合否の表示があったとはいえ正式な通知が来るまでドキドキした。
* テストセンター受験では試験環境を整える必要がないところが良い。
* あまり業務でさわっていないオンプレとVPCの接続とか組織とかAWS Organizationsが苦手だった。
* 試験勉強でAWS知識のアップデートができたところは良かった。リージョンを超えたサービスとか提供しやすくなっていると感じた。
手順メモ　NiftyのセカンドメールをiPhoneから使えるようにする

# はじめに
すごくマイナーな話で、なかなかネットに情報がなかったので、自分用メモ

# Nifty側設定
最初にNifty側で、セカンドメールのメールアカウントに対してimapを有効にする。
（popでも設定できそうだがこちらの方が便利なので。）

名前　(任意)
メール　(メールアドレス)
説明　(任意)

受信メールサーバー
ホスト名　imap.nifty.com
ユーザー名　(メールアドレス)
パスワード　(パスワード)

送信メールサーバー　（詳細画面に）
smtp.nifty.com
SSL 使用
認証　パスワード
サーバーポート　993
Excelをデータベースのように使ってみた！

# 初めに
初投稿です。
RPAで業務を自動化するとき、インプットとしてExcelファイルを使う事が多いと思います。
AutomationAnywhereでは[Excelの基本操作]と[Excelの高度な操作]というパッケージが準備されており、
普段はこれらの機能で十分自動化を実現できるのですが、ちょっと変わった使い方を紹介出来ればと思います。
# 事前準備
### ODBCドライバの32Bit版を準備
[コントロールパネル]-[管理ツール]-[ODBC Data Sources(32Bits)]に**｢Excel Files｣の32Bit版**が存在しない場合は
以下のURLよりインストールしてください。
URL：https://www.microsoft.com/en-in/download/details.aspx?id=13255
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587639/cb6bd3fa-f66d-a127-23a5-f4cf09080261.png)

### データ格納用のExcelファイルを準備する。
**1行目は必ずヘッダ情報**を設定してください。
**シート名がテーブル名**の代わりになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587639/62aa46dd-f958-fba3-8074-5440000dc683.png)


# ロボットの作成
①**[データベース]-[接続]**アクションを使います。
　接続モードは｢デフォルト｣に設定します。
　接続文字列は｢テキストを入力｣を選択し、設定値に
　｢Driver={Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)};DriverId=1046;Dbq=<対象Excelファイルのパス>;DefaultDir=<作業領域>;｣を設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587639/87f1fd73-04ef-66be-8863-0fc3e6ea4bd6.png)

②DataTable変数に値を取得する場合は
　　**[データベース]-[データテーブルにエクスポート]**アクションを
　Csvファイルに値を取得する場合は
　　**[データベース]-[読み取り]**アクションを使います。

　Selectステートメントを入力にSQL文を設定します。
　テーブルの代わりに[シート名$$]と記載します。**必ず語尾に$を２つ設定します。**

　出力結果は｢割り当て先｣に設定したDataTable型の変数(tblTest)に格納します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587639/4a43af8c-f61d-ac5f-1b95-74f0ff78e6d9.png)

③使い終わったら**[データべース]-[接続解除]**で接続を解除します。


# ロボットの実行結果
上記ロボットを実行すると以下のような結果になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/587639/27714a57-cca5-4db4-a20c-060a536f855d.png)

#　最後に
如何だったでしょうか？
フィルタをかけたい場合は
　select * from [Sheet1$$] where 商品コード = 'ACE001'
とwhere句を追加する事で可能です。

insert/update/deleteを行いたい場合も
**[データベース]-[挿入/更新/削除]**アクションを使用する事で実行出来ます。

データベース環境を構築するのは大袈裟だけど、SQLを使ってデータの管理を行いたい！
という需要がございましたら、ぜひ試してみてくださいね！

では、皆様、良いRPAライフをお送りください(^o^)
Power Apps グローバル変数とコンテキスト変数の罠？

言語使用的に現状（記事投稿時点 2021年12月）では、どうしようもないよね、でも、知らないとハマるよね。っていうシーンに出会ったので、忘れないように記事にしておく次第。

# 出会ったシーン
結論としては「グローバル変数」と「コンテキスト変数」を”同じ変数名”で命名してしまい、どっちが呼び出されているのか作成者が理解できなくなって混乱した、です。（当方は、混乱しているシーンを Web 会議の画面上で眺めていた）

## 再現例
現象を極限まで簡略化して説明します。下イメージのようにボタンコントロールの OnSelect イベントで「グローバル変数（Set関数）」と「コンテキスト変数(UpdateContext関数)」で”同じ変数名”（例では val01）を設定しています。
![01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/3f343073-66d9-67f1-2562-1cb045a827bf.png)

この状態で、ラベルコントロールへ val01 の値を表示させます。コンテキスト変数が表示されました。
![02.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/010c0db0-2d00-5712-f07a-4c7397b67eeb.png)

スクリーン（画面）を足して、同様に val01 の値を表示すると、グローバル変数が表示されます。
![03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/d33c90b4-c7c6-2d7c-912e-8599fa07571a.png)


別スクリーンでグローバル変数が利用できるのは変数のスコープ（範囲）による動作ですね。2画面目ではコンテキスト変数を生成してないので Set関数 で指定した値が表示されます。

変数のスコープに関しては、共著「[Microsoft Power Apps入門 手を動かしてわかるローコード開発の考え方](https://amzn.to/3sGO4Gv)」で、可能な限りわかりやすく解説しております。変数？スコープ？影響範囲？？よくわからないなぁ、と感じる方は書店などで是非お手に取ってみてください。

# つまり…
つまり、Power Apps では記事投稿時点では「変数のスコープに関わらず、同一の変数名を利用可能」という言語仕様である、です。また「コンテキスト変数が優先される」という点も前述の動作から確認できました。

前述の例ごとく、関数が列挙されているだけであれば発見しやすいでしょう。しかし、コンテキスト変数は Navigate 関数で画面遷移する際にも生成できます。Form コントロールの OnSuccess で画面遷移が仕込んであって、そこにコンテキスト変数が宣言されている、みたいなパターンは見つけるのにソコソコ苦労するんじゃないかな、と思います。

# では、どう対策したら良いか？
「変数の命名に気を付ける」← この1点につきます。
所属企業などのコーディング規約があれば、それに従ってください。規約・ルールが存在しないのであれば、Microsoft から提供されている下記のガイドラインを活用しましょう。

## PowerApps キャンバスアプリのコーディング規約とガイドライン
■日本語
https://memo.tyoshida.me/wp-content/uploads/2021/06/4bbaa6955f6a1caa85a9653c13d61d72.pdf

■英語
https://pahandsonlab.blob.core.windows.net/documents/PowerApps%20canvas%20app%20coding%20standards%20and%20guidelines.pdf

ちなみに、上記ガイドラインにも変数に関しては注意喚起がされています。
![04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/215892/afe9ef26-c884-ce75-9847-30830b76e059.png)

ちゃんと書いてありますね。なお、曖昧除去演算子に関しては単純な変数では関係しないので、この純粋な変数という文脈では関連しません。

# まとめ

- Power Apps はグローバル変数とコンテキスト変数で”同じ変数名”が利用可能
- ”同じ変数名”が存在する場合、コンテキスト変数が優先される
- 変数の文脈における対策は「変数名をチャンと付ける」以外、現状は無い
- 公式のコーディング規約とガイドラインは読んどいたほうが良いゾ！

同一変数名が利用可能な点が仕様とはいえチョッと不親切だなぁ、と思いつつ。とはいえ、命名に気を付けていれば知らなくても問題にならない箇所でもあるのも事実です。変数名をテキトー付けて利用するのはおススメしないです。意味ある命名をしましょう。たとえば、検証用だったり、1週間ぐらい利用できれば良いみたいな使い捨てのアプリまで、がっつり細かな命名しろ、とは申しませんが、普段から気を付けておくのがおススメだと個人的には思います。
書籍やWebサイトで変数 a とか b 等が利用されがちなのは”変数名短くしないと文章量が増えちゃって大変”等の理由があります。また、変数名よりも、もっと優先して伝えたい情報がある場合（今回のように）val 等の簡素な変数名に”あえて”することもあります。優しさがある書籍なら「ちゃんと命名しましょうね」ってドコかに書いてあるハズです（たぶん。


少なくとも「命名は大切だ！」という点だけは覚えておくと、アプリ作成者もそのアプリのコードを見る方も幸せになる可能性があがります。ローコードと言えども、コードですから。ちゃんと”意味のある命名”していきましょう！

それでは、皆さま。素晴らしい Power Platform Life を！
ハードウエアの故障

ちょっといろいろ暴言を吐きまくったので反省の意味で少し書いておく。

FreeBSD/mipsのおそらく最後のリリースになるであろう12.3Rが出たので、ZRoute.orgでビルドしていろいろ焼き直しをしている。

以前はamd64の12RでjailとZFSのコマンドで環境を作っていたが13RにしてBastilleBSDに環境を移行した。

改めてビルドしてみるといくつかのportsもどきでCVEのエラーが出たので、本家と同じバージョンにアップデートしてみた。

すでに本家のportsはgcc4では通らないfor(int i=0;;)にパッチを当てていないものがあり、gcc4のサポートは終了しているようだ。

RalinkのSOCを使っているGPS,JJY NTP ST1とおうちモニター(oumon)は結構すんなり入れ替えられた。

入れ替え作業のついでにoumonで照度データを集めるようにしました。

![スクリーンショット 2021-12-13 8.40.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104066/b54a6ac5-4341-6003-722c-7d0a9d16e847.png)

またRalinkのifのrtに若干不安があるので、センサーモジュールからoumonへのhttpはこれまでの1分おきから10分おきに変更しました。

以前はrootfsを小さくするためにntpdとntpdateを分けていたのだが、分けてビルドできなくなったので、一つにした。以前は4M Flashも想定したが、現在はすべて8M以上なのであまり分ける意味がなくなった。

入れ替えはAsia BSD Con 2019で話したリモートアップデートで行った。コンソールつないだりの手間がないので、非常に簡単にできるが、失敗しないかはらはらする。

FireWallとVPNはAtherosのSOCで動かしていてまずVPNサーバの焼き直しをしてみたところまったく機能しなくなった。

dmesgを見てみるとスイッチ(RTL8366SR)の認識に失敗している。

http://dmesgd.nycbug.org/index.cgi?do=view&id=6380

なにか修正の副作用かと思い調べてみたが、なかなかわからない。以前は認識してはずの古いコードでも問題が解消しない。

RTL8366SRのサポートは自分が作ったもので、コードをいじってみたが上手くいかない。NYCBUGの過去のdmesgを検索してみても以前はちゃんと動いていたことが確認できる。

完全に壊れているわけではなく、u-bootでは認識していたり、起動後にスイッチとしては機能している。

どうもRTL8366SRの挙動が変わってしまって認識できなくなったのが原因と思われます。RTL8366SRはReaktekの初期のGigaスイッチであまり作られておらず、ほとんどが後継のRTL8366RBを使っています。

RT2880なモジュールに付いたRTL8366SRも認識できなくなっているので、コードの問題かもしれません。

Gigaなスイッチは消費電力が大きく壊れやすいのかもしれません。RBのタイプでも調子が悪くu-bootからネットアクセスができないモジュールもありました。

そもそもSRとRBはチップを認識するためのIDが別のアドレスにあり、とってもおかしな設計をしていたり、不思議な動きがあったような記憶があります。やっぱり蟹です。

このモジュールは3,4年くらい24x7で使っていて、可能性としてはRTL8366SR自体の問題か、電源などの周辺回路の問題が考えられますが、深くは調べてません。

結局RTL8366RBのモジュールに入れ替えました。同じモジュールがふたつあるので、今回の教訓からコールドスタンバイにしました。

OS入れ替えなどで障害が発生した場合はOSを疑いますが、入れ替えのために電源を落としたりすることで、部品の故障が顕在化する可能性があるような気がします。

OS入れ替えの前に、電源を落としてそのまま起動しても、問題が起きていた可能性が高いです。このような確認をしたほうが良いのかもしれません。

すこし調べてみたところI2CでのRTL8366SRが認識できなくなってるようです。1回はアクセスに成功するのですが2回目以降はダメです。

openwrtをビルドして焼いてみて試したところ、認識できているようです。FreeBSDのI2Cのコードと相性が悪くなったような感じです。とはいえ以前は動いていたコードだしなんだかなって感じです。

CoregaのCG-WLR300GNVもネットワークが使えない。RTL8366RBが見えなくなってるようだ。

我が家で一番故障率が高いのはRT3050が入った白いFONです。 故障はいろいろなパターンがあるような気がします。

* 全く起動しない
* ブート後すぐ固まる
* 起動はするがネットワークが使えない
* 起動するが数日すると固まっている

寒いと起動しないモジュールもありました。

安定して動いていた期間もあり、OSの問題とは考え難い。

~~かなり熱を持つので、SOCにヒートシンクを貼っているが、それでも壊れる。~~ いろいろ対策下おかげか、ちょっと壊れにくくなったきがします。

おうちのNTP ST1はすべてこれなのでどうにかしたい。

watchdogを実装して、不調なモジュールは固まったら再起動するようにして使っています。

2025/04/20にJJY ST1のFON(DCジャック:大,flash:16pin)が壊れました。症状は電源を入れても、LEDも点灯せずまったく起動しなくなりました。
AtCoder230をやった(Java)

AtCoder230をやった。
※諸事情でリアルタイム参加できなかったから、、泣

##[A](https://atcoder.jp/contests/abc230/tasks/abc230_a)
文字列を出力する問題
与えられた数字が
1~9だと、**AGC00x**と表示
10~41だと、**AGC0xx**と表示
42~54だと、基盤となる数字に1を足して、**AGC0xx**と表示
※ソースはクソです。多分もっといい書き方あります

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>();    
        
        list.add(scan.nextLine());
        
        if(Integer.parseInt(list.get(0)) < 10){
            System.out.println("AGC00" + list.get(0));    
        } else {
            if(Integer.parseInt(list.get(0)) >= 42){
                System.out.println("AGC0" + Integer.toString(Integer.parseInt(list.get(0)) + 1));    
            } else {
                System.out.println("AGC0" + list.get(0));       
            }
        }
    }
}

```

##[B](https://atcoder.jp/contests/abc230/tasks/abc230_b)
文字列Tは**oxx**を10^5回連結させて組み合わせた連結文字と書いている。
しかし文字列S（入力によって与えられる文字列）は10以下であるから、
文字列Tのループを少なくするため、10^2でソースコードを記述している。

```
import java.util.*;

public class Main {
    public static void main(String[] args) throws Exception {
        // Your code here!
        Scanner scan = new Scanner(System.in);
        ArrayList<String> list = new ArrayList<String>();    
        
        list.add(scan.nextLine());
        
        String str = "oxx";
        for(int i = 1; i < 100; i++){
            str += "oxx";
        }
        
        if(str.contains(list.get(0))){
            System.out.println("Yes");
        } else {
            System.out.println("No");
        }
    }
}
```

いつかC問題もJavaで解きたいな(n回目)。
今回のC問題ちらっとみたけどいけそうな気がする。
ServerlessFramework + AWS + Pythonで作るレイヤーと単体テスト

# はじめに
ServerlessFramework + AWS + Pythonでバックエンドを構築しているとき、開発規模が大きくなってくるとLambda内のPythonコードを共通化したくなることがあると思います。そんなときに使えるのがLambdaレイヤー。Lambdaレイヤーとして作ったモジュールを色々なLambdaで使い回すことができます。モジュールのサイズが大きくなりすぎてコンソールで表示されなくなった時の切り分けにも使えそうです

[以前の記事](https://qiita.com/nashitake/items/b8122bc9693d592f5360)の続きです

## 最終的な構成

```
/
├── serverless.yml
├── functions/
│   ├── hello/
│   │   ├── handler.py
│   │   └── requirements.txt
├── layers/
│   ├── original_module.py
├── layers-test/
│   ├── test_original_module.py
```

# 作り方
## Lambdaレイヤーを定義して、Lambdaと紐付ける
serverless.ymlのルートレベルにLayer定義を追加して、functionsと紐付けます

```serverless.yml
layers:
  layer-modules:
    path: layers
    description: layer for ingredients
    CompatibleRuntimes:
      - python3.8

functions:
  hello:
    module: functions/hello
    handler: handler.hello
    layers:
      - Ref: LayerDashmodulesLambdaLayer  # layerとの紐付け部
    events:
      - http:
          path: /users/create
          method: get
```

LambdaとLayerを紐づけている部分ですが、少し変わった名前になっているかと思います。この名前は.serverless/serverless-state-.jsonの中で検索してもらえると出てきます。どうやらlayersで定義している名前「layer-modules」をもとに、自動で生成されているようです（modulesは先頭大文字にならないのか...）

## Lambdaレイヤー側のコード
```original_module.py
# coding: UTF-8

class OriginalModule:
    def add(self, arg1, arg2):
        return arg1 + arg2
```

## Lambdaレイヤー呼び出し側のコード
```hander.py
import sys
sys.path.append('/opt')
from original_module import OriginalModule

def hello(event, context):
    originalModule = OriginalModule()
    result = originalModule.add(3, 5)

# 〜　略　〜 #
```

LambdaにLayerを紐づけると、Lambda実行ディレクトリの/opt以下に生成されるようです。エラーが出る場合はrequirements.txtを置き忘れていたり名前を間違えていたり、Dockerデーモンが動いているかを確認してみてください

## 単体テストを追加
Layer化されているとAWSコンソールからでは修正できなくなります。そうすると気軽にトライアンドエラーできなくなるので、単体テストをしっかりやったほうがいいかと思っています

```test_original_module.py
# coding: UTF-8
import unittest
import os
import sys

sys.path.append(
    os.path.join(os.path.dirname(__file__), 
    '../layers/')
)
from original_module import OriginalModule

class TestOriginalModule(unittest.TestCase):
    def test_case(self):
        target = OriginalModule()
        self.assertEqual(target.add(1, 2), 3)
```

実行するときはこんな感じです

```
python -m unittest test_original_module
```
ibus-skkのビルド

## Note: 2022/08/19
Ubuntu 22.04.1 時点ではちゃんと設定が保存されるようになっている気がするので、以下をやっておくだけでよさそう。

* Setup > Behavior > Initial mode: Latin
  * OKを押す

## diff

ibus-skkの設定が再起動後保持されなくなったので、デフォルト設定をいじるため、ビルドしてインストールしてみた。

```diff
diff --git a/src/preferences.vala b/src/preferences.vala
index c7f196a..306ee46 100644
--- a/src/preferences.vala
+++ b/src/preferences.vala
@@ -89,7 +89,7 @@ public class Preferences : Object {
         _default.set ("show_annotation",
                       new Variant.boolean (true));
         _default.set ("initial_input_mode",
-                      new Variant.int32 (Skk.InputMode.HIRAGANA));
+                      new Variant.int32 (Skk.InputMode.LATIN));
         _default.set ("egg_like_newline",
                       new Variant.boolean (false));
         _default.set ("typing_rule",
```

## ghq get
```
ghq get ueno/ibus-skk
```

## ビルド依存のインストール
```
sudo apt install gnome-common libibus-1.0-dev libskk-dev libgtk-3-dev valac
```

## ビルド
```
./autogen.sh
./configure
make
```

## インストール
```
sudo make install
```

これだと `ibus-engine-skk` と `ibus-setup-skk` が `/usr/local/libexec` に入ってしまうので、`/usr/lib/ibus` に `sudo cp` する。なお、一旦SKKのかわりに英語のIMEだけ有効化して再起動するなどしないとこれは実行できない。
Azure MonitorエージェントによるWindows仮想マシンの監視

本記事は以下サイトにて記載しています。
恐れ入りますがリンクから移動してご参照ください。

Azure MonitorエージェントによるWindows仮想マシンの監視
https://cloudsteady.jp/post/50812/
　
　
現在パーソルプロセス＆テクノロジーではAdvent Calendar 2021を開催中です。
https://qiita.com/advent-calendar/2021/ppt

こちらも興味ある記事あれば是非ご参照ください。
kintoneのフィールド値からQRコードを生成するプラグイン


#概要
kintoneのフィールド値からQRコードを生成してみます。
やることとしてはとってもシンプルですが、リンクの読み取りだけじゃなくハッシュ値なんかをQRコードで印刷して、電子チケットや入館管理システムなんかもkintoneと連携して作ることができちゃいます。

さくっとできる割には応用範囲の広いカスタマイズではないかということで、スクリプトの例とプラグインを作ってみましたので公開します。

#javascriptカスタマイズ

とりあえずGETリクエストでQRコード画像を作ることができる
https://goqr.me/api/
を使わせてもらってやってみました。

アプリに必要なフィールドは

* 文字列のフィールド（一行文字列、複数行文字列、リンク など）
* スペース

です。
以下のコード例では、
文字列フィールドのコードは「文字列__1行_」
スペースのコードは「output」
というアプリで作っています。

``` javascript:qrcode
	kintone.events.on([
		"app.record.detail.show", // PCのレコード詳細表示イベント
		"mobile.app.record.detail.show" //モバイルのレコード詳細表示イベント
	], function (event) {
		try {
			const code_str = event.record['文字列__1行_'].value;
			// スペース要素の取得（PCとモバイルで要素取得のメソッドが違います）
			const space = kintone.app.record.getSpaceElement('output') || kintone.mobile.app.record.getSpaceElement('output');

			// QRコード用のimg要素を作ります
			const img = document.createElement('img');
			// GETクエリにQRコード化したい文字列を含めて画像のソースとして使うことができます。
			// サイズを 150 x 150 に指定しています。
			img.src = 'https://api.qrserver.com/v1/create-qr-code/?size=150x150&data=' + code_str;

			// スペース要素に追加して表示完了
			space.appendChild(img);

			return event;
		} catch (ex) {
			console.warn("Exception KintoneEventsOn Queue", ex);
		}
	});
```

#プラグイン化もしました

ここまでやってみて、あまりに簡単なのでちょっとこれだけじゃなあ……ということでプラグインも作ってみました。
kintoneと連携する以上は外部のAPIに文字列を送信しないでQRコードにしたい場合が多いと思うので、プラグインでは
https://github.com/davidshimjs/qrcodejs
を使わせてもらっています。

[<img width=120 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67365/d8463110-639d-2ff4-0e18-1b2419eba684.png">](https://spica-git.github.io/gh-projects/zip/kintone_qr_generator.zip)
↑プラグインのzipファイルが **ダウンロード** できます。

##プラグインの設定

こんな感じの設定ができます。
QRコードにしたい文字列フィールドとスペースを選択してサイズを指定。（80～1000ピクセルまで指定できます）

![qr_generator_plugin.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67365/bbc0280c-5803-9c37-4172-4ba50b4e3ef6.png)

設定したレコードをアプリで見てみるとちゃんとQRコードが出力されました。

[<img width=320 src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67365/3407f8b3-7b22-f3d7-8103-9423919b0546.png">](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/67365/3407f8b3-7b22-f3d7-8103-9423919b0546.png)

よしよし。大丈夫ですね！

#Spicaについて

さていかがでしたでしょうかー。もうkintoneハックしまくりの方にはちょっとつまらない内容だったかもしれないですが。
昨年のkintone AdventCarendarでは[俺とPTAとkintone](https://qiita.com/spica/items/6e7e086dbc9f650bf8e0)とか言って、kintoneの非営利団体向けライセンスで挫折しちゃった体験記を書いたのですが、本当はコロナ禍のなかでこそ活きる活動だったなあと色々タイミングが噛み合わなかったのが未だに悔しい今日このごろであります。

Spicaでは[機能拡張スタンダードAll-In](https://spica.tokyo/bluelaunch)というプラグインを販売しております。
かなり細かく自動計算したりフィールドの編集可不可とかPDF出力レイアウト作成とか一文字検索とかとかとかとかいろいろできるようになるプラグインでございます。よければトライアルで使ってみてもらえたらと。

ではでは、どクラウドです！
【Rails】本番環境のECSからS3へアクセスできないを解決【AWS】

## やりたいこと
本番環境でRailsからS3へファイルアップロードする時のエラーを解決したい。

## 環境
- rails 6.14
    - gem 'aws-sdk-rails'
    - gem 'aws-sdk-s3', '~> 1'
- ECS(Fargate)

## 結論

https://github.com/aws/aws-sdk-ruby#configuration-options

ECSの資格情報をRailsに与えることで解決。
`app/controllers/rails_controller.rb`内の記述を以下に書き換える。

```ruby:app/controllers/rails_controller.rb（修正後）
s3 = Aws::S3::Resource.new(
      region: @region,
      credentials: Aws::ECSCredentials.new
    )
```

```ruby:app/controllers/rails_controller.rb（修正前）
s３ = Aws::S3::Resource.new(
      region: @region,
      credentials: Aws::Credentials.new(
          ENV['AWS_ACCESS_KEY'],
          ENV['AWS_SECRET_KEY']
       )
    )
```
GraphQLのPOSTをするときに馬鹿をやらかした話

# はじめに
Heroku Postgreに対して外部から(Herokuアプリ外のサービスから)データを挿入したいという状況の時、
Hasuraはとても役に立ちます。
今回は、そのPOST操作(SQLのINSERT操作)を行おうとしたときに出会った魑魅魍魎を紹介しようと思います。

## Hasuraってなに？
この記事に丸投げします。私はここから学びました。
https://qiita.com/maaz118/items/9e198ea91ad8fc624491

また、HasuraはHerokuに対して強力なサポートをしており、
ワンクリックでHeroku Postgreを利用したGraphQLサーバーを立ち上げてくれます。
https://hasura.io/learn/ja/graphql/hasura/setup/

## 今回実装したかった事
AndroidアプリケーションからHeroku Postgreに対してデータの挿入を行いたい
それなら、GraphQLのmutationを利用して挿入しようじゃないか

## おっと
今回発行するGraphQL Queryは以下のような感じだ。keyの命名と値の型の対応がおかしいだろという意見は最もだが、
主題ではないので無視してほしい。ちなみに、値は適当なものを入れている。

```graphql
mutation{
    insert_some_table(
        objects:[
            {id: 2, user_id: "2", timestamp: "2020-01-02T21:12:01", punish_id: 2, latitude: 43.123, longitude: 38.0123, car_data_id: 1, is_payment: false, image_base64: "test"}
        ]
    ){returning{id}}
}
```

あとはこれをPOSTするだけだーとなったわけである。

Android(Java)でPOSTリクエストを出す方法はここのコードを用いた。
http://blog.livedoor.jp/sce_info3-craft/archives/9599960.html

なので、こんな感じでJson文字列を書いてみた。

```java
String jsonString = "{\"query\":\"mutation{insert_warn_info(objects:[{id:3,user_id:\"2\",timestamp:\"2021-01-02T21:12:01\",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:\"test\"}])}\"}";
```

そうしたらエラー発生 :thinking: 

```
W/System.err: org.json.JSONException: Unterminated object at character 61 of {"query":"mutation{insert_warn_info(objects:[{id:3,user_id:"2",timestamp:"2021-01-02T21:12:01",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:"test"}])}"}
```
あれ？エスケープはできてるんじゃないんですか奥さん？

## 今回の馬鹿
今回のJSONの構成は{"query": "GraphQL Query"}という形になっている。
さて、GraphQL Queryには文字列をダブルクォーテーションで指定しなければならない部分があるわけだ。

そして、エスケープは""の1つ下のネスト毎に1回外されるという法則がある。
元々このjsonStringは文字列としてダブルクォーテーションで囲っているため、
このダブルクォーテーションを外すと、以下のようになる。

```json
{"query":"mutation{insert_warn_info(objects:[{id:3,user_id:"2",timestamp:"2021-01-02T21:12:01",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:"test"}])}"}
```

jsonでコードブロックをハイライトしたのでお気づきになるだろう。そう、ダブルクォーテーションの対応がおかしいのだ。

## これで解決
これはエスケープの必要があるな？ということで以下のようにする。

```json
{"query":"mutation{insert_warn_info(objects:[{id:3,user_id:\"2\",timestamp:\"2021-01-02T21:12:01\",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:\"test\"}])}"}
```

これをjavaのStringに埋め込むためには、**このエスケープ文字をエスケープする必要がある！**
よって以下のようになる。

```java
String jsonString = "{\"query\":\"mutation{insert_warn_info(objects:[{id:3,user_id:\\\"2\\\",timestamp:\\\"2021-01-02T21:12:01\\\",punish_id:2,latitude:83.123,longitude: 78.0123,car_data_id:1,is_payment:false,image_base64:\\\"test\\\"}])}\"}";
```

``user_id:\\\"2\\\"`` のような感じになるということだ。

## おわりに
言われればそうだが、気づかないものだ。いや、経験が足りないだけな気がするが。
同じ状況に陥った人がいるかは知らないが何かのはずみで助けになったら幸いである。
scpコマンドを用いてファイルをローカルからリモートにコピーする

# 目的

- ローカルのPCからscpコマンドを実行して「ローカルからリモートへファイルをコピー」する時のscpコマンドの例を記載する

# 方法

- 下記コマンドを実行する。（基本形）

    ```terminal
    $ scp コピー元ファイルパス リモートのユーザー名@リモートのIPアドレス:ファイル名を含むコピー先のパス
    ```

- ローカルの`~/text.txt`ファイルを、IPアドレスが`*.*.*.*`のユーザーが`miriwo`の`/home/miriwo`に`test.txt`をコピーしたい場合、下記を実行する。

    ```terminal
    $ scp ~/text.txt miriwo@*.*.*.*:/home/miriwo/text.txt
    ```

# オプション

- 接続時に使用するssh鍵や接続先のポート番号の指定、ディレクトリのコピーなどオプションを使うことで指定する事ができる。
    - `-P ポート番号`

        ```terminal
        $ scp -P ポート番号 コピー元ファイルパス リモートのユーザー名@リモートのIPアドレス:ファイル名を含むコピー先のパス
        ```

    - `-i ssh秘密鍵のパス`

        ```terminal
        $ scp -i ssh秘密鍵のフルパス コピー元ファイルパス リモートのユーザー名@リモートのIPアドレス:ファイル名を含むコピー先のパス
        ```

    - `-r`

        ```terminal
        $ scp -r コピー元ファイルパス リモートのユーザー名@リモートのIPアドレス:ファイル名を含むコピー先のパス
        ```
[Swift] class から struct の static func を closure 引数付きで呼び出す時、循環参照するか調べた

実行したコード：

```swift:swift
import Foundation

// 引数のクロージャを非同期実行する関数
// 実際の場面では非同期実行することが多いので、今回も非同期実行にする
struct A {
    static func a(_ closure: @escaping () -> Void) {
         DispatchQueue.main.async  {
             closure()
         }
    }
}

// Aを利用するクラス
// 実際の場面では ViewModel とか？
class B {
    
    // 検証に使用する変数
    var int: Int = 0
    var closure: () -> Void = {}
    
    // MARK: -
    
    // インスタンスの番号
    let version:Int
    
    init(_ version: Int) {
        self.version = version
    }
    
    // インスタンスが解放されるか調べるために、 deinit したか分かるようにする
    deinit {
        print("deinit \(version)")
    }
    
    // MARK: -
    
    func b() {
        switch version {
        case 0:
            A.a {
                _ = 1 + 1
            }
        case 1:
            A.a {
                self.int = 1
            }
        case 2:
            A.a {
                self.int = self.int * 2
            }
        case 3:
            A.a {
                self.closure = {}
            }
        case 4:
            A.a {
                self.closure()
            }
        case 5:
            A.a {
                self.closure = { self.int = 1 }
            }
        case 6:
            // 循環参照が起こる基本的なケース
            // A.a() は呼び出さない
            // case 5 と比較する目的
            self.closure = { self.int = 1 }
        default:
            print("not implemented")
        }
    }
}

(0...6).forEach { i in
    var b:B? = B(i)
    b?.b()
    b = nil // 循環参照が起きていなければ、インスタンスが解放されて deinit が呼ばれる
}

```

実行結果：

```
deinit 0
deinit 1
deinit 2
deinit 3
deinit 4
```

closure の中で ``self.int = 1``みたいなことしても循環参照になってない！
Chrome拡張機能を使ってITC-LMSを魔改造したい

この記事は[EEIC2022 Advent Calender2021](https://adventar.org/calendars/6319)第12日目の記事として書かれました。

はじめまして。EEIC2022の川というものです。せっかく学科のアドカレがあるということで、自分がちょっと前に作ったChromeの拡張機能の話をしたいと思います。
自分はqiitaやブログの記事を書くのは今回が初めてなので、不慣れなところがあるかもしれませんが、大目に見て楽しんでいただければ幸いです。

## あなたのITC-LMSをもっと便利にしたくありませんか？
<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Chromeの拡張機能作ってITC-LMSの時間割ページに「未提出の課題・テスト一覧」を表示するようにした <a href="https://t.co/DHK1F1EY0s">pic.twitter.com/DHK1F1EY0s</a></p>&mdash; 川 (@hososuke0412) <a href="https://twitter.com/hososuke0412/status/1446433260486103042?ref_src=twsrc%5Etfw">October 8, 2021</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

https://github.com/SosukeHosokawa/improved_itc-lms

10月くらいに自分はITC-LMSという、東大の学内サイト上で動くChromeの拡張機能を作って、なんとなくTwitterで公開してみました。
最初は自分の親しい人とかに使ってもらえるといいな、というくらいにしか思っていなかったのですが、実際公開してみると予想以上の反響があり、多くの人にダウンロードしていただけたようです。

今回の記事では、Google Chrome拡張機能の仕組みのかんたんな説明と本記事執筆にあたって上記の拡張機能に追加した新機能の紹介をしたいと思います。

## Chrome拡張機能の仕組みの概要
Chrome拡張機能の詳しい作り方に関する情報はインターネットを探せば、[公式のドキュメント](https://developer.chrome.com/docs/extensions/)などたくさん見つかると思うので、ここでは超初心者向けに拡張機能がどんなことをしているのかの説明に留めたいと思います。

拡張機能がWebサイト上でどんなことをしているのかを理解するためには、まず、Webサイトがどのような要素で構成されているかを知る必要があります。Webサイトのソースコードは基本的に、文書の内容・論理構造を記述した「HTML」、文書の見た目を修飾するための情報を記述した「CSS」、Webページを動的に動かすための「JavaScript」の3つの要素に分けることができます。

これらのソースコードはWebブラウザの検証機能などを用いて見ることができます。Chromeの場合はソースを見たいWebサイトで右クリック→「検証」の項目を選ぶことで見ることができます。

![chrome_dev_img.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692543/d7bad48d-d8c0-0d7d-e718-635082a6041d.png)



このように、WebページはJavaScriptを用いることで様々な操作を行えるようにしているのですが、私達がいま取り扱おうとしているブラウザの拡張機能は、実は元のWebサイトにユーザーが独自のJavaScriptを適用させることで、元のサイトとは異なる操作ができるようになるというものです。
拡張機能を制作するときにはJavaScript本体と、どのような条件でそれを実行するのかを指定すればブラウザ側で勝手に処理を行ってくれるので、比較的簡単に機能を追加することができます。

## 作った拡張機能の紹介
今回自分が作った拡張機能の主な機能は、ITC-LMSを開いたときのトップページ(時間割)に別ページにある「課題・テスト一覧」の内容を埋め込むというものです。

この機能を実現するためにはJavaScriptだけでhtmlを送受信する必要があるのですが、今回は[jQuery](https://jquery.com/)というライブラリを用いることで解決しています。(ただ、自分はそこまでWebに詳しいわけではないのでこの方法には問題があったり、よりよい方法があったりするかもしれません)

### 新機能紹介
本記事を執筆するにあたって、Twitterにあげたバージョンのままでは味気ないと思い新機能をいくつか追加したのでここで宣伝したいと思います。新機能は[こちら](https://github.com/SosukeHosokawa/improved_itc-lms)からソースコードをダウンロードし直すことで使えるようになります。

#### 期限が近づいた課題をハイライトして目立たせる機能
課題一覧をトップページに表示させているとは言っても、時には期限を見逃すことがあるかもしれません。今回追加したハイライト機能により期限の見逃しを一層減らすことができると思います。
![new_feature1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692543/c3a400dc-bf44-7108-29f8-4bb164678167.png "新機能1")


#### 科目を指定して非表示にする機能
~~授業を切って課題一覧が未提出の課題で埋まってしまったとき、この機能できれいな課題一覧に戻すことができます。~~

#### 上記の項目の設定画面
上記の機能のオン・オフの他、ハイライトの色やどれだけ期限が近づけばハイライトを行うかなどを設定できます。

## 拡張機能製作時の注意点
jQueryのような外部と通信できるライブラリを用いると、プログラムの書き方によってはページのリロード1回あたりのサーバ負荷が大幅に増えることもあるので
節度をもった利用を心がけましょう

## まとめ
Chromeの拡張機能開発はエディタとブラウザさえあれば環境構築無しですぐに始めることができ、作業の効率化にもつながるので、興味があったらぜひ挑戦してみてほしいです。
また、今回自分が作った拡張機能は[github](https://github.com/SosukeHosokawa/improved_itc-lms)で公開しているので、ダウンロードはもちろん、issueやpull requestでの新機能の提案なども待っています。

プログラミングをうまく利用して快適なEEICライフをおくりましょう！
Twilio Studio stepsを使用して複数Flow内で同期をとる方法と注意点

#はじめに
複数の電話番号にTwilio発でコール&レスポンスをする必要があり、複数Flowを並行実行させる方法をとりました。
その際に課題となったのが、「呼び出し元のFlowと呼び出し先のFlowで同期をとる」でした。
時間的猶予がなかったため、今回は各Flowの処理状況をSyncではなく、Executionのステータスと経由したWidget(Step)で判断することにしました。

#別Flowを実行する
別FlowのExecutionを作成することで、そのFlowを非同期で実行できます。
toに設定の電話番号を変更すると、Execution作成のたびにコール先の電話番号を
変更できます。

```ruby:別Flowを実行する。(別FlowのExecutionを作成する。)
exports.handler = function (context, event, callback) {
    const client = context.getTwilioClient();
    client.studio.v1.flows("FlowのSID").executions.create({
        to: "発信先電話番号",
        from: "発信元電話番号",
    })
        .then((success) => {
            callback(null, success);
        })
        .catch((error) => {
            callback(null, error);
        });
};
```

#非同期実行のExecutionが完了するまで呼び出し元のFlowを待機する。
非同期で実行しているExecutionの処理状況は、statusフィールドから取得できます。

このExecutionのステータスがactiveの時に一定数秒待機した後に再度ステータスを
チェックし、endedに変更後、先に進む制御を入れることで、呼び出し元のFlowを
待機させることができます。

| status | 状態 |
|:------:|:-----|
| active | 処理中 |
| ended  | 処理終了 |

```ruby:別FlowのExecutionのステータスを取得する。
exports.handler = function (context, event, callback) {
    const client = context.getTwilioClient();
    client.studio.flows("FlowのSID")
        .executions("ExecutionのSID")
        .fetch()
        .then((execution) => {
            callback(null, execution.status)
        })
        .catch((error) => {
            callback(null, error)
        });
};
```
#呼び出し先のFlowで1をダイヤルされたかどうかを確認する。

※呼び出し先のFlowの例
　コール先のスタッフが1をダイヤルした場合のみ、acceptのSay/Playウィジェットを経由します。
![CallFlowImage.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1626190/c8925d65-bca7-08db-2816-4863ee49c80a.png)

stepsで取得のstep情報のtransitionedFromフィールドから、最後に経由したWidget
の名前を取得できます。

```ruby:最後に経由したWidgetの名前を取得する。
exports.handler = function (context, event, callback) {
    const client = context.getTwilioClient();
    client.studio.flows("FlowのSID")
        .executions("ExecutionのSID")
        .steps
        .list({ limit: 1 })
        .then((steps) => {
            callback(null, steps[0].transitionedFrom)
        })
        .catch((error) => {
            console.log(error)
            callback(null, error)
        });
};
```

#注意点
・1つのExecutionの経由できるWidgetの上限は1,000 stepsに設定されています。
　そのため、飛び出し元のFlowの処理を待機する際に経由するwidgetのstep数を
　少量に抑えることをお勧めします。

・Functionの実行時間の上限は10秒に設定されています。
　そのため、Flowを待機させる際にExecutionのstatusのチェックのスパンを10秒超
　に設定する場合で、Waitする処理をFunctionで実行する場合は、実行時間が10秒を下回るよう実行する必要がございます。

```ruby:9秒間待機する処理をfunctionで実行する。
exports.handler = function (context, event, callback) {
    const timerUp = () => callback(null, `9秒間待機しました。`);
    setTimeout(timerUp, 9000);
};
```
railsでpostgresqlのenumを使いたい

## この記事でわかること

- Ruby on RailsでDBをpostgresql利用で開発する際に、**PostgreSQL**のEnumを利用する方法
    - 結論からいうと`gem 'activerecord-postgres_enum'`を利用します。


## まえおき

- Ruby on RailsでEnumを扱おうと思ったときに一番に思いつくのは`ActiveRecord::Enum`です。
- この`ActiveRecord::Enum`はActiveRecordがDBにINSERT or DELETEする際に、定義したEnumの文字列から整数値に変換して保存させるといった使い方が一番使われると思います
- ただ、DBで実際のデータを見たときに、`1`とか`2`が入っていてActiveRecordを介さないと一体何を表しているのかわからないので、PostgreSQLのEnumの機能を利用してデータの見やすさ改善を行っていきます。

## 手順

手順は簡単、まずはgemを入れましょう＼(^o^)／
社員テーブルの性別と血液型の項目にEnumを利用してみます。

### テーブル作成

1. Gemfileに`gem 'activerecord-postgres_enum'`を追加する

    ```ruby:Gemfile.rb
    # その他の部分は省略
    gem 'activerecord-postgres_enum'

    ```
2. 例の如く`bundle install`実行してください
3.  migrationファイルを作成していきます
    - `create_enum`がポイント

    ```ruby:20211212174036_create_employees.rb
    class CreateEmployees < ActiveRecord::Migration[5.2]
      def change
        # 作成するenumを宣言
        create_enum :empooyee_gender, %w(male female other)
        create_enum :empooyee_blood_type, %w(a b o ab)

        create_table :employees do |t|
          t.string :name, null: false
          # 各カラムに上記で宣言したenumを指定する
          t.enum :gender, enum_name: :employee_gender
          t.enum :blood_type, enum_name: :employee_blood_type
          t.timestamps
        end
      end
    end
    ```
4. `bundle exec rails db:migrate`でテーブルを作成しましょう
5. `gender`, `blood_type`にenumが適用されていることを確認します（下記はTablePlusを使って確認しています）
  - data_typeがcreate_enumで作成したenumの名前になっていることがわかります
  ![スクリーンショット 2021-12-13 2.56.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312978/98d1f329-d6af-7bf1-2531-ae888a427327.png)
- 試しにデータも入れてみましょう
  - 下記のようにデータがぱっと見てわかりやすいですね。
  ![スクリーンショット 2021-12-13 2.59.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/312978/03f17617-b82a-387c-9014-d0c25895185b.png)

### `ActiveRecord`から、作成したenumを扱う

- ModelにEnumを宣言します
- 基本的にはいつもと同じですが、value値に対応する文字列を指定します

```ruby:employee.rb
class Employee < ApplicationRecord
  enum gender: {
    male: 'male',
    female: 'female',
    other: 'other'
  }

  enum blood_type: {
    a: 'a',
    b: 'b',
    o: 'o',
    ab: 'ab'
  }
end
```
- このようにすることで、いつもの`ActiveRecord::Enum`と同じ用に扱うことができます

お疲れさまでした。


## あとがき

- 個人的にはEnumを使うときは整数値を保存せずに、上記のように文字列でデータが保存されることでデータの見やすさが圧倒的に違うので、どんどん利用していきたいと思っています。
    - 整数として保存されると実装を追わないと何を示しているのかわからない
    - 特にAPIの開発をしていると辛い部分があります...
- また、今回記事にした理由として、gemを使わずにenumを作成しようとした際に下記のデメリットが有りました
    - migrationファイルにSQLを直接書くことになり、せっかくrailsを使っているのに...という気分になる（ｗ）
    - テーブル自体は作成できるが、`schema.rb`にスキーマが正しく追加されず下記のように省略されてしまう
 
```ruby:schema.rb
# Could not dump table "employees" because of following StandardError
#   Unknown type 'employee_gender' for column 'gender'
```
- こういった理由から今回は`gem 'activerecord-postgres_enum'`を採用しました。

なにかありましたらコメントいただければと思います。
[研究：その2]mediapipeを使用したジェスチャー認識で色々遠隔操作してみる


現在、私は大学で骨格認識技術を使用してIOTデバイスだったりアプリケーションをジェスチャーで遠隔操作すると言った研究をしています。この記事は、進捗報告件、やってみた記事として上げていきたいと思います。

前回まではこちら。

https://qiita.com/magisystem0408/items/9548005b706cbdb94045

## 前回までのスケジュール
![スクリーンショット 2021-12-13 2.06.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/12a3ef3f-f10c-d623-c208-1800ca1b2a4c.png)

## 今週実装したもの
### yeelightの繋ぎこみ完了
yeelightは操作するデバイスとライトが同じwifiを使用をしていることが必須で、2.4G/Hzの通信帯出ないと繋げません。

![light.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/accdfbc9-469f-9c58-bda8-c5de8c066f01.gif)

使用したYeelight

https://jp.yeelight.com/#/index

### ジェスチャー判定の閾値調査について

まず目指すものは、どんな人でもジェスチャー認識できるようにする。
![Web 1366 – 87.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/962b2130-3492-58ba-8585-b913bf37c152.png)

現在ジェスチャー判定の計算の仕方はジョイントとの距離と角度の計算を組み合わせて判定しています。

Vサインの場合
![Web 1366 – 86.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/4c05e555-da1f-43df-36ca-c01c689b164d.png)

男女含めたサインを調査。(ご協力者ありがとうございました。)
![Web 1366 – 91.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/e56ce153-757e-cf2e-0bf6-adabbc57aafc.png)


### 今回気づいたこと
![Web 1366 – 90.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/81115abb-a9e2-7c20-06a1-6e38c4d7c602.png)

### 上記を踏まえて実装したもの
![Web 1366 – 92.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/67f6d047-a186-8a81-c7dd-1512ccba782f.png)


## 次までのスケジュール
卒論執筆に向けた調査を中心に動く。
![スクリーンショット 2021-12-13 2.39.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466470/157ce67f-9b45-b323-0e97-77620952164c.png)
NotionでGitHubのプレビューを表示する

アルプ株式会社でエンジニアをしています、集約のエンティティ@pictinyです。
これは[Notion Advent Calendar 2021](https://qiita.com/advent-calendar/2021/notion) 12日目のエントリです。
11日目は[NotionでJiraのプレビューを表示する](https://qiita.com/pictiny/items/16cc91e44da47ca0b9bd)でした。

# Github連携
Notionでは認証が必要なコンテンツのURLで[ブックマーク](https://qiita.com/pictiny/items/745cfcf562c6429a3efc#%E3%83%96%E3%83%83%E3%82%AF%E3%83%9E%E3%83%BC%E3%82%AF)を作ると、faviconやドメインが展開されるだけでコンテンツの中身が展開されません。
NotionとGitHubを連携すればブックマークの作成時に認証を突破してプレビューを表示することができます。

GitHubのPull RequestのURLをペーストすると表示される `Connect to GitHub to update` のボタンを押すと、GitHubの認証画面が表示されます。

![Screen Shot 2021-12-12 at 2.11.32 copy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/427952/ae224e4a-9f91-5dff-24a0-a71797a1c0e8.png)

認証したいアカウントでログインするとGitHubと連携でき、連携後にGitHubのPull RequestのURLをペーストするとプレビューが表示されます。

# まとめ
GitHubのプレビューもとても便利なので連携を済ませておきましょう！
ExcelでJsonファイル作成機能作ってみた※C#用追加機能あり

## 概要
Excelを用いてJsonファイルを作成するxlsmファイルです。
ある程度汎用化させているので自由な形で作成できると思います。
追加機能で、Jsonファイルに応じたC#用のクラスファイルも生成する機能も付けています。
JsonSerializerで扱うように作ってるので、
C#でデータを扱う際にはほぼ作業なく実装できるのではないかと思ってます。
GitHubに公開していますので自由に使ってみてください。
※ご意見、ご感想お待ちしております
## Gitリンク
<strong>ExcelJsonMaker.xlsm</strong>ファイルが本体です。
落としてそのまま使えるようになってます
https://github.com/ApuriDasuo/ExcelJsonMaker


## 使い方
### 「出力」シート
基本的な情報を記入します
![出力シート記入情報](https://cdn-ak.f.st-hatena.com/images/fotolife/a/apuridasuo/20211213/20211213014259.png)
<strong>▼出力開始ボタン</strong> 
必要事項をすべて記入した後、 
このボタンを押すと出力を開始します
<strong>▼出力パス</strong> 
出力先を記入することで指定できます 
※未記入でもOKです 
※出力後に自動でフォルダを開きます 
<strong>▼C#：シリアライズ用クラスファイル作成するか？</strong> 
Jsonファイルに加えて、 
C#用のクラスファイルを出力するか切り替えることができます 
<strong>▼パラメータ用型一覧</strong> 
Json作成時に、各要素の型を指定するのですが、 
指定する型のリストと、未記入時に記入する内容をここに記入します。 
自由に編集できるので好きな型と対応する初期値を記入してください
###「各Jsonファイル」シート
作成したいJsonファイルのパラメータを記入します
※１シート１Jsonファイルです
※シート数は自由に追加削除して大丈夫です
![【例】Class2シート内容](https://cdn-ak.f.st-hatena.com/images/fotolife/a/apuridasuo/20211213/20211213015158.png)
<strong>・１行目</strong>
各要素の型を選択
※リストは「出力」シートの「▼パラメータ用型一覧」参照
<strong>・２行目</strong>
各要素の名前（Key）
配列の場合は、名前の末尾に[]を記入することで配列となります
<strong>・３行目以降</strong>
各要素の値（Value）
※セル内で改行も可能です（\nに置換します）
※未記入のセルは、自動的に初期値で穴埋めします
##サンプル出力データ
落としてきたExcelJsonMaker.xlsmファイルを
そのまま出力したらサンプルになると思います。
### Master_Class1.json
![Master_Class1.jsonの内容](https://cdn-ak.f.st-hatena.com/images/fotolife/a/apuridasuo/20211213/20211213020203.png)
指定のKey,ValueがJsonファイルになっているの思います。
成形はめんどくさい+自動化するならいらないので適当にやってます
### Master_Class1.cs
![Master_Class1.csの内容](https://cdn-ak.f.st-hatena.com/images/fotolife/a/apuridasuo/20211213/20211213020423.png)
出力したJsonファイルに対応するクラスファイルになります。
VSCodeのNeo Vimでipynbを編集するとき, モード変更ができなかったので応急処置をした

##この記事の目標
* `Enter`と`Esc`でコマンドモードと編集モードを切り替えられるはずが, Neo Vimと干渉して使えないっぽいので改善する.

###目指す動作例
* `ctrl+cmd+i`でコマンドモードから編集モード(vimにおけるノーマルモード)へ.
* `ctrl+cmd+j`で編集モードからコマンドモードへ.

##方法
###keybindings.jsonをいじる.

* コマンドパレット(`shift+cmd+p`)を開いて, 「基本設定: キーボードショートカットを開く(JSON)」を検索.
* 以下のように, ショートカットを追加する.
* whenについては, 既存のショートカット(`cmd+k cmd+s`)で`notebook.cell.edit`とかを参考にした.

```json
[
    {
        "key": "ctrl+cmd+j",
        "command": "notebook.cell.quitEdit",
        "when": "neovim.mode == normal"
    },

    {
        "key": "ctrl+cmd+i",
        "command": "notebook.cell.edit",
        "when": "notebookEditable"
    }
]

```

##所感
* githubにはそれっぽいissueがあったけど, 理解できず撤退した. 
* 応急処置なので, ひどい設定の仕方(よく使う機能と競合etc)だったら許して

##参考
* https://github.com/microsoft/vscode/issues/91987
* https://github.com/VSCodeVim/Vim/issues/5238