OmniAICreator/Qiita-1.07M huggingface dataset:
レシートを読み取る

レシートをスキャンして，内容を読み取ります。今回はScanSnapを利用するのでJPEG画像ですが，PDFの場合はpdftoppmを使えば良い。

以下は，最新の機能を使っているので，プロデル1.8系では動作しません。1.9系をお使い下さい。

今回は以下の2つのレシートを読み取ります。日付と合計額を読み取ります。
![コンビニのレシート](http://nipo.jp/0_masked.png "コンビニのレシート")
![タクシーのレシート](http://nipo.jp/1_masked.png "タクシーのレシート")

## 方針

0. レシート画像を1行ずつ切り分ける
0. 切り分けた画像に対してOCR処理を行う
0. 日付と合計額が書かれている部分を抜き出す


## レシート画像を1行ずつ切り分けてOCR

プロデルのOCRは，レイアウト情報を保存しません。行毎に出力されるわけでもありません。したがって，先に画像を加工しておく必要があります。また，文字の周りに十分な余白がないと認識しません。

```プロデル
ファイル名は，「xxx.jpg」

’準備
レシート画像は，画像（ファイル名）を作ったもの。
画素配列は，レシート画像を配列化したもの。
横幅は，画素配列（1）の個数。
白い画像は，｛｝。
白い行は，｛｝。
横幅回繰り返せ
	白い点は，色情報を作ったもの。
	白い点の要素は，｛255,255,255｝。
	白い行へ白い点を追加する。
繰り返し終わり
30回繰り返せ
	白い画像へ白い行を追加する。
繰り返し終わり

’OCR開始
行区切りは，1。
読み取りテキストは，｛｝。
画素配列の個数回，行番号へカウントしながら繰り返せ
	白い画素数は，0。
	行画素は，画素配列（行番号）。
	行画素を【画素：色情報】へそれぞれ繰り返せ
		各色合計は，画素の赤＋画素の緑＋画素の青。
		もし各色合計＞600なら
			白い画素数へ1を足す。
		もし終わり
	繰り返し終わり
	もし白い画素数＞横幅×0.98なら
		もし行番号-行区切りが8以上なら
			開始番号は，行区切り-1。
			もし開始番号が0以下なら開始番号は，1。
			切り出し画像は，｛｝。
			切り出し画像へ白い画像を一括追加する。
			切り出し画像へ画素配列の開始番号番目から（行番号-開始番号+1+1）個切り出したものを一括追加する。
			切り出し画像へ白い画像を一括追加する。
			切り出し画像を画像に変換して「temp.jpg」へ保存する。
			一行テキストは，OCRで「temp.jpg」を読み取ったもの。
			もし一行テキストが「」でないなら
				一行テキストを読み取りテキストへ加える。
			もし終わり
			行区切りは，行番号。
		もし終わり
	もし終わり
繰り返し終わり
```

準備のところで作っている`白い画像`は，余白です。切り出した画像の上下に貼り付けます。

行の切れ目の判定は，白い画素が98％を超えているかどうかで行います。
白い画素かどうかは，RGBの値の合計が600/765より大きいかどうかで判定します。

レシートは傾いておらず，行の切れ目はきれいに白くなっていることを前提としています。

切り出した画像はtemp.jpgに保存し，そのファイル名をOCRに渡しています。

`もし行番号-行区切りが8以上なら`の部分は，文字の入っていない（最低でも縦8ピクセルはないと文字は入っていないと判断）部分にOCRをかけるのは時間の無駄であるために用意しています。

また，白くない部分の上下1ピクセルも切り出し画像に含めています。

読み取る文字がなかった場合，「」が返ってきますので，この場合の結果は捨てます。

## 日付と合計額の抽出

正規表現で抽出します。

```プロデル
’後処理
日付は，「」。
金額は，「」。
読み取りテキストを一行テキストへそれぞれ繰り返せ
	一行テキストは，正規表現で一行テキストを「「[\s　，,]+」」から「」へ置換したもの。
	’日付？
	日付候補は，一行テキストから「「[０-９0-9]+年[０-９0-9]+月[０-９0-9]+日」」という正規表現で取り出したもの。
	もし日付候補の個数が1なら，日付は，日付候補（１）。
	’金額
	金額表現候補は，一行テキストから「「合計|合言十|合十」」という正規表現で取り出したもの。
	金額候補は，一行テキストから「「\d+」」という正規表現で取り出したもの。
	もし金額表現候補の個数が1かつ金額候補の個数が1なら
		金額は，金額候補（1）。
	もし終わり
繰り返し終わり
日付を報告する。
金額を報告する。
```

## 実行

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/150160/7e9dff8d-ac4b-2192-469c-c1ee3251ee8d.png)

読めました！！
アウトプットって、承認欲求だったの

私はとてもめんどくさがり屋です。

しかも、なんでも自動化したくなってしまう癖があります。

しかも、あまり文書を書くのが（口で言うのも）へたくそです。

ですが、平成時代にスーパーファミコンのアダルトゲームを作った、ってほどですので
それほどの年になっているにも関わらず
結婚すらできていません。

:::note info
まぁ、婚約した方との交通事故死があったのですが、、、寂しい思いを常に感じています
:::

## 当社ホームページ（正確にはWordpressテーマ）のリニューアルをしていました

はじめてのphpがWordpressテーマです。

:::note info
ガチでmysqlを操作するよりかはマシですが
:::

わからない所ばかり、google先生に頼ろうとするも
あまりの検索キーワードの多さで、私がロボットとみなされ、
ついにgoogle検索から追い出されているほどです。

普通なら本で勉強したいところですが、
検索で得ようとしたところです。

:::note info
確かに昔は本で勉強しましたが、最後に購入した本は Windows NT 4.0に関するものです
:::

あまりの検索数を確保するために、デフォルトをduckduck go にしたのですが

## 別にイライラしているわけではないが寂しい

なんか、病み垢と同じです

見てもらう、っていう承認欲求が欲しかったのです。

とかいって

https://neet.co.jp/

うちのような会社、給料1円も出ませんので

Wordpressのテーマ書けるような人は在籍していないと考えます

社内SNSにアウトプットしても、意味不になる。

結論として、qiitaにアウトプットすることで、承認欲求をしてしまったのです。
OGP画像を動的に自動生成する方法



## この記事の概要

- OGP画像を動的に自動生成したい
    - 例1：記事のタイトルをテキストとして画像内に入れたい
    - 例2：記事の作成者のアイコンを画像内に入れたい
- SNS投稿時のOGP画像を動的に変えたい

### イメージ

![https___cdn.qiita.com_assets_public_article-ogp-background-9f5428127621718a910c8b63951390ad.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531593/991c8559-f72c-777b-152b-a3e5455335f2.png)

こんな感じで、記事のタイトルや、作成者の情報を土台の上に貼り付けて１枚の画像としてOGPにしたい

## 利用するサービス

- [Cloudinary](https://cloudinary.com/)


## Cloudinaryとは

![スクリーンショット 2022-12-03 20.08.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531593/1918f655-9b89-39b0-01e3-c41a1821e0f7.png)

https://cloudinary.com/

Cloudinaryは、画像を管理できるクラウドサービスです。
画像をアップロードするだけでURLが割り振られ、URLに変数を追加することで、画像を動的に変えることができます。

例えば

- 画像の上に文字を追加する
- 画像の上に別の画像を追加する

などなど、

OGP画像を生成するタイミングで、そのページのTitleを自動的に乗せたい時なんかにも活用できます。

### 無料プランがあるのが嬉しい

Cloudinaryには、プランが複数ありますが、フリープランなら無料で使えます（これは嬉しいですね）
登録方法は簡単で、メールアドレスとパスワードを入力してアカウントを作成するだけです。

## Cloudinaryの使い方

Cloudinaryの使い方はとっても簡単です。
調べてみるとたくさん出てきたので、有識者さんたちの記事を載せておきます。

https://kanaxx.hatenablog.jp/entry/cloudinary/first-step

https://dev.classmethod.jp/articles/top_10_tips_for_making_cloudinary_work_well_for_you/

https://jsnotice.com/posts/2022-02-02/index.html

簡単に説明すると、

- OGP画像に使いたい背景画像をアップロードする
- 生成されたURLをルールに基づき編集し動的に変更されるようにする

## 1:OGP画像に使いたい背景画像をアップロードする

まずはOGP画像に使いたい背景画像を作成してアップロードします。

![image_base.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531593/a318ea12-4502-b331-8dad-fe48557d9c97.jpeg)


## 動的URLの生成方法

Cloudinaryに登録して、画像をアップロードすると以下のようなURLを取得できます。

```
https://res.cloudinary.com/hoge/image/upload/v0000000/image.png
```

Cloudinaryは、上記のURLに記述をすることで、画像を動的に変えることができます。

例えば、

```
https://res.cloudinary.com/hoge/image/upload/l_text:font_name:記事のタイトル,w_500,c_fit/image.png
```

ブラウザに打ち込めば、記事のタイトルが画像の上に表示されています。

![image_base_n7ne9m.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2531593/6079a37d-bf2d-bf56-af91-2774d3094c41.jpeg)

文字以外にも画像を入れることができたり、文字の配置も自由に設定できます。
また文字のフォントもアップロードすることで、自由に変更が可能です。

Cloudinaryでのフォントの追加方法はこちらがおすすめです

https://boook24.com/?p=1326

## さいごに

OGP画像のURLが準備できたら、文字部分を動的に変更されるようにプラグラムを変更しましょう。

```
<meta property="og:image" content="https://res.cloudinary.com/hoge/image/upload/l_text:font_name:記事のタイトル,w_500,c_fit/image.png"/>
```

これで動的なOGP画像を自動生成できます。
Azure P2Sをカスタイマイズする01

# Azure P2Sのカスタマイズを行いたい
以前の記事から派生したです。
WindowsでのAzure P2Sを想定しています。

派生元の記事はこちらです。
最初の記事[AWS Client VPNとAzure P2S 機能比較 01~AWS Client VPN構築編01~](https://qiita.com/hidekko/items/5dc7de8f3cde645959b2)
2番目の記事[AWS Client VPNとAzure P2S 機能比較 02~AWS Client VPN クライアントPC設定編~](https://qiita.com/hidekko/items/c7e65dbd5985ec260c9f)
3番目の記事[AWS Client VPNとAzure P2S 機能比較 03~Azure P2S構築編~](https://qiita.com/hidekko/items/0ba2fb85b6c89da5fe84)
4番目の記事[AWS Client VPNとAzure P2S 機能比較 04~Azure P2S クライアントPC設定編~](https://qiita.com/hidekko/items/44bb46daf35d3ba91b41)

特に4番目の記事、[AWS Client VPNとAzure P2S 機能比較 04~Azure P2S クライアントPC設定編~](https://qiita.com/hidekko/items/44bb46daf35d3ba91b41)の設定変更です。

## 具体的にどこの設定変更なのか？
ここの赤枠内の画像の変更です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/ba3e368c-cdc1-4d58-3484-98edfedd28c3.png)

ここの画像を会社のロゴや社章、シンボルマークに変更することが可能です。
ただMicrosoft公式には一切載っていませんのであくまで自己責任でお願いします。

## 設定変更方法は？
Azure P2Sのインストールディレクトリ内に画像があるので、これを差し替えます。
インストールディレクトリは
```
%userprofile%\AppData\Roaming\Microsoft\Network\Connections\Cm\{16進数の乱数}
```
ですので、ここのディレクトリをまずは開きます。
開いてみるとこうなっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/224b4221-1638-28a3-f658-63357a91d059.png)
[azurevpnbanner.bmp]という画像があるのでこれを差し替えます。
サイズは<font color="Red">**330×140ピクセル**</font>です。

## 実際に変更してみる
特別なアプリケーションを使うのは面倒ですし、ユーザフレンドリーではないので、WindowsにデフォルトでインストールされているMSペイントを使います。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/de6b4f7f-0f80-76aa-85c2-4ece2587c711.png)
330×140ピクセルを指定して、適当に文字を打ちました。
それぞれの会社のロゴや、社章、シンボルマークにしてください。
<font color="Red">赤枠</font>が元々の画像データです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/73d8a344-5aa2-ceb3-ec97-991184461ee2.png)
そしてこちらの赤枠が新しく作った画像データです。
元々test.bmpという名前だったものをazurevpnbanner.bmpに名前を変更しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/f12df041-edca-fff5-5508-580ffedd7aa3.png)
そしてAzure P2Sを起動すると、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/643392/e1385a05-7c54-f628-2d76-d75e305b5ec2.png)
ご覧の通り画像が変更されました。

再起動の不要ですし、すぐに設定が変更可能です。

本日はここまで。
仕事で使えそうな 競プロ御用達crate紹介

# 前説
AtCoderでのRustで使えるcrateで使えそうなものを独断と偏見で紹介します。
Rustのバージョンは結構古いので(v1.42.0)そこはご注意ください。

# 紹介
- regex
https://crates.io/crates/regex

Rustで正規表現を使うときのデファクトスタンダードみたいなcrateです。

- rand
https://crates.io/crates/rand

Rustで乱数を使うときのデファクトスタンダードみたいなcrateです。

この辺は有名すぎるかなということでさらっと流します。

- maplit
https://crates.io/crates/maplit

hashmapやhashsetをmacroで作ることができるcrateです。
```Rust
let map = hashmap!{
    "a" => 1,
    "b" => 2,
};

let set = hashset!{"a", "b"};
```

- superslice
https://crates.io/crates/superslice

二部探索をサポートしてくれるライブラリです。vecにもbinary_searchというメソッドがありますが、さがす値が複数配列にあった場合どれが取れるかが不確定だったり、見つからないとerrorが返ってくるというのがあります。
このcrateの場合は複数あった場合は左端、なかった場合は右端を返すという挙動をします。また複数あった場合にその範囲をとるメソッドなどもあります。

```Rust
let s = [0, 1, 1, 1, 2, 3, 5];

assert_eq!(1, s.lower_bound(&1));

assert_eq!(4, s.upper_bound(&1));

assert_eq!(1..4, s.equal_range(&1));
```

- itertools
https://crates.io/crates/itertools

Iteratorを拡張するcrateでかなり多機能で便利です。vecとiteratorのメソッドをそれぞれ使うために型を反復横跳びする手間をぐっと減らしてくれます。

iterのままユニークにしたり、ソートしたりや
```Rust
let i = [1, 6, 9, 3, 5, 6].iter();
  i.clone().unique();
  sorted(i);
```

組み合わせの列挙などもできます。
```Rust
let i = [1, 6, 9].iter();
  
i.clone().combinations(2);
i.permutations(2);
```

# まとめ
itertoolsが便利。
anacondaとvirtualenvを使う〜仮想環境でエラー解決〜

Flaskでアプリ制作をして特に大きく躓いたところが２つあった。
一つはデータベース周り、もう一つはデプロイの際のトラブルだ。

しかしこれら二つをあっさり解決してくれたのが仮想環境だったので今回はanacondaとvirtualenvの使い方をメモしたい。

まずはanacondaとvirtualenvをインストールしよう。


https://www.anaconda.com

👆のサイトからダウンロード。意外と簡単だった。


```
$  pip install virtualenv
```
👆こちらがvirtualenv。ターミナルでインストールしよう。これも簡単。

この二つがインストール完了したらまずはターミナルでanacondaから設定開始。

まずは以下のコマンドを打ちましょう。

```
conda create -n ○○○○ python=○.○
```

○○○○の部分は好きな仮想環境名をつけて下さい。　python=○.○はお使いのpythonバージョンを入力。



以下のコマンドで作成した仮想環境を確認できます。
```
conda info -e
```


### VS CODEで立ち上げる　

次はVS CODEを開いて任意のファイルを開く。

表示→コマンドパレットから、検索窓でsettings.jsonと検索。
![スクリーンショット 2022-12-03 11.16.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2980135/eb22eb62-9c27-d740-467a-9ec124804139.png)

jsonファイルが開くので中に👇を記述

![スクリーンショット 2022-12-03 11.19.28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2980135/be736deb-bbe5-3edd-05ee-72d60c685c7b.png)

（何故か文字色が濁ってる・・。本来ならもと鮮やかな色になってます。）

○○○○には先ほど作成した仮想環境名を記述。

このあとは通常通りpythonファイルを作成。その後にvirtualenvを設定します。

### Virtualenvの作成

ファイルを作成したらVS CODE内でターミナルを立ち上げる。

```
$ virtualenv ○○○○
```

👆のコマンドで作成。 ○○○○の部分は好きな名前を。

新たにvirtualenvファイルが作成されます。

さらに続けてこの仮想環境を有効化。以下のコマンドを入力。

```
$ source ○○○○/bin/activate
```

これで完了。意外とあっさり終わりました。
あとは必要なライブラリーをインストール。ここから普段通りにコードを書いていきましょう。


### まとめ

仮想環境ってなんか敷居高そう・・って勝手に思ってて今まで食わず嫌いで放置・・しかしアプリ制作の時に痛い目に合いました。

まずデータベースの作成が出来ない！これは色々調べたけど結局謎のまま・・。多分私のMacとかVS CODE環境が原因か？

以前の記事👇で with app.app_context()を使い無理やりデータベースを作成しましたが何故かテーブルが存在しないというエラーも出る始末。



https://qiita.com/sasao-genmaicha/items/57e2c6758e1aa8df7ae0

堪忍して仮想環境使いましたがあっさり解決。

そして最後にアプリが完成したらネット上に公開。この時はherokuを使用。
デプロイの際には使用したライブラリをheroku側に教える必要があるんだけど仮想環境なしだと今までインストールした全てのライブラリが集められる。
余計なライブラリも含まれるのでもちろんheroku側でエラーになる。

この時に仮想環境の恩恵が受けれる。まっさらな新しい仮想環境なので余計なライブラリーが無い。
だからデプロイの際は必要最低限の量でherokuに登録ができる。


以上のことを踏まえてこれから（面倒くさがらず）毎回仮想環境を使用したいと思う。
Linux Networking協会という団体を作ってみました

色々やりたいことはあるんですが、仕事も忙しいのでとりあえず発足の通知のみ

2022年12月3日時点で84名の方達に参加してもらっています。


ご興味のある方は是非
https://join.slack.com/t/linux-networking/shared_invite/zt-1k6uq1dqo-BYmOyIG0YQ7G51OiPubrkQ
プロデルから.NETのクラスライブラリを使う

今回は、プロデルのネット型を使って.NET Frameworkのクラスを呼び出す方法を紹介します。

プロデルには様々な機能を日本語でプログラムするためのプロデル専用のライブラリがあらかじめ用意されています。一方でプロデルそのものは.NET環境で動作するため、.NETのクラスライブラリを一応直接利用することもできます。(複雑にはなりますが)

今回は、プロデルから.NET Frameworkの機能を利用してみます。なお今回紹介する方法は、プロデルで想定している本来の使い方からやや外れています。より作りこむには.NETの知識が必要となります。また、プロデルの制約などの理由で正しく動作しない機能もあります。

プロデル専用のライブラリでは実現できないことをどうしてもプロデルで実現したいというときにご活用ください。

## ネット型
プロデルで.NETのクラスライブラリを利用するには、「ネット型」を使います。
プロデルでは、純粋な.NET(FCL)の型を「ネット型」と呼びます。ネット型を使うには、次のような書式で書きます。

```:プロデル
"【クラス名】"のネット型を作る
"【完全なクラス名】,【アセンブリ名】"のネット型を作る
```

クラス名には、名前空間を含むクラス名を指定します。プロデルではusingキーワードが使えないため、名前空間は省略できません。また完全修飾型名で指定することもできます。
【アセンブリ名】には、DLLファイルに宣言されたアセンブリ名を指定します。つまりVisual Studioのソリューションで参照するときのアセンブリの名前を指定します。GACに登録されたアセンブリでは、DLLファイルのパスを指定せず、アセンブリ名を指定すれば、参照できます。

使いたいクラスのアセンブリ名を調べるには、次のようなプログラムで確認できます。
```:C#
Console.WriteLine(typeof(Button).AssemblyQualifiedName);
//System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
```

コンソールに表示された名前は、先頭から2つ目のカンマまでがネット型に指定する完全なクラス名とアセンブリ名です。
```:プロデル
"System.Windows.Forms.Button, System.Windows.Forms"のネット型を作る
```



## メソッド呼び出し
プロデルでメソッドを呼び出すには、次のような書式で書きます。

```:プロデル
【オブジェクト名】:【メソッド名】(引数)
```

C#やVB.NETでは「.」と書くべきところがプロデルでは「:」となります。「:」はプロデル上でレシーバオブジェクトを表す記号です。引数には、メソッドに渡す値を指定します。引数は省略することができ、また複数の引数を指定するときには「,」で区切ります。なお助詞は指定できません。

## プロパティへのアクセス
プロデルからプロパティの値を取得したり設定したりするには、次のような書式で書きます。

```:プロデル
【オブジェクト名】の【メソッド名】
```

C#やVB.NETでは「.」と書くべきところがプロデルでは「の」となります。プロデルではプロパティが設定項目として扱われているため、設定項目と同じように扱われます。

## 列挙型の値
プロパティやメソッドの引数によっては列挙型の定数値を指定する場合があります。プロデルでは列挙型の定数名を文字列で指定します。

## イベントハンドラの設定
オブジェクトのイベントを手順で受け取るには、次のような書式でイベントハンドラを指定します。

```:プロデル
【オブジェクト名】の【イベント名】時の手順は、【呼び出す手順】
```

プロデルでは、イベントがイベント手順と同じ機能ですので、イベント手順を設定する代入文で指定します。

イベントが発生した時の引数(一般に変数名e)は「この時」特殊変数に保存されます。「この時」特殊変数もネット型のオブジェクトですが多くの場合、そのまま操作できます。

## 値の型変換
文字列(string型)や整数(int型)、PointやSizeなどよく使われる構造体は、プロデルの型と対応付けられています。そのため、多くは文字列または配列で代入することで適切な型へ変換されます。

## プログラム例
2つの例を掲載します。一つ目は、StringBuilderクラスのインスタンスを生成して操作するプログラムです。C#やVB.NETの文法ではなく、あくまでもプロデルの文法に則ってメソッドやプロパティを操作します。

動作環境:[プロデル1.9.1163](https://rdr.utopiat.net/files/1.9/index.php?type=exe)

```文字列の連結.rdr
builderという"System.Text.StringBuilder"のネット型を作る
builder:Append（「こんにちは」）
builder:Append（「さようなら」）
「[builderのLength]:[builder:ToString()]」を表示する
```

二つ目に、Windowsフォームでボタンを配置するプログラムです。
フォームデザイナが使えないため、Visual Studio上のC#で書く場合とも勝手が違いますが、一応フォームを表示させることができます。なお、Size型やPoint型、フォーム関連の一部の列挙型は、プロデルの標準の型に自動的に変換される仕組みになっています。

また、プロデルデザイナ上でのプログラムは、UIとは別スレッドで実行されているため、明示的にUIスレッドで実行させる必要があります。(プロデルの種類では自動的にUIスレッドで実行されます)

```Windowsフォーム.rdr
UIスレッドで『
	窓という"System.Windows.Forms.Form, System.Windows.Forms"のネット型を作る
	ボタンという"System.Windows.Forms.Button, System.Windows.Forms"のネット型を作る
	窓のTextは、「WinFormsのテスト」
	窓のFormBorderStyleは、「固定ツール」
	ボタンのLocationは、{30,30}
	ボタンのSizeは、{126,40}
	ボタンのTextは、「OK」
	ボタン:Show()
	窓のControls:Add(ボタン)
	窓:Show()
』を実行する
ボタンのClick時の手順は、クリックさせた
窓のClosed時の手順は、閉じられた
待機

クリックさせた手順
	「こんにちは」を表示する
終わり
閉じられた手順
	終了する
終わり
```
ポケモンしりとりを作りながらFlutterに入門する

ポケモンしりとりを作りながらFlutterに入門します。

## この記事を書こうと思ったきっかけ
- Flutterに入門したい
- ポケモンバイオレットを買ったのでポケモン関連で何か作りたい

## 作りたいもの
【ポケモンしりとり】
仕様は下記のような感じをイメージしています。
- ボタンを押してスタート
- 最初にランダムにポケモンの名前と画像が出る
- 音声入力でしりとりしていく
- 制限時間は1匹10秒以内
- 正解するとポイントが貯まる
- ポケモンによって獲得できるポイントが変わる

※1人でやるしりとりです

## 動作環境
- Mac OS X: 13.0 Ventura 
- Flutter: 3.3.8
- Dart: 2.18.4
- Xcode: 14.1
- Android Studio: 2021.3.1 Patch 1 Dolphin

※最初に見たチュートリアルがAndroid StudioだったのでAndroid Studioを使っているのですが、だんだんいつも使っていて慣れているVSCodeでやりたくなってきました。

## できたこと・できてないこと
### ボタンを押してスタート
とりあえずスタートボタンを押してゲームを始めます。
<img width="150" alt="ボタンを押してスタート" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982087/af361027-b73a-e617-efeb-2dad8ee270ae.png">

### 最初にランダムにポケモンの名前と画像が出る
[PokeAPI](https://pokeapi.co/)からランダムにポケモンを取得して表示します。
<img width="150" alt="最初にランダムにポケモンの名前が出る" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982087/8e242612-6946-b60d-9e44-2b94c37faf87.png">

### 音声入力でしりとりしていく
まだ途中までしかできていないですが、
Flutterの音声認識パッケージの[speech_to_text](https://pub.dev/packages/speech_to_text)を使用して音声入力するようにしました。
また、ポケモンの名前はほぼカタカナのみで、音声入力した文字列のうちカタカナのみを取得したかったので、[kana_kit](https://pub.dev/packages/kana_kit)を使用しました。
（「フシギソウ」とかは「不思議そう」とかになってしまっていた）

入力されたポケモンの英語名をPokeAPIに渡してポケモンのデータを取得します。

しりとりのロジックはまだできてないので、音声入力したポケモンが表示されるだけ。

※PokeAPIにはポケモンの英語名を渡さないといけないので、ポケモンの日本語名/英語名をキーバリューに持つMapを作成して、音声入力の値に対応する英語名を渡すようにしています。

### 制限時間は1匹10秒以内
まだできていない。

### 正解するとポイントが貯まる
いまは1回正解すると1ポイントが取得されて、画面右上に表示されるようになっています。
※まだしりとりになっていないので、ポケモンが存在すれば正解。
<img width="150" alt="正解するとポイントが貯まる" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2982087/8487edf1-1ba0-32f2-a35c-f418ecc217ff.png">

### ポケモンによって獲得できるポイントが変わる
これもまだなのですが、ポケモンの世代が新しいほど高得点とかにしようかなと考えてます。


## 学んだこと
上記を作る中でFlutterの下記のようなことが少しわかってきました。
- Widgetの使い方
- パッケージの使い方
- APIの呼び方

## 今後やりたいこと
アプリの機能追加としては下記をやってみたいところです。
- デザインをかっこよくする
- 効果音とか出ちゃう
- ログインができる
- ランキングが表示される

また、Flutter入門的には下記についてもう少し調べてみようと思います。
- 状態管理
- ページ遷移
- プッシュ通知
- テスト
- リリースまわり
Leetcode 455. Assign Cookies

# 455. Assign Cookies

https://leetcode.com/problems/assign-cookies/

## 難易度
### Easy

## アプローチ
### Greedy

```java
class Solution {
    public int findContentChildren(int[] g, int[] s) {
        Arrays.sort(g);
        Arrays.sort(s);

        int childrenWant = 0;
        int cookieSize = 0;
        int result = 0;

        for (; childrenWant < g.length && cookieSize < s.length; ) {
            if (g[childrenWant] <= s[cookieSize]) {
                childrenWant++;
                cookieSize++;
                result++;
            } else {
                cookieSize++;
            }
        }
        return result;
    }
}
```
GitHubが落ちたら仕事にならん→そのときだけ遊べるゲームを作りました！


[クソアプリアドベントカレンダー2022](https://qiita.com/advent-calendar/2022/kuso-app) 5日目担当の[@nabettu](https://twitter.com/nabettu)です！

今日は表題の通り「GitHubが落ちときだけ遊べるゲームを作ってきました！」

みなさんこの崖から落ちていく悲しきOctoCatをみたことはありますか？
![CleanShot 2022-12-03 at 19.28.54@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40154/fb6e26e5-a282-9400-96ac-d2149a35e1a0.png)

この画面が出たらエンジニアはもう仕事になりませんよね。。。

ということでそんなときのために！GitHubが500画面になると自動的にゲームが挿入されるChrome拡張を作ってきました。プレイ画面はこんな感じです。

崖の下で襲ってくるバグから逃げつづけるOctoCatをイメージしたゲームになります。
![CleanShot 2022-12-03 at 19.28.26.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40154/0826ff7a-f580-4df7-6f92-2690ca33bb2f.gif)

このChrome拡張さえいれておけば、いつGitHubが落ちても安心ですね！

## 利用方法

一応GoogleWebストアの審査には出しましたが、多分審査で落ちてしまうのでw、こちらからダウンロードしていただいて、
「Chrome設定画面→拡張機能→右上のデベロッパーモードをON→パッケージ化されていない拡張機能を読み込む」から、Zipを指定してインストールしてください。

https://drive.google.com/file/d/18zgsXlXOEk3uA4oEtu4Yr6p6hyd0p0qE/view?usp=share_link

そして遊ぶためにはGitHubに落ちてもらわなきゃならないのですが、実は500画面は /500 にアクセスすると500画面が表示できるので、ぜひこちらで遊んでみてください。

https://github.com/500

※こちらの画面で動くように作ってありますので、もしかしたら怒ったピンクのユニコーンの画面だと動かないかもしれませんｗ

## 作り方

ブラウザで動くゲームとして、今回はアドベントカレンダー1日目のDE-TEIUさんの構成を参考にさせていただきました。

こちらのゲームもPhaser(フェイザー)を使って作ってみました。

https://qiita.com/de_teiu_tkg/items/cdb6ad2972a23663dbde

さて、ゲーム単体で動くページであればこちらの記事にそって作っていただくだけでよいのですが、

これを
1. 既存の画面に差し込む形で
2. ChromeExtensionにゲームを入れて動くようにする

方法をそれぞれ解説していきます。


## 既存の画面にゲームを差し込む

今回のChromeExtionsionは動作する画面はマニフェストファイルに記述することで、github.comのみとしています。
そして500画面にあるerror_500というIDのdomがあったら動作するようにしています。

そのうえでPhaserのConfigでも同じdomを指定してそのdom内にゲームを配置しつつ、画面の真ん中に置かれるようにcssを追記しています。

```js
const errorDom = document.querySelector("#error_500");
if (errorDom) {
  errorDom.setAttribute(
    "style",
    "position: fixed;top: 0;left: 50%;transform: translateX(-50%);z-index: 100;"
  );
  startGame();
}
const config: Phaser.Types.Core.GameConfig = {
  parent: "error_500",
...省略
};
export const startGame = path => {
  new Phaser.Game(config);
};

```

## ChromeExtensionにゲームを入れて動くようにする
上記のように設定したうえで、ビルドしたjsをconsoleで実行するとそのまま動くのですが、一点問題があります。Webサイトと違ってjsと一緒に配置されていないため画像の読込ができなくなってしまいます。

そこで、マニフェストファイルに web_accessible_resources で画像を追加しつつ、

こちらの記事を参考にしてファイルパスを取得→ゲームの実行時に拡張機能内の画像パスを読み込んでゲーム内に展開する。という方法で実現しました。

https://zenn.dev/seya/articles/e5687c980653e4


```js
//ゲーム読込前のパス取得
const imagePath = {
    octocat: chrome.runtime.getURL("images/octocat.png"),
    bug: chrome.runtime.getURL("images/bug.png"),
    bg: chrome.runtime.getURL("images/bg.png"),
  };

//ゲーム内での読込
this.load.image("octocat", imagePath.octocat);
```

以上がChromeExtionsionで動くゲームを既存のサイトに挿入する方法でした！

ソースコードはこちら

https://github.com/nabettu/OctocatRun

明日は@Gonsunaさんよろしくお願いします！
Reactで作成したアプリをGithub Pagesへ公開


# Reactを静的サイトとして公開できるらしい
ReactをGitHubPagesへ公開する手順書です。

[ソースコード]
https://github.com/saisai-web/Neko
[公開GitHub Pages]
https://saisai-web.github.io/Neko/

初めは公開ディレクトリ(/docs)とかで直接やる方を検討していたんですが、gh-pagesを使った
やり方の方がシンプルでやりやすかったのでそちらを記載します。

# 前提条件
・MacOS
・GitHubアカウント作成済み
・NodeJSインストール済み

# 手順
## GitHubにリポジトリを作成する
Newから新しいリポジトリを作成してください。
![スクリーンショット 2022-12-03 19.19.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803173/b73a12f5-9215-aa2e-b6da-cf016c410352.png)

リポジトリ名は任意で、CreateRepositoryできれば完了です。
![スクリーンショット 2022-12-03 19.20.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803173/1bae2ef7-9da9-f9bf-93bc-1e2f4cc2512e.png)
作成したリポジトリは後で使用します。
## TerminalでReactプロジェクトを作成
```console:
$ npx create-react-app プロジェクト名
$　　cd プロジェクト名
```

## 必要なパッケージ等もインストールする
Github-Pagesで公開する際に必要なライブラリをインストールします。
```console:
$ npm install gh-pages --save-dev
$　　npm install cross-env --save-dev
```

## package.jsonを編集する
scripts欄の、buildは下記に変更し、deployは追記してください。

```json:~/プロジェクト名/package.json
{
  ...,
  "scripts": {
    ...,
    "build": "cross-env PUBLIC_URL=/<リポジトリ名> react-scripts build",
    "deploy": "npm run build && gh-pages -d build"
  },
}
```
## TerminalからGitHubへアクセス
deployする前に、初めに作成したgithubリポジトリを登録しておく
```console:
$ git remote add origin https://github.com/<Gitユーザー名>/<リポジトリ名>.git
```
## deployして完了

```console:
$ npm run deploy
```
deployが完了すると作成したgithubリポジトリにgh-pagesブランチが作成されているのが確認できる
## 公開URLをクリック
github項目のActionから確認できる
![スクリーンショット 2022-12-03 19.37.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1803173/19868401-d9f0-6d48-84c1-bb001b48a7c8.png)
deployの欄のurlから作成したアプリを閲覧できる
Livewireを使っててAlpine.jsを使わないのは誠に罪深きことでございます。

# Alpine.jsはLivewireと連携できるメソッドが用意されている
Alpine.jsとLivewireは同じ開発者([Caleb Porzio氏](https://twitter.com/calebporzio))らしく、ゆえにAlpine.jsにはLivewireに適したライブラリとなっています。
あと、Livewireのドキュメントにも<b>「Livewireを使う開発者ならAlpine.js使っとるよなぁ？(意訳)」</b>と書いてます。
![CF106AE2-8B0A-4459-BDD6-5383CE52056C.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311883/1cfbb5f5-adfc-5dbf-bd67-44cfe74c51c7.jpeg)
引用元：https://readouble.com/laravel/9.x/ja/frontend.html


トッピングって言い方カワイイ



## メソッド・プロパティの例
### ①$wire
![726EE4DE-B4E9-4DC9-B5CD-2D0BE0B791DA.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311883/f6a15b48-8c81-1b70-9486-8344aabee78e.jpeg)
引用元：https://readouble.com/livewire/2.x/ja/alpine-js.html

  Livewire側で定義したメソッドを使える。クリックイベントと一緒に使ったらAlpine.jsのx-on:clickでLivewireのメソッドを呼び出せる。
(必要かどうかはﾜｶﾗﾝﾃｨｳｽㄟ( ･ө･ )ㄏ)

### ②＠entagle
![A3B21C5D-2D84-4736-8E20-79E9C9E9B731.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311883/c1e033bf-8465-004f-cafb-4ff58508652c.jpeg)
引用元：https://readouble.com/livewire/2.x/ja/alpine-js.html

Livewire側で定義したプロパティが使える。
これは便利かも。
使用する場面としては、Livewire側でデータを更新したあとにそのデータを受け取る時に使えそう。

# その他Alpine.jsを使う理由

### ①<b>Vueみたいにフロントエンド全般を作るライブラリは流石に過剰な気がする</b>
Livewireがデータ取得や更新を行ってくれるので、Alpine.jsはBladeファイルのDOM操作のために使うのが役割として合ってます。
なので、Vueみたいにフロントエンド全般を作るライブラリは流石に過剰だと思いまぴた。

### ②<b>てかVue使うならLivewire使わんのでは</b>
Vue × Livewireの組み合わせなんてのは公式ドキュメントには書いて無さそうだ。
むしろVue使うなら<b><font color='red'>「Vue × InertiaがLaravelとVueを活かせてめちゃヨシ子！！」</b>と公式ドキュメントに書いております。
↓↓↓
![19D3B9BC-F66F-45AD-A2D0-5D0058228687.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1311883/f540b3e6-a5b4-e0bc-b2e7-4ee05570402f.jpeg)
引用元：https://readouble.com/laravel/9.x/ja/frontend.html

::: note
1個目で述べたけどやっぱりVueとLivewireは役割が被ってるとこあるっぽいからそもそもVueは使わなさそうです。
2人は互いに交じり合わないねじれの位置にいるってワケ。
(ヲタクとアイドル的な。)


:::


# まとめ
Livewire使うならAlpine.jsを使おう。
もしVue,React使うならInertiaを使おう。
リストボタンにVisualforceページを設定する方法

## やりたいこと
* 詳細ページリンク/詳細ページボタン等に設定できるVisualforceページをリストボタンにも設定したい

## 方法
* Visualforceページのpageタグに`recordSetVar`の属性を追加
* recordSetVarを使用するにあたり、対応するApex classに`ApexPages.StandardSetController`クラスを追加

## 参考
- https://developer.salesforce.com/docs/atlas.ja-jp.pages.meta/pages/pages_quick_start_massupdate.htm
- https://tyoshikawa1106.hatenablog.com/entry/2013/09/03/232942
オブジェクト項目の数式を使ってVisualforceページのリンクを作る

# やり方
1. オブジェクトマネージャからカスタム数式項目を作成
2. 数式の戻り値のデータ型：テキストを設定
3. 数式にHYPERLINK関数を用いてリンクページを設定する
```
HYPERLINK("/apex/VISUALFORCE_NAME?id=" + Id , "Download", "_self")
```
上記の例では自身のオブジェクトのId項目を引数に与えている。
HYPERLINK関数については[こちらの公式ヘルプ](https://help.salesforce.com/s/articleView?id=sf.tips_for_using_hyperlink_formula_fields.htm&type=5)を参照。
#mros2 どうですか？ in 2022

この記事は[ROS2 Advent Calendar 2022](https://qiita.com/advent-calendar/2022/ros2)の3日目の記事です．

# この記事について

巷で話題のmROS 2，お手軽に試してみませんか？？
組込みマイコンボードから通常のROS 2ノードとダイレクトにTopic通信できます．agent的なものは不要なので，ボードを ROS 2 network に差し込むだけで，Plug & Play的に通信が始まります！

https://github.com/mROS-base/mros2

~~2022/09/31~~ 2022/10/01に，こんなイベントをやりました．

https://algyan.connpass.com/event/259028/

いやmROS 2ってなんやねん？という方は，まずはコチラをご一読ください．

https://speakerdeck.com/takasehideki/ketukiyokumros-2tutenannanoka

ハンズオン資料は Google Docs にてドバっと公開しております．

https://docs.google.com/document/d/14tb6riEkbYYiEMxBEIIdI4j2KYm1JenvI23AvOBuCHU/edit?usp=sharing

上記のプレゼンと，当日のハンズオン風景を垂れ流し録画したYouTubeアーカイブも公開されています．ぜひ合わせてご覧ください．

https://www.youtube.com/watch?v=Hjo1ZfefjL4

# mROS 2 on ROSCon 2022!!

今年はようやっとROSConで発表できました！
すでにスライドと動画アーカイブが公開されていますので，こちらもどうぞです．

https://speakerdeck.com/takasehideki/mros-2-yet-another-runtime-environment-onto-embedded-devices

https://vimeo.com/showcase/9954564/video/767150435

このプレゼン中の**論よりRUN Part3**のデモは，[イーソル](https://www.esol.co.jp/)の皆々様から本当にawesomeな貢献をいただきました．何度でも見て欲しい！

https://twitter.com/takasehideki/status/1584488359808102402

# 問合せ先

いごいた！動かしてみたいけどあかん！こんなんやりたいねん！！
などなど，Twitterで [@takasehideki](https://twitter.com/takasehideki) にMentionするか， #mros2 とかハッシュタグつけてお知らせください．たまにエゴサってみたときにそんなようなTweetにあとで気づいてしまうと，割りと悲しいので,,, （いやっエゴサってんのかい）
mROS 2を使ってみたい方や育ててみたい方，全力でサポートします！

いやまずボードが手に入らんねん！てな問合せ以外でしたら，遠慮なくお知らせください．それは私も困っています;(

# 蛇足

ホントは前日の @HansRobo くんの素敵な記事[「ROS2でヘッダファイルのインストール先が変わったらしい」](https://hans-robo.hatenablog.com/entry/2022/12/01/235528)を受けて書きたいネタがあったのですが，きちんとした検証が間に合わず,,, （その前の下地作りでコケてしまっています
とはいえ担当日を飛ばすのもアレなので，今年を振り返るという名目でお茶を濁させてください;(

ROS 2のアドカレに「カレンダー2」が錬成されているので，12月中に間に合えばそっちに追って投下します:pray:
Unity Timelineのカスタムクリップで独自のパラメータをアニメーション化する方法

# 概要
この記事ではUnityのTimelineのカスタムクリップで使うパラメーターのキーフレームアニメションを作成する方法について書きます。カスタムでトラックを作って、アニメーションのように詳細に制御したいという時に、下の画像のように設定できるようにします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/104976/e1dcbc55-ed9a-ae7f-c8a3-c6f47c533f54.png)
カスタムクリップの作り方はこちらなどを参考に
https://tips.hecomi.com/entry/2022/03/28/235336

# やり方
やり方は以下二つを行うことで可能になります。
* 作成したPlayableBehaviourを[Serializable]にする
* PlayableAssetにPlayableBehaviourのクラスを**public**で持たせておく

以下テスト用のサンプルです。
シリアライズされた少数型の変数をキーフレームで制御することが可能です。


``` cs:ExamplePlayableAsset.cs
using System;
using UnityEngine;
using UnityEngine.Playables;

[Serializable]
public class ExamplePlayableAsset : PlayableAsset
{
    public ExamplePlayableBehaviour behaviour = new ExamplePlayableBehaviour();

    public override Playable CreatePlayable(PlayableGraph graph, GameObject go)
    {
        ScriptPlayable<ExamplePlayableBehaviour> playable =
            ScriptPlayable<ExamplePlayableBehaviour>.Create(graph, behaviour);
        return playable;
    }
}
```

``` cs:ExamplePlayableBehaviour.cs
using System;
using UnityEngine;
using UnityEngine.Playables;

[Serializable]
public class ExamplePlayableBehaviour : PlayableBehaviour
{
    //キーフレームで制御可能
    public Vector3 Vector3;
    public Color Color;
    public float Float;
    public double Double;
    
    //キーフレームで制御不可
    public string Text;
    public int Int;
}
```


# 参考
タイムラインをカスタマイズしたい場合はこちらの動画の視聴をお勧めします。
Mixerについてなど網羅的に解説されているため、この動画から入門するのがおすすめです。
今回の内容については40:30頃に解説されています。

https://youtu.be/6SPpjSKy9LI?t=2436
Salesforce で関連リストが複数形で表示されない時の変更方法

# Salesforce で関連リストが複数形で表示されない時の変更方法

## 問題
関連リストのオブジェクトの表示ラベルが複数形にならない。
これのせいでTrailheadのmodule/projectのChallengeがエラーになったりする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238022/224f0695-7070-8021-756a-c8c76bd04d77.png)
画像例のSupplyがそう。

※この問題でエラーが発生するTrailhead Challengeの例
https://trailhead.salesforce.com/ja/content/learn/projects/workshop-battle-station/battle-station-3

## 原因
複数形が存在しない言語（日本語など）でカスタムオブジェクトを作成すると、Plural Label（表示ラベル(複数形)）が未定義のまま作成される。
その状態でページレイアウト設定を行うと、関連リストが単数形の表示ラベルとなる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238022/4fd1656a-3be4-2237-e8a8-a5073522ec23.png)
オブジェクトマネージャでPlural Label が空白だった場合がそう。（参考画像では設定済み）


## 解決方法
最初に名称変更を試す。
* 設定より組織情報のデフォルト言語を英語に変更
* 設定よりRename Tabs and Labels（オブジェクト、タブ、項目の表示ラベルの名称変更）でSelect Language：Englishを選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238022/7f36f0ed-ecfe-574a-998e-08715201cb98.png)
* 対象を編集
* Pluralを入力
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238022/281eb1ad-a02e-ed8d-3697-419cdd8fb697.png)


それでも反映されない場合は上書きを試す。
* 設定よりUser Interface > Translation Workbench > Override
* Setup Component を Custom Field に、Objectで対象のオブジェクトを選択、AspectをRelated Lis Labelに設定
* Related List Label Override を手動編集
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238022/d890e7a9-f38d-b7fa-d5d1-956523f521cb.png)

## 参考
- https://help.salesforce.com/s/articleView?id=sf.customize_rename.htm&type=5
- https://help.salesforce.com/s/articleView?id=sf.entering_translated_terms_in_packages.htm&type=5
- https://developer.salesforce.com/forums/?id=906F00000008uIQIAY
RNBOで簡単にVST3Instrumentを作ってみる

RNBOというMaxのアドオンがでたので早速試してみる

こんな感じのサイン波形の鳴るシンセ
モノフォニックです

MIDIを受けて
ステレオで出力します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/d44758a2-0b60-e919-a89f-c9b59f9962f6.png)

上のがrnbo~の中に書かれていて
外側のMaxのパッチはこんな感じ

midiinとdacをつなげばMax上で動作を確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/3e15e255-f30f-6e6a-8b16-3f282f428465.png)

Audio Plugin Exportを選んで
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/e942ceb8-a7e4-a12a-f00c-f2654d11e480.png)

VSTプラグインの設定をして
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/f2d68c56-c55a-772a-4dcd-822fd8247041.png)

出来たパッチをVST3InstrumentとしてExport
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/658e638e-d6e7-3f2f-f3df-d919d0ade168.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/821dc42f-8623-2171-5ac2-db921f87f9c1.png)

こんな感じでフォルダができていて
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/9cd69964-57d0-6f97-d984-683bf3719937.png)

vst3ができている！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/89779574-e73f-906d-c175-e76904e24af7.png)

これをプラグインの認識するフォルダに移して
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/43cf16bc-c67a-0718-eb80-42ccd875aec1.png)

DAW（Nuendo）を起動
VSTプラグインのところに追加されている！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/1c275d16-6c4c-3518-da1d-66441e047fdf.png)


https://twitter.com/tatmos/status/1598986088538071041

ポリフォニックにするには
@polyphonyを書くみたい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/72e4e7be-1d32-1f19-3bf8-60c09a368366.png)

param のものが外から操作できるパラメータになる
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/17c0f164-2367-06b9-dbf3-327e9b9bc8a4.png)

VST上でも操作できる　（スライダーみたいな感じになっている）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/5e63de86-7468-6542-47e7-5f85370e4bd6.png)


https://twitter.com/tatmos/status/1599028690121547776
Open3Dで点群のAABBとOBBを可視化する

たまに必要になるものの、Cloud CompareやMesh labで簡単に値をゲットする方法がなさそうなのでメモ書き。   
plyの部分は適当に読み替えてください。

```Python

import sys
import numpy as np
import open3d as o3d
import sys

ply = o3d.io.read_point_cloud("xxx.ply")
point_array = np.array(ply.points)

lines = [
   [0, 1],
   [0, 2],
   [0, 3],
   [1, 7],
   [1, 6],
   [2, 7],
   [2, 5],
   [3, 6],
   [3, 5],
   [4, 5],
   [4, 6],
   [4, 7],
]

aabb = ply.get_axis_aligned_bounding_box()
vta = np.asarray(aabb.get_box_points())
print("aabb\n", np.asarray(vta))

colors = [[1, 0, 0] for i in range(len(lines))]
line_set = o3d.geometry.LineSet(
   points=o3d.utility.Vector3dVector(vta),
   lines=o3d.utility.Vector2iVector(lines),
)
line_set.colors = o3d.utility.Vector3dVector(colors)

obb = ply.get_oriented_bounding_box()
vtobb = np.asarray(obb.get_box_points())
print("obb\n", np.asarray(vtobb))


colors_obb = [[0, 0, 1] for i in range(len(lines))]
line_set_obb = o3d.geometry.LineSet(
   points=o3d.utility.Vector3dVector(vtobb),
   lines=o3d.utility.Vector2iVector(lines),
)
line_set_obb.colors = o3d.utility.Vector3dVector(colors_obb)

# red = AABB line color
# blue = OBB line color
o3d.visualization.draw_geometries([ply, line_set, line_set_obb])
```
p5.jsで雪を降らせる

⇒<a href="https://note.nonbiri3.com/bubble2.php">実際の動作ページはこちら</a>

```html
<div id="P5Canvas"></div>

<script src="//cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.7/p5.js"></script>

<script>
var canvas;
var NUM_OF_BUBBLES = 50;
var MIN_SIZE = 1;
var MAX_SIZE = 4;
var bubbles = [];

function setup() {
  canvas=createCanvas(640, 480);
  canvas.parent("P5Canvas");

  for (let i = 0; i < NUM_OF_BUBBLES; i++) {
    bubbles.push(new Bubble());
  }
}

function draw() {
  background(0);
  for (let b of bubbles) {
    b.move();
    b.show();
  }
}

class Bubble {
  constructor() {
    this.x = random(width);
    this.y = height;
    this.r = random(MIN_SIZE, MAX_SIZE);
    this.speedY = random(-2, -1);
    this.lightX = random([-1, 1]);
    this.lightY = random([-1, 1]);
  }

  move() {
    this.x += random(-1, 1);
    this.y -= this.speedY;

    if (this.isOffScreen()) {
      this.x = random(width);
      this.y = 0;
      this.r = random(MIN_SIZE, MAX_SIZE);
    }
  }

  show() {
    stroke(255, 255, 255);
    ellipse(this.x, this.y, this.r * 2);
    fill(255)    
  drawingContext.shadowBlur = 20;
  drawingContext.shadowColor = color(255, 255, 255);
  }

  isOffScreen() {
    return this.y > 480;
  }
}
  </script>
```
【激選】 生産性爆上がり 超おすすめ拡張機能 10選


#  はじめに
作業の効率を爆上げする拡張機能についてです！

ある長期インターンで、新人に教えたら感動してもらうことが多く、もっと多くの人にこの感動を届けるべきだと思い執筆いたしました。

どれも無料でQOLを爆上げしてくれるものなので、良さそうと思ったものは是非取り入れてみてください！

## 1. AdBlock
こちらの拡張機能を使えば、ブラウザ上に出てくるすべての広告をブロックしてくれます。
YouTubeの広告もブロックしてくれるため、これ一つでYouTubeプレミアム同然です！ 

https://chrome.google.com/webstore/detail/adblock-%E2%80%94-best-ad-blocker/gighmmpiobklfepjocnamgkkbiglidom

## 2. AutoPagerize
GoogleChromeの2ページ目へいくためのリンクや次へのリンク押していませんか？
こちらの拡張機能を使えば、リンクを押すことなく自動で次のページを表示してくれます！
騙されたと思って入れてみてください！地味に便利です！(笑)

https://chrome.google.com/webstore/detail/autopagerize/igiofjhpmpihnifddepnpngfjhkfenbp?hl=ja


## 3. Acid Tabs
作業をしていたらタブがぐちゃぐちゃになってしまうことありませんか？
こちらの拡張機能を使うと、指定したサイトをグループに自動でまとめてくれます！
これを入れてから作業の効率が見違えるほど変わります！まだの人は直ちに入れましょう(笑)

https://chrome.google.com/webstore/detail/acid-tabs/hgceopemmcmigbmhphbcgkeffommpjfc


## 4. OneTab
こちらもタブ関連の拡張機能です！
コンテンツ制作など、タブを行き来せずに、もっと自由度高く、タブをまとめたいと思ったことはありませんか？
こちらの拡張機能では、複数の異なるURLを一つにまとめ、数多くのタブを整理することが可能です！
また、メモリ使用量を95%減少してくれます。

https://chrome.google.com/webstore/detail/onetab/chphlpgkkbolifaimnlloiipkdnihall?hl=ja


## 5. Black Menu for Google™
サクッとGoogleアプリを使いたい時ってありませんか？
その時に便利なのがこちらの拡張機能です！
僕は、サクッと翻訳したり、マップを見たい時に使っています！

https://chrome.google.com/webstore/detail/black-menu-for-google/eignhdfgaldabilaaegmdfbajngjmoke?hl=ja


## 6. Picture-in-Picture Extension
「動画を見ながら作業したい！」って時あったりしませんか？
こちらの拡張機能では、動画だけの画面を最前面に持ってくることができます！
単純作業の時などはぜひ！

https://chrome.google.com/webstore/detail/picture-in-picture-extens/hkgfoiooedgoejojocmhlaklaeopbecg


## 7. Video Speed Controller
ほぼすべての動画の速さを自由自在に操ることができます！

https://chrome.google.com/webstore/detail/video-speed-controller/nffaoalbilbmmfgbnbgppjihopabppdk


## 8. Save to Notion
Notionにあとで読みたい記事などをまとめている人には必見の拡張機能です！
ボタンを押すだけで読みたい記事を保存したい先に保存できます！

https://chrome.google.com/webstore/detail/save-to-notion/ldmmifpegigmeammaeckplhnjbbpccmm

## 9. Zoom Scheduler
会議などでzoomを開き、リンクをコピーしペーストし、、という操作毎回めんどうではないですか？
こちらの拡張機能を使えば、ボタン一つでGoogleカレンダー上にzoomの準備をすることができます！

https://chrome.google.com/webstore/detail/zoom-scheduler/kgjfgplpablkjnlkjmjdecgdpfankdle


## 10. G-calize
こちらは、Googleカレンダーを使っている人には是非使ってみてほしい拡張機能です！
デフォルトのGoogleカレンダーの背景色を変えたり、文字色を変えたりカスタマイズできます！

https://chrome.google.com/webstore/detail/g-calize/piiljfhidimfponnkjlkecnpjhdijfde

## 番外編
こちらは拡張機能ではないですが、とっても便利なので紹介します！
その名もSideKickです！

基本的な設計はGoogleChromeと全く同じ、Chromeの拡張機能も使えます！


#### Sidekickでできること
https://join.meetsidekick.com/niwio

1. よく使うアプリケーションをサイドバーに設置できる
2. またアカウントごとにアプリケーションを登録できる(下の画像のG-mailなどを見てください)
3. しかもこれ使っていないタブをAIが自動で認識してくれるためメモリの消費を抑えることができます！

![スクリーンショット 2022-12-03 19.05.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1081227/b2892db8-1947-2b2f-f9a0-e72316631f59.png)

こちらの記事でも紹介しているので、もしよろしければ

https://qiita.com/kubochiro/items/9d8474bc0f3c642b3ec2


## 最後に
いかがでしたでしょうか？
何か不明点や編集点などありましたらご連絡ください。
【Flutter】GetX超簡略紹介

# GetXとは
Flutterで使えるめっちゃ便利な拡張機能。
Flutterの拡張機能でおなじみのpub.devのこのページから導入可能です。

https://pub.dev/packages/get/install

# GetXの三大機能

GetXには、おもにこの3つの大きな機能があります。

■State Management(状態管理)・・・変数やリストの書き込み、保存、読み込みが簡単に出来る。
■Route Management(ルート管理)・・・アプリでの画面遷移が簡単に出来る。
■Dependency Management(依存管理)・・・Classの継承などが簡単に出来る。

それぞれざっくりと特徴を見ていきましょう！

# State Management(状態管理)

## 宣言、初期化

GetXなし
```
var name = "Ayutaya";
```
GetXあり
```
var name = "Ayutaya".obs;
```

## 表示

GetXなし
```
Text("$(name)")
```
GetXあり
```
obx(() => Text("${controller.name}"));
```
※controllerについては[Dependency Management(依存管理)](#dependency-management依存管理)参照

## 代入
GetXなし
```
name="Ayutaya2";
```
GetXあり
```
controller.name="Ayutaya2".obs;
```
※controllerについては[Dependency Management(依存管理)](#dependency-management依存管理)参照

# Route Management(ルート管理)

GetXなし
```
Navigator.of(context).pushNamed("/subpage");
```
GetXあり
```
Get.toNamed('/home');
```

# Dependency Management(依存管理)

GetXなし

Stateful Widgetを使って、その親Classを作って、さらに継承させて…

GetXあり　(次の1行をGetXを使いたいclassの最初に書くだけ)
```
final controller = Get.put(CounterController());
```

# GetXのメリット

一見、GetXの機能を使った方がコードが長くなっている部分もありますが、Stateful Widgetを使用せずに状態管理が出来るのはすごいメリットです！！
状態管理と画面表示を完全に別のClassとして用意できるので複数画面をまたぐような状態管理もたやすく出来てしまいます。


# 参考文献

公式サイトは英語ですが、ほぼすべての情報が分かりやすく網羅されているので必見です！！

https://pub.dev/packages/get
GPT3で画像生成してみた。

# 初めに
前回に引き続き、openAIのGPT3を用いて画像生成を行いました。
https://qiita.com/Yu_unI1/items/112deff0583884cd2d85

# 実装
```python:image.py
import os
import openai

import configparser

config_ini = configparser.ConfigParser()
config_ini.read('config.ini', encoding='utf-8')

openai.api_key = config_ini['GPT']['API_KEY']

response = openai.Image.create(
    prompt="A girl using laptop",
    n=1,
    size="1024x1024"
)

print(response)
```


promptに入れたキーワードから画像を生成してくれるようです。詳しいアルゴリズムはこちらの記事に綺麗にまとまっています！
https://gigazine.net/news/20200729-how-gpt-3-work/
TypeScript環境構築

# Node.jsを入れる

公式サイト(https://nodejs.org) で推奨版を
ダウンロードするやり方もあるが、
node.jsはバージョンを切り替えることが割とあるので、
最初からバージョンマネージャーを入れてしまったほうが早い。

Node.jsバージョンマネージャーは色々あるが、
ここでは、nvmを使う。


公式サイト(https://github.com/nvm-sh/nvm) を見ると、
下記のコマンドでインストールできる模様。

```:terminal
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.2/install.sh | bash
```

インストールしただけだとPATHが通っていないので、
PATHも公式に従って通してみる

```:terminal
export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
```

ちゃんとインストールされたか確認

```:terminal
nvm -v
```

インストールされたversionが返ってくれば問題なし。

早速、nvm経由でnode.jsをインストールしたいので、
まずはインストール可能なversionの一覧を見てみたい。

```:terminal
nvm ls-remote
```

![Screenshot 2022-12-03 at 18.19.37.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1290117/2dfce4d5-9c65-c936-7d86-ec428d990820.png)


たくさん出てくる。
LTSと横に書いているやつは、
Long Term Supportの略なので、
メンテンスがしっかりしている。

なので、基本的にはこのLTS系を
インストールすることが望ましい。
(あえて不安定なversionでバグを見つけたりしたい人を除く)


とりあえず、LTSで一番最新の
v18.12.1をインストールしてみる。

```:terminal
nvm install v18.12.1
```

ちゃんとインストールできたか確認

```:terminal
nvm ls
```

![Screenshot 2022-12-03 at 18.24.27.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1290117/d360c2ed-7fbb-8f2c-8f6a-d5626d582329.png)
 
こんなふうに、
システムの上らへんに、
今インストールしたversionが出ていれば、
インストールされている。

ちなみに、->で指しているところが、
現在のNode.jsのversionになる。

```:terminal
node -v
```
を実行すると、同じversionになっているはずである。

使うversionを切り替えたいときは、
```:terminal
nvm use v18.12.1
nvm use system
```
のようにuseを使えばいい。


# TypeScript導入

まずは、pacage.jsonを作ってしまおう。

```:terminal
npm init –yes
```

早速、TypeScriptをインストールしてみる。

```:terminal
npm install --save-dev typescript @types/node
```
※なぜかはわからないが、コピペしたやつをそのまま実行しても上手く行かないときがあるので、
その際は、直打ちして試してほしい。


TypeScriptがインストールできたら、
コンパイラに関する設定ファイルである、
tsconfig.jsonを作成したい。

```:terminal
npx tsc –init
```

tsconfig.jsonの設定の詳細はさておき、
一旦これでもうTypeScriptを動かすことはできる。

適当なTypeScriptのファイルを作ってみる
```:index.ts
const hello: string = "Hello world"
console.log(hello)
```

このファイルをコンパイルする
```:terminal
npx tsc
```

index.jsというファイルがあれば、
それがコンパイルされたファイルになるので、

```:terminal
node index.js
```
とすれば、Hello Worldと表示されるはず。

ちなみに、いきなりtsファイルを実行するには、
ts-nodeを使う。

```:terminal
npm install --save ts-node
```

インストールできたら、
```:terminal
 ./node_modules/.bin/ts-node index.ts
```
でHello Worldと表示される。
Pluto で作ったノートブックをGist に公開後完成品を見てもらう．

# 本日は

アドベントカレンダー5日目です．

https://qiita.com/advent-calendar/2022/julia

4 日目には Pluto.jl が提供する Julia のためのノートブックを使ったノートによって Julia のコードの使い方の解説が書いてあります．

ノートの作成にはいくつか手動のステップがあります．

まずはいつも通り Pluto Notebook の環境を立ち上げます．


```julia
julia> using Pluto; Pluto.run()
```

シェアしたいノートブックを開き下記のようなマークを押します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/01615076-af1c-d093-e140-b25b25fa2b36.png)

そうすると次のようが画面に移動しさまざまなフォーマットで保存することができます．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/863faf3c-bec1-210b-818a-c43fed88f7dd.png)


ここでは StaticHTML にて保存しておきます. `filename.jl.html` という形式の名前で保存されます．

あとは [gist](https://gist.github.com/) にアップロードします.

例えば4日目のアドベントカレンダーに使ったノートブックです．

https://gist.github.com/terasakisatoshi/d7609ea81591fcf4b8eb566ac84beac4

リンク先の画像は下記のような見た目を得ます．HTML がレンダリングされず生のHTMLが見えています．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/657291f6-7d00-98c0-c62d-275845b60987.png)

そこで gist のリンクをコピーして [GitHub HTML viewer](https://htmlview.glitch.me/)　に移動します．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/135978/6bd3a1b5-2c90-0532-04b6-2429b123a00a.png)

入力枠に gist のリンクを貼るとリッチな出力で表示されます．

https://htmlview.glitch.me/?https://gist.githubusercontent.com/terasakisatoshi/01caba955f13e78ea00ce7b0a06cbfdc/raw/8017f6ec8a185cfb89aa287cdce46ba3a189d37f/gs.jl.html

リンク先に Gray-Scott の拡散モデルのノートブックが見られればOKです．
Excelと表計算の年表

Excelと表計算の歴史を少し調べたので年表を作りました。

近年では
Excel2007の~~OpenDocument対応~~ OfficeOpenXML対応(.xlsx対応)、マルチスレッド対応
Excel2016のJavascriptAPI対応、新関数追加(IFS,SWITCHなど)
Excel2021のスピル機能や新関数追加(XLOOKUP,LETなど)
が結構大きな変更ですかね。。

![ExcelHistory.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3010991/ccfea00a-2700-2d14-a7c4-95abdb222df3.png)
Amazon ECS FargateをSysdigサーバーレスエージェントでモニタリングするためのTips

コンテナセキュリティに強いSysdigをAWS Fargateで検証した際に、少しハマったので、同じ轍を踏む方が出ないように共有。

手順はSysdig Japanさんにて公開いただいている翻訳版が丁寧でわかりやすいです！
https://sysdig.jp/blog/aws-fargate-serverless-agents/

公式のnginxイメージを使ったDockerイメージを元にFargate起動した場合、とくにエントリポイントなくnginxプロセスが起動して、Webサーバーとして機能します。
Dockerファイルはこんな感じ。
```
From nginx:latest

COPY ./default.conf /etc/nginx/conf.d
COPY ./src/index.html /usr/share/nginx/html/index.html
```

この環境にSysdigサーバーレスエージェントをインストールした際に、どうもエージェントが機能していないような。。。
以下のように明示的にEntryPointを追加することで対応できました。
```
      ContainerDefinitions:
        - Name: !Ref ServiceName
          Image: "123456789123.dkr.ecr.us-east-1.amazonaws.com/test-nginx:latest"
           # ここを追加
          EntryPoint:
            - "nginx"
            - "-g"
            - "daemon off;"
```

無事、モニタリングしてくれている模様 :)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/51320/55a440ff-6636-1c47-0e1b-54a76258a662.png)
tweepyを使って特定のワードの入ったツイートを取得する

おはこんばんちわ。

## 大まかな流れと準備
###### 最終目標
「特定のワードを指定したツイートを取得して、csv形式で保存する。」

裏テーマ「金曜ロードショー放送中のみんなのリアクションが見たい。」


###### 方法

1.Pythonでtweepyを利用し、ツイートデータを取得。
2.欲しいデータのみ抽出。
→今回はツイート本文とツイート時間を取得。
3.データの加工、整理。
4.結果をcsv形式で出力。

###### 準備

・TwitterAPI(v2)のデベロッパーアカウントを取得する。
・Pythonを実行できる環境を用意する。

###### 今回のコードの注意点
・時間指定
→元々のタイムゾーンがutcなので日本時間から-9時間しなければならない。
→TwitterAPIの機能で一週間前までしか遡ることができない。
・検索ワードのAND,ORなど
→できると思いますが、今回は割愛します。

## コード
```php
import tweepy
import pandas as pd
import datetime as dt
import time
from datetime import timedelta

# 認証　
api_key = '自分のtwitterAPIのコード'
api_key_secret = '自分のtwitterAPIのコード'
access_token = '自分のtwitterAPIのコード'
access_token_secret = '自分のtwitterAPIのコード'
bearer_token = '自分のtwitterAPIのコード'

# 接続
client = tweepy.Client(
    consumer_key=api_key,
    consumer_secret=api_key_secret,
    access_token=access_token,
    access_token_secret=access_token_secret,
    bearer_token=bearer_token)
```
```php
# 関数化を行った
#　変数には検索ワード、保存するcsvの名前,時間を入力する。
def comment_log(tag,name,year=2022,month=11,day=26,hour_s=12,hour_e=15,minute=00,second=00):
    movie_text =[]
    movie_time =[]
    dt_s = dt.datetime(year,month,day,hour_s,minute,second)
    dt_e = dt.datetime(year,month,day,hour_e,minute,second)
    dt_s_str = dt.datetime.strftime(dt_s,"%Y-%m-%dT%H:%M:%SZ")
    dt_e_str = dt.datetime.strftime(dt_e,"%Y-%m-%dT%H:%M:%SZ")
    first_flg = True
    while True:
        #このお休みが大事
        time.sleep(1)
        #1周目
        if first_flg == True:
            tweets = client.search_recent_tweets(query=tag + ' - 視聴認定バッジ',
                                        max_results=100,
                                        tweet_fields=["created_at"],
                                        start_time = dt_s_str,
                                        end_time = dt_e_str)
            first_flg = False
        # 2周目以降
        else:
            tweets = client.search_recent_tweets(query=tag + ' - 視聴認定バッジ',
                                        max_results=100,
                                        tweet_fields=["created_at"],
                                        pagination_token=next_token,
                                        start_time = dt_s_str,
                                        end_time = dt_e_str)

        # 本文と時間のリストにそれぞれ追加していく
        if tweets is not None:
            for tweet in tweets[0]:
                movie_text.append(tweet.text)
                movie_time.append(tweet.created_at)

        # ここで次の100件を取得するためのトークンを取得
        try:
            next_token = tweets.meta['next_token']
        except KeyError:
            break

    # DataFrameを作成しつつ、タイムゾーンを日本に変更
    df = pd.DataFrame(data={'時間':movie_time})
    df['時間'] = df['時間'].dt.tz_convert('Asia/Tokyo')
    df['本文'] = movie_text
    # csv形式で保存
    df.to_csv(name+'.csv')
```
# 参考
https://zero-cheese.com/8436/

***
自分で試行錯誤してコードを完成させること自体はじめてに近い経験だったので、
承認欲求のようなものが生まれて今回この話題で書かせてもらいました。
自分の中に落とし込むことも難しかったのに、見えない人に対して文字で説明することは考えていたよりも不自由で困難でしたが、良い経験になったと思います。
この投稿の内容自体やコードの内容にも色々と不備あると思いますが、
どうか生暖かい目で見てやってください。
あざした。
GitHub Codepaces

#### GitHub Codespacesとは

* [Remote Development](https://code.visualstudio.com/docs/remote/remote-overview)用のVMをクラウドに立てて、ローカルのブラウザもしくはVisual Studio Codeから接続して利用できる。
* 2 core x 60時間 (4 core x 30時間) + ストレージ 15GB まで無料で利用できる。

#### 簡単な使い方

* Codepacesを管理 (新規作成、起動・停止、削除) する。
  * GitHub Codepacesの[開発者コンソール](https://github.com/codespaces)から行える。

* 現在の使用量を確認する。
  * [Billing and plans](https://github.com/settings/billing)のUsage this month / Codespacesを参照する。
  * 参考：[Viewing your GitHub Codespaces usage](https://docs.github.com/en/enterprise-cloud@latest/billing/managing-billing-for-github-codespaces/viewing-your-github-codespaces-usage)
* Visual Studio Codeから接続する。
  * [GitHub Codespacesプラグイン](https://marketplace.visualstudio.com/items?itemName=GitHub.codespaces)をインストールする。
  * `Ctrl + Shift + P` → `Codespaces: Sign In` → ブラウザでログイン (OAuth2連携) → `Ctrl + Shift + P` → `Codespaces: Connect to Codespace`
* 起動したアプリにアクセスする。(Webアプリの場合)
  * VM上で起動したアプリに接続するにはPort Forwardingが必要となる。(参考：[Forwarding ports in your codespace](https://docs.github.com/en/codespaces/developing-in-codespaces/forwarding-ports-in-your-codespace))
    * アプリ起動時にOutputに`http://localhost:3000`のようなURLが出力されると自動でポート転送が設定される他、PORTSパネルから手動で設定することもできる。
    * Visual Studio Codeで接続している場合は端末のポート転送も自動で設定されるため `localhost` でアクセスができる。
    * ブラウザで接続している場合は、VisibilityがPrivateのポート転送ではGitHubの認証が必要なので、同じブラウザでアクセスするか、ブラウザが使うCookieをコピー(する必要がある。(参考：[Security in GitHub Codespaces](https://docs.github.com/ja/codespaces/codespaces-reference/security-in-github-codespaces#port-forwarding))


#### トラブルシューティング

* ブラウザで接続したときに以下のService Workerのエラーが表示される。

  ```
  Error loading webview: Error: Could not register service workers: NotSupportedError: Failed to register a ServiceWorker for scope
  ```

  * 3rd Party Cookieを無効化していると、このエラーが発生する。クロスサイトでロードしたスクリプトでServce Workerを登録しているようで、ブラウザで利用するときには3rd Party Cookieを許可する必要がある。

#### 参考記事

- [GitHub Codespaces が GA しました（概要、課金など色々まとめ）](https://qiita.com/uikou/items/1feb83865f9d638807ad)
- [GitHub Codespaces で開発する](https://docs.wantedly.dev/fields/dev-tools/codespaces)
- [GitHub Codespaces を使いはじめる | 豆蔵デベロッパーサイト](https://developer.mamezou-tech.com/blogs/2022/05/18/start-using-codespaces/)