OmniAICreator/Qiita-1.07M huggingface dataset:
AttentionとKernel Smoothingの対応関係についてのメモ

Attentionを勉強する過程でKernel smoothingと等価なことをやっているのでは？！と思い，調べてみたら英語の文献[^1]は出てきたのですが日本語で言及されているものを見たことなかったので，雑メモですが投稿します．
[^1]: AttentionとKernel smoothingの等価性に言及している文献をいくつか挙げておきます．[Transformer Dissection: A Unified Understanding of Transformer's Attention via the Lens of Kernel](https://arxiv.org/abs/1908.11775)はAttentionをKernel Smoothingの観点から再解釈した上で新しいAttentionのバリエーションを提案しています．[An Attentive Survey of Attention Models](https://arxiv.org/abs/1904.02874)はAttentionを利用したモデルのサーベイ論文です．[DIVE INTO DEEP LEARNING 10.2. Attention Pooling: Nadaraya-Watson Kernel Regression](https://d2l.ai/chapter_attention-mechanisms/nadaraya-watson.html)はAttentionを実装するチュートリアルで，Kernel smoothingと絡めて説明されています．

# 結論
BERTやTransformerで利用されるAttention（注意機構）ですが，もっとも素朴なAttentionはKernel Smoothing（Nadaraya-Watson kernel estimatorとも呼ばれる．日本語だとカーネル平滑化．）という回帰の古典的な手法と等価な処理をしていると言えます．以降はそれを示すために，2つがどう対応しているの，またどんな処理をしているのか見ていきます．

# AttentionとKernel smoothingの対応
AttentionはNeural Networkで用いられるアーキテクチャです．ベクトルの系列[^2]$\\{q_1,\dots,q_J\\}, q_j\in\mathbb{R}^M$が与えられたときに，対応する出力$\\{f_1,\dots,f_J\\}\in\mathbb{R}^{J\times D}$を返す仕組みです．この入力はQueryと呼ばれます．この出力を計算するのに用いるのがKeyとValueのペアの集合$\left\\{(k_i, v_i)\right\\}_{i=1}^I, k_i\in\mathbb{R}^M, v_i\in\mathbb{R}^D$です．
[^2]: 厳密には順序関係は考慮されないので集合と見た方が良さそうです．参考：[Attention might be something you need](https://docs.google.com/document/d/1e0vscvd-mtpwHWJdhMMEUs-193hQ_LnKpssDkU8NaW0/mobilebasic#)

一方で，Kernel smoothingの目的は回帰問題を解くことです．すなわち，教師データとして入力と出力のペアが複数与えられたときに，その関係をうまく表現する関数を推定し，未知の入力集合に対しての出力を予測するわけです．ここで登場する変数をAttentionに合わせる形で定義したのが以下の表です．

| 変数               | Attentionにおける呼び方 | Kernel Smoothingにおける呼び方 | 
| ------------------ | ----------------------- | ------------------------------ | 
| $k_i, v_i$         | KeyとValueのペア        | 観測された入力と出力のペア     | 
| $q_j$              | Query                   | 入力を予測したい未知の入力     | 
| $f_j$              | Queryに対応する出力     | 予測値                         | 
| $\alpha(k_i, q_j)$ | 関連度，類似度          | カーネル                       | 

この変数を用いて両者の目的を一般化するならば，与えられている$\\{(k_i, v_i)\\}$を利用することで$\\{q_j\\}$に対応する出力$\\{f_j\\}$を得ようということです．それをAttentionとKernel Smoothingでは，以下のように実現します．ここからはAttentionもしくはKernel Smoothingをご存じの方は「そうですね」と思いながら読んでいただければと思います．

まず，$k_i$と$q_j$の類似度を$\alpha(k_i,q_j)$としておきます．この類似度を求めるのには標準内積などがよく用いられます．Attentionにおいてはこれを関連度（のようなもの）と呼ぶこともあるようですし，Kernel smoothingにおいてはこれをカーネルと呼びます．
この時$q_j$に対応する出力$f_j$は次のように求められます．
$$f_j=\sum_i \tilde{\alpha}(q_j,k_i)v_i$$
ここで$\tilde{\alpha}$は$$\tilde{\alpha}(q, k_i)=\frac{\alpha(q, k_i)}{\sum_l\alpha(q,k_l)}$$
と$\sum_i\tilde{\alpha}(q,k_i)=1$となるように正規化された類似度です．つまり，AttentionとKernel smoothingでやっていることは$\\{q_j\\}$と$\\{k_i\\}$の全ての組み合わせの類似度を利用して$\\{v_i\\}$の重み付き平均を出力としましょうということです．


# 最後に
私はAttentionに元々明るくなかったので，このように回帰手法と関連づけられると処理をスッキリ理解することができました．Kernel Smoothingは1964年に発表されているので[^3]，Attentionというのは意外と古典的な仕組みなんだなーということがここからわかります．逆にKernel smoothingを利用する際には，Attentionを高速化するアプローチ[^4]が使えるかもしれません．
[^3]: [On Estimation Regression](https://epubs.siam.org/doi/10.1137/1109020)
[^4]: [Efficient Transformers: A Survey](https://arxiv.org/abs/2009.06732)
.bash_profileと.bashrcを理解してる人は見ないでください。

# はじめに
環境構築の際に、見たことはあるけどイマイチ理解していないランキングに必ず上位に入るであろう`.bash_profile`や`.bashrc`たち。。
自分も理解していないことが原因で苦労したので、それを機に学習してみましたので、備忘録として残しておくと共に、自分と同じ人たちを救う記事になればと思います！

# .bash_profileとは？.bashrcとは？
bashを使う際の設定を記載するファイルです。似たものではありますが、具体的には以下のような違いがあります。

| ファイル | 実行タイミング | 注意点 | 設定内容 |
|:-:|:-:|:-:|:-:|
| ~/.bash_profile  | ログイン時  | ここでは何も出力しない  | 環境変数（exportで宣言する変数）  |
| ~/.bashrc  | シェル起動時  | 右から順に読込  | エイリアス、シェル関数、コマンドラインの補完  |

## PATHを通すとは？
PATHとは環境変数のひとつで、`コマンド(cdなどの実行ファイル)入力時にシェル(bashやzsh等)が実際に実行ファイルを探しに行く際に参照する`ものです。
PATHを通しておけば以下のコマンドは同様の意味になります。

```bash
# cdコマンドは/binディレクトリに格納されている
/bin/cd

# PATHを通しているため/bin/cdと同じ効果
cd
```

### PATHの通し方
PATHを通したい時は、`~/.bash_profile`に通したいPATHを記入する。

```bash
# echo 'export PATH=/通したいパス:$PATH' >> .bash_profile

$ echo 'export PATH=/usr/sample:$PATH' >> .bash_profile
```

設定後は、以下のコマンドで環境変数を有効にします。

```bash
$ source ~/.bash_profile
```


### PATHの確認方法
PATHは、環境変数の`$PATH`に設定されていますので、`echo $PATH`とすることで確認出来ます。

```bash
$ echo $PATH
#=> /usr/local/bin:/usr/bin:/bin:/usr/sbin:...
```

### 実行ファイル格納場所の確認方法
`which コマンド`とすることで、指定したコマンドの実行ファイルがどこに格納されているのか確認出来ます。
※実行ファイルが複数ある場合は、`左から優先されて実行される`ので注意が必要です。

```bash
$ which mysql
#=> /usr/local/opt/mysql@5.6/bin/mysql
```

# 終わりに
何も分からなかった時と比べるとかなり理解度が高まった。基本的な事かもしれないけど、理解しておくだけでも細かいエラーに対応できる気がするので有意義な情報でした。。

# 参考
[.bash_profileと.bashrcのまとめ]
(https://qiita.com/takutoki/items/021b804b9957fe65e093)

[PATHを通すの意味と通し方　.bash_profile]
(https://qiita.com/ozipi/items/29d7ae0b21e476dd7b8e)

[Bash: .bashrcと.bash_profileの違いを今度こそ理解する]
(https://techracho.bpsinc.jp/hachi8833/2021_07_08/66396)
[Flutter] ios 色々エラーが出て困った時


<h3>掃除してみる</h3>

`$ flutter clean && \
  rm -Rf build && \
  rm -Rf ios/Flutter/Flutter.framework && \
  rm -Rf ios/Flutter/Flutter.podspec && \
  rm -Rf ios/Flutter/App.framework && \
  rm -Rf ios/Pods && \
  rm -Rf ios/.symlinks && \
  rm -Rf ios/build && \
  rm -Rf ios/Runner.xcworkspace && \
  rm -f ios/Podfile && \
  rm -f ios/Podfile.lock && \
  rm -f pubspec.lock && \
  flutter build ios && \
  flutter run`
ExcelVbaからOutlookのメール作成、RTF（リッチテキストフォーマット）で文中に添付ファイルを貼る


ExcelVbaからOutlookのメール作成、
RTF（リッチテキストフォーマット）で文中に添付ファイルを貼る

##解説

:::note info
通常、HTML形式で作成するが、RTFであれば、文中に添付ファイルを位置を決めて埋め込むことができる。
たとえば、表組み（テーブル）に、添付ファイルごとに解説・説明付きで、表現することができる。
この、RTFで添付ファイルを埋め込む形式での、Outlookメールを、ExcelVBAで作成する場合の例が以下。
:::

:::note info
メール文書内の、文書成型は、ワードのオブジェクトとして実施するのがミソ（WordEditorで、docを得ている箇所）
:::

:::note info
vbaでのword操作は、「Range」を使いこなすのが大事。doc内を、Paragraphsや、Sentencesを、for文で順にみていくことが可能。この時、Paragraphsの要素は、Paragraphだが、Sentencesの要素はSentenceではなく、Range。
:::


##ソース

```vb:Excel2Outlook_SendMail_RTF

'要、参照設定　：　Microsoft Word 16.0 Object Library

Option Explicit

Public Sub Excel2Outlook_SendMail_RTF()

Dim wb As Workbook
Set wb = ActiveWorkbook

' エクセルの表組みをコピー
' 領域は適宜
'/---------------
wb.Sheets("Sheet1").Range("A1:C3").Copy
'/---------------
Dim myol, mymail, ins, doc
Set myol = CreateObject("Outlook.Application")
Set mymail = myol.createItem(0)
mymail.Display

 mymail.bodyformat = 3 'olFormatRichText
'mymail.bodyformat = 2 'olFormatHTML

Set ins = mymail.GetInspector

'WordEditorで、本文編集する
Set doc = ins.WordEditor

Dim rng As Word.Range

'/// 3センテンス作成
doc.Range.InsertAfter " " & vbCrLf
doc.Range.InsertAfter "***" & vbCrLf
doc.Range.InsertAfter " " & vbCrLf

'/// 真ん中のセンテンスを選出
Set rng = doc.Sentences(2)

'貼り付け
'Const wdPasteHTML = 10
rng.PasteSpecial DataType:=10, Placement:=0

Dim marks(2) As String
marks(0) = "ε１ε"
marks(1) = "ε２ε"


Dim files(2) As String

files(0) = "C:\Users\user_name\Desktop\atc_test1.txt"
files(1) = "C:\Users\user_name\Desktop\atc_test2.txt"

Dim sntn As Word.Range
Dim p, mk
For Each p In doc.Paragraphs
    
    Set sntn = p.Range
    
    For mk = 0 To UBound(marks)
        sntn.Find.Execute FindText:=marks(mk)
        
        If sntn.Find.Found Then
            sntn.Text = ""
            If Trim(files(mk)) <> "" Then
                sntn.InsertFile Attachment:=True, Link:=False, Filename:=files(mk)
            End If
        End If
    Next

Next

doc.Range.Font.Name = "ＭＳ Ｐゴシック"
doc.Range.Font.Size = 10.5

'/---------------
mymail.To = "" 'wb.Sheets("_設定").Cells(1, 2).Value
mymail.cc = "" 'wb.Sheets("_設定").Cells(2, 2).Value
mymail.Subject = "" 'wb.Sheets("_設定").Cells(3, 2).Value
'mymail.body = ""
'/---------------

mymail.Recipients.ResolveAll

'/---------------
'''' mymail.send
'/---------------

Set mymail = Nothing
Set myol = Nothing
Set wb = Nothing

End Sub


```

##エクセル側準備

表組みを、以下のように準備して、
ε１ε、ε２εの位置に、添付ファイルを埋め込んでいる
（シート名は「Sheet1」）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/107418/f22fbc10-d32a-5708-19ff-9cc8a8206bf6.png)




##参考ページ

https://qiita.com/santarou6/items/0a316f6a48451edcbb31
【Inkscape】インストールしたフォントが表示されないときの対処法

## 環境
+ Microsoft Windows 10.0.19042.1165
+ Inkscape 0.92.4

## 対処法
フォントファイルを右クリックして「すべてのユーザーに対してインストール」を選択
![スクリーンショット (154).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/45c7f398-5b3b-e503-5633-28a0f8bec0e5.png)

これでInkscapeで使えるようになる。
![スクリーンショット (155).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1946472/7144cd39-9d25-5551-3284-05bef3f2ed80.png)

ちなみに、このフォントはオザワタクヤさんのフリーフォント「ROLAchan」

https://ozawa.design/store/rolachan/

## 参考

https://blog.ver001.com/windows-font-install/
[01] VirtualBox 5.2 系のインストール手順

|本シリーズのトップページ|
|:--|
|[[シリーズ] VirtualBox のインストールについて](https://qiita.com/robozushi10/items/edea49b473219d22816b)|

# 概要

Ubuntu 18.04 に VirtualBox 5.2 系をインストールする手順である.
また、2021/05 時点で Vagrant 2.2.14 が使用可能なことも確認している.

**2021/05 時点では VirtualBox 6.1.X 系を使うと Vagrant が使えなかった**ので、
VirtualBox 5.2 系をインストールした.


# 物理ホスト環境

```
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=18.04
DISTRIB_CODENAME=bionic
DISTRIB_DESCRIPTION="Ubuntu 18.04.4 LTS"
```

# 手順

## 1. インストール候補の VirtualBox のバージョンを確認する

```bash
$ sudo apt list virtualbox -a
一覧表示... 完了
virtualbox/bionic-updates 5.2.42-dfsg-0~ubuntu1.18.04.1 amd64
virtualbox/bionic-security 5.2.18-dfsg-2~ubuntu18.04.5 amd64
virtualbox/bionic 5.2.10-dfsg-6 amd64
```

## 2. VirtualBox をインストールする

当方の場合は、約 5分ほど要した.

```bash
$ sudo apt install -y virtualbox
```

もしもセキュアブート用のキーが指定されれば適当に決めておくこと.
ここでは「abc123」としておく.

PC を再起動させると(下図のような)青画面になるので、
「Enroll key」から `abc123` と入力すれば良い.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1246056/bb18bbf6-b83a-1da8-18d1-c1b6ad26ca22.png)

## 3. インストールされたことを確認する

```bash
$ virtualbox --help
Oracle VM VirtualBox Manager 5.2.42_Ubuntu
(C) 2005-2020 Oracle Corporation
All rights reserved.
```


以上.

このあと、VirtualBox の操作性を上げるために Vagrant を導入する.
sshログイン自動化（コマンド対話例含む）

# sshログイン自動化方法

自身のホスト環境とビルド環境、実行環境が違う場合が、
実務の開発時にはあると思います。そんな時のログイン自動化メモです。

## 前提環境

- Windows10 (WSL2)
- 普通のLinuxでもたぶん大丈夫なはず。

## コマンド対話が不要な場合

sshpassを使います。まずは以下でインストールします。

```sh
$ sudo apt install sshpass
```

ログイン＋ログイン先での処理は以下のように実施します。

```sh
USERNAME="AAAAAA"
PASSWORD="XXXXXX"
SERVER_URL="192.168.1.10"
WORK_DIR="~"

sshpass -p ${PASSWORD} ssh ${USERNAME}@${SERVER_URL} \
      "\
       cd ${WORK_DIR};\
       ls\
      "
```

上記のように、sshpass+sshの後にエスケープを使って複数行記述すれば、
任意のコマンドをサーバー上で実行させられます。

## コマンド対話が必要な場合

例えば、初回sshログイン時は、コマンド対話が必要であるため、完全に自動化できません。
そこで、expectを使えば初回ログインなどのコマンド対話も自動化となります。

まずは、expectをインストールします。

```sh
$ sudo apt install expect
```

以下を任意の.expファイルとして保存し(例: `test.exp`)、
`expect test.exp {サーバーURL} {パスワード} {ワークフォルダ}`で実行します。

```exp
log_file /var/log/expect.log

set ServerUrl [lindex $argv 0]
set Password [lindex $argv 1]
set WorkDir [lindex $argv 2]
set Prompt "\[#$%>\]"

set timeout 5

spawn env LANG=C /usr/bin/ssh ${ServerUrl}

expect {
    -glob "(yes/no)?" {
        send "yes\n"
        exp_continue
    }
    -glob "password:" {
        send -- "${Password}\n"
    }
}

expect {
    -glob "${Prompt}" {
        send "cd ${WorkDir}\n"
        send "ls\n"
        interact
        exit 0
    }
}
```

`-glob "hogehoge"` の部分で、コンソール上の文字列を取得したときの条件文を記述し、
条件に合致したときは、その`{}`内の処理を実行します。
[AWS] CloudFront とリージョン間のネットワークのパフォーマンスが上がってた

小ネタです。

# AWS CloudFront とリージョン間のネットワークのパフォーマンスが上がってた

## CloudFront とリージョン間のネットワークとは

私が所属している会社ではサービスを CloudFront 経由で提供しています。
今回のネットワークの部分は以下の図で言うと赤い矢印の部分です。

![概要図.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86389/aa7af571-33ba-2ca7-47d8-b39c5b0a47de.png "概要図")

## パフォーマンスが上がっていた

現在提供しているサービスは世界各地で利用されているため、可能な限りのリージョンエンドポイントから死活監視を実施しています。その際にレスポンスタイムがわかるのですが、何もしていないのにそのレスポンスタイムが全体的に速くなっていました。以下は Datadog の Synthetic Monitoring です。

![SyntheticMonitoring.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86389/222338c0-317b-0656-7901-a70bf827ef71.png "Datadog の Synthetic Monitoring")

地理的距離が遠いほどパフォーマンスが改善されています。サービスが実装されているアプリケーションではパフォーマンスに関してのリリースは最近されていないことと、監視エンドポイントとサービスが提供されているアプリケーションのリージョン間の距離が遠いほどパフォーマンス改善効果が見られることから、おそらく CloudFront とリージョン間の AWS ネットワークバックボーンの改善が行われたと予測できます。

## まとめ
何もしてないのにパフォーマンス改善されているのには驚きましたし流石だなと思いました。ちょうどグローバル環境のパフォーマンス改善を考えていたのでとても助かりました。今後も改善されていくことに期待したいです。

## 追記
残念ながら戻ってました。

![スクリーンショット 2021-08-31 16.23.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/86389/87666f1a-b573-8638-c4eb-8b8edab9ecf5.png)
react-pdfでFireabase Storageの画像を出力するためのcors設定手順

#背景

React+Goを使ってWebアプリケーション開発をしております。フォームの入力内容をもとに履歴書としてPDF出力する処理を実装することになり、Reactのライブラリ「React-pdf」を使用して実装することができました。ただ、Firebase Storage内の画像をなかなか出力することができず、格闘していたところ、原因はFirebaseへのアクセス権限設定（cors設定）であるとわかりました。

#この記事で解説する内容

- Firebase Storageのcors設定手順

#そもそもcorsって？
corsとはオリジン間リソース共有（Cross-Origin Resource Sharing）の略。追加のHTTPヘッダーを使用して、あるオリジン（＝データの送信元）で動作しているWebアプリケーションに、異なるオリジンのリソースへのアクセス権を与えるようブラウザに指示するための仕組み。

#文字列と罫線のPDF出力
文字列と罫線のPDF出力はこちらを参考に。
https://qiita.com/kashimuuuuu/items/0d249be6bcea834c473c

#Firebase Storageのcors設定手順

手順
①Google Cloud SDKをインストールする
②ローカルにcors.jsonを作成する
③cors.jsonをデプロイする

##①Google Cloud SDKをインストールする
以下を参考にGoogle Cloud SDKをインストールします。「CORS の構成」の「ここからインストール」というリンクをクリックする。
https://firebase.google.com/docs/storage/web/download-files?hl=ja#cors_configuration


##②ローカルにcors.jsonを作成する

``` json:cors.json
[
  {
    "origin": ["*"],
    "method": ["GET"],
    "maxAgeSeconds": 3600
  }
]
```

##③cors.jsonをデプロイする
ターミナルを起動し、cors.jsonが存在するディレクトリで以下コマンドを実行する。

”gs://xxxx.appspot.com”の部分はFirebase StorageのURLに書き換える。

```
gsutil cors set cors.json gs://xxxx.appspot.com 
```
（開発環境と本番環境ではgs:以下が異なる）

##デプロイされたファイルを確認
```
gsutil cors get gs://xxxx.appspot.com 
```
（開発環境と本番環境ではgs:以下が異なる）

#参考
- Firebase StorageにCORSの設定をする
https://qiita.com/niusounds/items/383a780d46ee8551e98c

- Cloud SDK
https://cloud.google.com/sdk/
59日後にITパスポートを受けるFラン私大文系既卒(31日目)

# CSR(Corporate Social Responsibility)
* CSRとは?
 * 企業の社会的責任
* CSRの関連用語
 * グリーンIT
 * ダイバーシティ
 * ソーシャルビジネス
 * SDGs

# ステークホルダ
* ステークホルダとは?
 * 企業と利害関係にある人

# HRM(Human Resource Management)
* HRMとは?
 * 人を経営資源の一つと考え、人的資源を効率的に活用すること

# HRテック
* HRテックとは?
 * HRMにIT技術を用いる方法

# 事業
* 事業とは?
 * 複数の業務のこと

# 業務
* 業務とは?
 * 手作業とシステムのこと

# システム
* システムとは?
 * ソフトウェアとハードウェアのこと
 
# 回帰分析
* 回帰分析とは?
 * 過去を分析して、過去を予測する手法

# 期待値
* 期待値とは？
 * 値と確率を掛け算し、その後全ての組み合わせを足し算して求める

# 売上
* 売上とは?
 * 商品やサービスで得たお金

# 費用
* 費用とは?
 * 固定費と変動費

# 固定費
* 固定費とは?
 * 人件費と家賃

# 変動費
* 変動費とは？
 * 材料費

# 資本金
* 資本金とは?
 * 株主が出したお金
 
# 損益計算書
* 損益計算書とは?
 * 会社の利益が書かれている
 * 会社がどのように稼いだかを明らかにする文書

# 売上総利益
* 売上総利益とは?
 * 売上 - 売上原価

# 営業利益
* 営業利益とは?
 * 売上総利益 - 販売費
 * 本業で稼いだお金

# 経常利益
* 経常利益とは?
 * 営業利益 - 営業外利益 - 営業外費用
 * 本業と副業を合わせた金額

# 当期純利益
* 当期純利益とは? 
 * 全ての利益から、全ての費用を引いた金額

# キャッシュフロー計算書
* キャッシュフロー計算書とは?
 * 会社に現金がどれほど残っているかが書いてある文書

# ROE(Return On Equity)
* ROEとは?
 * 株主から貰ったお金でどれだけ利益をあげたかを表す指標
 * 自己資本利益率
* 式

```math
REO = \frac{自己資本}{当期純利益}
```
【TypeScript入門】型エイリアスとは

#　型エイリアスで型定義を再利用しよう
##　型エイリアスとは
* typeを使って、型に名前をつけて宣言できる
* 同じ型を何度も定義する必要がない（再利用ができる）
* 型に名前をつけることで変数の役割を明確化

```typescript:/src/object/alias.ts
type Country = {
    capital: string
    language: string
    name: string
  }

  const japan: Country = {
    capital: 'Tokyo',
    language: 'Japanese',
    name: 'Japan',
  }
  console.log('sample 1:', japan)
//sample 1: {capital: "Tokyo", language: "Japanese", name: "Japan"}

  const america: Country = {
    capital: 'Washington, D.C.',
    language: 'English',
    name: 'United States of America',
  }
  console.log('sample 2:', america)
//sample 2: {capital: "Washington, D.C.", language: "English", name: "United States of America"}
```

# 合併型(union)と交差型(intersection)
* 合併型: 型Aか型Bどちらかの型をもつ
* 交差型: 型Aと型B両方の型を持つ
* 交差型は「AとBに共通する型」ではない

```typescript
 // 合併型(union)と交差型(intersection)
  type Knight = {
    hp: number
    sp: number
    weapon: string
    swordSkill: string
  }

  type Wizard = {
    hp: number
    mp: number
    weapon: string
    magicSkill: string
  }

  type Adventurer = Knight | Wizard // 合併型: KnightとWizardどちらかの型を持つ
  type Paladin = Knight & Wizard // 交差型: KnightとWizardが持つ型を全て持っている

  // Knightの型を持つadventurer2
  const adventurer1: Adventurer = {
    hp: 100,
    sp: 30,
    weapon: '木の剣',
    swordSkill: '三連斬り',
  }

  console.log('sample 3:', adventurer1)
//sample 3: {hp: 100, sp: 30, weapon: "木の剣", swordSkill: "三連斬り"}

  // Wizardの型を持つadventurer2
  const adventurer2: Adventurer = {
    hp: 100,
    mp: 30,
    weapon: '木の杖',
    magicSkill: 'ファイヤ',
//sp:30 エラーにならず、動いてしまう。
  }

  console.log('sample 4:', adventurer2)
//sample 4: {hp: 100, mp: 30, weapon: "木の杖", magicSkill: "ファイヤ"}

  // KnightとWizard両方の型を持つpaladin
  const paladin: Paladin = {
    hp: 300,//　１つでもプロパティが欠けるとエラーになる
    sp: 100,
    mp: 100,
    weapon: '銀の剣',
    swordSkill: '三連斬り',
    magicSkill: 'ファイヤボール',
  }

  console.log('sample 5:', paladin)
//sample 5: {hp: 300, sp: 100, mp: 100, weapon: "銀の剣", swordSkill: "三連斬り", …}

```
【Rails】超簡単！画像のPlaceholder設定方法

#爆速！！！画像投稿機能のプレースホルダー設定方法
rails でのwebアプリケーション開発で、画像投稿機能を実装した際に、画像がある場合とない場合の設定方法を今回は使えるととっても便利な「Helper」というものを使って実装していきます。

[Helperとは？という人はこちらを見てみてください](https://qiita.com/yukiyoshimura/items/f0763e187008aca46fb4)

###前提
テーブル作成→新規投稿機能が実装済み
また、画像投稿機能を実装済み(carrie waveを中の人は使用しています)
【今回の記事について】
テーブル名：posts
画像を保存するカラム名：image

##STEP1
まずは適当に画像を投稿していない場合に表示させたい画像をダウンロードし、
「app/assets/images」　の中に入れましょう。
＊この作業を忘れてエラーになることが多々見受けられるので要注意。

今回は画像名を「placeholder.png」として保存しています。
初心者などの方は、画像を左クリック→「Rename」→「placeholder.png」などと変更しましょう。

##STEP2

次にヘルパーを開いて記述していきます。
場所は「app/helpers」の中にあります。
今回は「posts_helper.rb」を編集していきます。
＊viewファイルで使用するコントローラーに準じたものを利用してください。

```posts_helper.rb
  def set_image(post)
      if post.image.present?
        post.image_url
      else
        "placeholder.png"
      end
  end
```

postを引数として、
もし、imageカラムに値があれば、その画像を。
なければ、STEP1で保存した画像
を返します。

##STEP3

実際に使ってみましょう。

一覧表示バージョンと詳細表示バージョンの例を今回は記載しようと思います。

```posts_controller.rb
  def index
      @posts= Post.all
  end
    
  def show
      @post = Post.find(params[:id])
  end

```

```posts/index.html.erb
   <% @posts.each do |t| %>
    :
    : 省略
    :
    <%= image_tag set_image(t) %>
    :
    : 省略
    :
  <% end %>
```

```posts/show.html.erb
    :
    : 省略
    :
    <%= image_tag set_image(@post) %>
    :
    : 省略
    :
```

このように　imageカラムを持つレコードを引数にセットするのがポイントです。

##番外編

ユーザーのプロフィール画像機能をつけた人も同様にできるのでやってみてください。

[GeekSalon](https://bit.ly/3fYvbtm)
【Vue】crypto-jsを用いて暗号化したデータをLocalStorageに保存する

## はじめに

「Vuexに保持してあるデータはリロードすると消えるのかい？！」
「でもLocalStorageにそのまま保存するのは危険ではないかい？！」
　＼じゃあ暗号化しよう！／

ということで、暗号化したデータをLocalStorageに保存する方法をご紹介します。

## 使用するライブラリ

[crypto-js](https://github.com/brix/crypto-js)

参考： [CryptoJS](https://cryptojs.gitbook.io/docs/)


## インストール

```
npm install crypto-js
```

もしくは

```
yarn add crypto-js
```

TypeScript環境では、上記だけだと怒られてしまうので、以下を実行しましょう

```
npm install --save @types/crypto-js
```

もしくは

```
yarn add @types/crypto-js
```

## 実装

```sample.ts
import crypto from 'crypto-js';

// 暗号化する
const ecrypted = crypto.AES.encrypt('暗号化したいデータ', '任意の暗号化フレーズ');

// LocalStorageに保存する
// 注意！:暗号化した値を使用する時は、toString()を忘れずに
localStorage.setItem('ecryptedData', ecrypted.toString());

// LocalStorageから取り出す
const ecryptedData = localStorage.getItem('ecryptedData')

// 復号する
// 注意!:復号化した値を使用する時は、エンコードを忘れずに
const decrypted = crypto.AES.decrypt(ecryptedData, '任意の暗号化フレーズ');
console.log(decrypted.toString(crypto.enc.Utf8));
```

## 注意点

上でも書いておりますが、

**暗号化した値を使用する時は、toString()を忘れずに。**
**復号化した値を使用する時は、エンコード = toString(crypto.enc.Utf8)を忘れずに。**
ASUS CM5500FDA メモリ不具合

どうにもすぐにファンが回るchromebook。これスワップしてる？ってきになってメモリを調べてみました。

で、絶句。8GB仕様のはずが4GB弱しかねぇし。
![Screenshot 2021-08-18 21.09.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1864453/1f1d6b77-0688-91be-c894-a4c228f1019c.png)

amazonの評価で同事象のものがあったので、あれか！って思いましたが、急いで公式に問い合わせてみました。

```
Chromebook のハードウェアをリセットする
https://support.google.com/chromebook/answer/3227606?hl=ja

Chromebook を初期状態にリセットする
https://support.google.com/chromebook/answer/183084?hl=ja&ref_topic=3417251

もし、上記の操作方法をお試しいただいても、症状が改善されない場合は、
当社修理センターより一旦検証させていただく必要がございます。
```

ってことで上記2つの操作を試します。
まぁこれで治るはずないですよね。

ってことで修理へ。
23日に引取、27日に回答がきました。

```
お客様指摘症状につきましてはGoogleOS起因で誤って認識されている状況となっております。
こちらにつきましては下記FAQにも記載されており、回避策の記載もございますのでご参照いただけますようお願いいたします。
https://www.asus.com/support/FAQ/1046420
現在、こちらについてはGoogleOSの更新にて解消される予定となっておりますが日程については未定となっておりますので
```

はっ、なにそれ。
最初の問い合わせでその回避策を提示できたんとちゃうのか？って内容でした。
OSの問題ってことだそうですが、こんなFAQレベルの提示でいいのか？って感じです。

無駄な修理になってしまった。

しかし回避策でなぜ大丈夫になるのか。本格対応と何が違うのか、謎が多すぎです。
これでandroid studioも普通に動くようになってくれるといいのですがね。

##不具合改善？？？
端末リセットして確認してみました。

https://qiita.com/irisis2021/items/c9721cd6c893f98f0f83
PostgreSQLがcould not locate a valid checkpoint recordというエラーで起動しなくなったとき

DockerでPostgreSQLを運用しているのだが、メンテナンスのためにDBを停止しようとして、誤って`Ctrl-C`を連打してしまい強制終了してしまった。
慌てて再起動を試みるも、次のようなエラーで起動しなくなっていた。

```
2021-08-27 16:16:22.532 UTC [1] LOG:  starting PostgreSQL 13.4 (Debian 13.4-1.pgdg100+1) on aarch64-unknown-linux-gnu, compiled by gcc (Debian 8.3.0-6) 8.3.0, 64-bit
2021-08-27 16:16:22.532 UTC [1] LOG:  listening on IPv4 address "0.0.0.0", port 5432
2021-08-27 16:16:22.532 UTC [1] LOG:  listening on IPv6 address "::", port 5432
2021-08-27 16:16:22.536 UTC [1] LOG:  listening on Unix socket "/var/run/postgresql/.s.PGSQL.5432"
2021-08-27 16:16:22.542 UTC [27] LOG:  database system was shut down at 2021-08-27 16:13:35 UTC
2021-08-27 16:16:22.543 UTC [27] LOG:  invalid primary checkpoint record
2021-08-27 16:16:22.543 UTC [27] PANIC:  could not locate a valid checkpoint record
2021-08-27 16:16:22.710 UTC [1] LOG:  startup process (PID 27) was terminated by signal 6: Aborted
2021-08-27 16:16:22.710 UTC [1] LOG:  aborting startup due to startup process failure
2021-08-27 16:16:22.712 UTC [1] LOG:  database system is shut down
```

ポイントは7行目の

```
PANIC:  could not locate a valid checkpoint record
```

で、Stack Overflow[^1]によるとWAL（トランザクションログ）が壊れているらしい。
[^1]: https://stackoverflow.com/questions/66537747/

データのバックアップを取った後に、以下のコマンドでWALをリセットして復旧を試みる（PostgreSQL 9までは`pg_resetxlog`というコマンドだったらしい）。

```
pg_resetwal /var/lib/postgresql/data
```

Docker Composeで停止中のコンテナに対して実行する場合は以下の通り。
`DB_USER_NAME`は、PostgreSQLの起動時に環境変数`POSTGRES_USER`で指定したユーザー名（デフォルトは`postgres`）。
`COMPOSE_SERVICE_NAME`は、`docker-compose.yml`で指定したデータベースコンテナのサービス名。

```
docker compose run --user=DB_USER_NAME COMPOSE_SERVICE_NAME pg_resetwal /var/lib/postgresql/data
```

コマンドの実行後はデータ破損がないか確認し、必要に応じて修正を行うこと。私の環境では現在のところ正常に稼働している。
【備忘録】【エラー解決】npm run startでnode serverを立ち上げたら400系エラー発生

下記コマンドでnodeのSSRサーバーを立ち上げる。

```ruby:ターミナル
% npm install
% npm run start
```

上記コマンドの結果、http://localhost:8080/ が開くようにはなった。
しかし、画面上で400系のエラーが発生。。

# 原因
同時に立ち上げているelasticsearchにまだデータが入っていないことだと判明。

# インデックスにドキュメントを入れる

インデックスに、検索対象にしたいドキュメントを入れていく。
（Elasticsearchでは、インデックスに入っているデータのことを"ドキュメント"と呼ぶ。）

①データ管理はrailsサーバー側で行っているため、rails consoleを立ち上げる。consoleの中で、下記コマンドを打ってindexを作成。

```ruby:コンソール
[1] pry(main)> Product.__elasticsearch__.create_index! force: true
Elasticsearch::Transport::Transport::Errors::BadRequest: [400] {"error":{"root_cause":[{"type":"illegal_argument_exception","reason":"Custom Analyzer [japanese] failed to find tokenizer under name [kuromoji_tokenizer]"}],"type":"illegal_argument_exception","reason":"Custom Analyzer [japanese] failed to find tokenizer under name [kuromoji_tokenizer]"},"status":400}
from /Users/●●/project/●●web_server/vendor/bundle/ruby/2.6.0/gems/elasticsearch-transport-7.5.0/lib/elasticsearch/transport/transport/base.rb:205:in `__raise_transport_error'
```

エラーが発生。indexが作成できない。。

# 原因
エラー文に書いてある通りで、kuromoji_tokenizer がないことが原因だった。
kuromoji_tokenizer は デフォルトでは elasticsearch にインストールされていないため、手動で入れる必要がある。


# kuromoji_tokenizerのインストール

### 注意点
私の場合はelasticsearchのバージョンが7.10.2なので、それに合わせて下記の通りkuromoji_tokenizerも7.10.2をインストールしています。
そのため下記コマンドはご自身のバージョンに合わせて、適宜変更してください。


```ruby:ターミナル
%　/usr/local/Cellar/elasticsearch/7.10.2/bin/elasticsearch-plugin install https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-kuromoji/analysis-kuromoji-7.10.2.zip
```

```ruby:結果
warning: no-jdk distributions that do not bundle a JDK are deprecated and will be removed in a future release
-> Installing https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-kuromoji/analysis-kuromoji-7.10.2.zip
-> Downloading https://artifacts.elastic.co/downloads/elasticsearch-plugins/analysis-kuromoji/analysis-kuromoji-7.10.2.zip
[=================================================] 100%
-> Installed analysis-kuromoji
```

# インストール状況の確認

```ruby:ターミナル
% elasticsearch-plugin list
```

```ruby:結果
analysis-kuromoji
```

インストール成功。


ではもう一度rails consoleを立ち上げて、index作成コマンドを実行してみる。

```ruby:コンソール
% rails c

[1] pry(main)> Product.__elasticsearch__.create_index! force: true
=> {"acknowledged"=>true, "shards_acknowledged"=>true, "index"=>"●●_products_development"}

```

成功！
indexが作成できたため、続いてindexの中にドキュメントを登録するコマンドを実行する。

```ruby:コンソール
% rails c

[2] pry(main)> Product.__elasticsearch__.import
   (1.1ms)  SET NAMES utf8,  @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'),  @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483
[...省略...]
  SubCategory Load (0.3ms)  SELECT `sub_categories`.* FROM `sub_categories` WHERE `sub_categories`.`id` = 9 LIMIT 1
=> 0
```

無事にドキュメントが登録できた。

もし、kuromoji_tokenizerをインストールしたのにもかかわらず同じエラーが発生した場合は、Homebrewをアップグレードしてみてください。

```ruby:ターミナル
% brew upgrade
```

私の場合は上記で上手くいきました。

それでも上手くいかない場合はこちらの記事を確認してみてください。

https://qiita.com/Syun00/items/f990322ae462abb2e6d9

最後にelasticsearch、npm run startを再起動し、無事に400系エラーが解消して環境構築用の画面が正しく表示されました。
React入門 - Part8 - hooksについて

# 目次

# React hooksとは

- Reactの機能(状態管理、ライフサイクルメソッド)をクラス無しで使うための仕組み
- React 16.8 で追加された新機能

何を言っているかよく分かりませんね。
現在は、おそらくですが、クラスでReactを実装することはあまり無く、関数コンポーネントで実装していくことが多いと思います。
ですので、あまり深く考えず、進んで、ちょっと慣れてきてから再度`hooks`とはを調べてみてもいいかと思います。

ライフサイクルメソッドについて、少し触れておきますと、
Mounting(マウント時)、Updating(更新時)、Unmounting(マウント解除時)のタイミングで処理するメソッドのことです。
そのライフサイクルメソッドがクラスを用いた実装ではなく、コンポーネントを用いた実装が行えるということですね。


# React hookの種類(基本)

以下３つは基本なので、必ず(使い方を)覚えて下さい。使わないことはないです。

### useState

  - ステートを管理するhook。
  - 可変のデータ。
  - コンポーネント自体によって保持される
  
　つまり、普通にコンポーネントの変数みたいに思っていれば問題ないと思います。

　実装方法

  ```typescript
  const [count, setCount] = useState(0)
  とか
  const [name, setName] = useState('')
  ```

 `[]`内の左の値は、値を取得するもの(変数)
 `[]`内の右の値は、値を設定取得するもの
 usestateの`()`括弧内は初期値

値は配列やオブジェクト型でも構いません。


### useEffect

 - 関数の実行タイミングをReactのレンダリング後まで遅らせるhook
 - 画面が描写された後に実行される

実装方法(レンダリング毎に実行)

```typescript
  useEffect(() => {
    処理
  })
```

実装方法(初回レンダリング時に実行)

```typescript
  useEffect(() => {
    処理
  }, [])
```

実装方法(特定値の変化時に実行)

```typescript
  useEffect(() => {
    処理
  }, [特定値])
```


### useContext

　　[React入r門 - Part4.2](https://qiita.com/yokowake12345/items/92ac41a616321d944462)を参照してください。

# React hookの種類(追加)

- useCallback
- useMemo

 こちら二つは、パフォーマンスな観点から式、値をメモ化しておくというものです。

　★★★使用例、自Qiitaへのリンク、他サイトへのリンク、説明を載せる
　　<font color="red">執筆中</font>

- useLayoutEffect

　useEffectとほとんど使い方は同じです。処理されるタイミングが違うだけです。
　実際にuseEffectと明確に実装を使い分けた現場がありませんでした。

- useRef
- useReducer

　こちら二つは、現場でもチラホラと実装を見かけたが、私のスキルストックに無いので
　割愛します。
　学んだら追記します。

- useImperativeHandle
- useDebugValue

　すみません。名前すら知らない。ので、興味ある方は自分で調べて下さい。。。。

# hookのルール

1. フックを呼び出すのはトップレベルのみ
2. React関数コンポーネント内から呼び出す
3. 独自(カスタム)フック内から呼び出す

順番に解説していきます。

# hookのルール(1. フックを呼び出すのはトップレベルのみ)

<font color="red">執筆中</font>

# 独自(カスタム)フックの作成方法

これが出来たら、初学者から脱出出来ます。

<font color="red">執筆中</font>
fastlaneのdeliverからscreenshots送信する方法

### 概要

2021/08 時点で、fastlane の deliver アクションからAppStoreのスクリーンショットを更新する方法を記載します。
そのまま利用しようとすると、第3世代iPadPro画像が登録されなかったので、その辺についても記載しています。

### スクショ準備

もし既にリリース済みのアプリにおいてスクショを用意したいのであれば、

```shell
fastlane deliver download_screenshots --use_live_version true
```

のコマンドで現状のスクショをダウンロードすると良いです。

ちなみに、`download_screenshots` のアクションは `api_key` に対応していないので、コマンド途中でAppStoreへのログイン処理と2FA対応が必要になります。

すでにリリースされていたスクショを取得すると、`/screenshots` フォルダができるかと思います。
ダウンロードしたフォルダ内を覗くとファイル名が `0_APP_IPAD_PRO_3GEN_129_0.png` みたいな名前の画像がいくつか格納されていると思います。

新規にアップする場合は `screenshots` フォルダを `/fastlane` 配下にでも作成してください。
そしてここに必要なスクショを全て格納してください。

## 画像命名規則の変更

さて、画像の準備はこれでOK。

と思ったら大間違いですw

2021/08 時点では、このまま `deliver` から `screenshot` を登録しようとすると、第3世代のiPadPro用(12.9-inch用)の画像だけ登録されません！
そうです、罠です。

なぜかというと `fastlane` の内部では決まった命名規則に従って、画像をAppStoreに送信しているのですが、AppStore定義の画像名が第3世代のiPadPro用だけ `fastlane` でうまく扱われないためです。
なのでダウンロードしてきた画像、あるいは用意したスクショに対して、下記の命名規則でリネームする必要があります。

それは `{num}_{deviceType}_{num}.{name}.png`といった形になります。

### 画像のリネーム

#### スクショの番号
まず、{num} の部分にスクリーンショット1つ目に使いたい画像を 0 から数えた数で記載します。

一つ目なら
`0_{deviceType}_0.{name}.png` になります。

二つ目なら
`1_{deviceType}_1.{name}.png` と num 部分をインクリメントしていきます。


#### 対応インチ数に応じた deviceType 名
次に `deviceType` を記載します。

各スクリーンサイズで `deviceType` 名が決まっているので、それを記載します。
2021/08/27 時点では下記のような `deviceType` があります。

![スクリーンショット 2021-08-27 14.05.20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/50890/8e467024-9d01-8ee8-7dca-2acb09799202.png)

2021/08/27 時点で、iPhoneアプリ申請に必要となるのは

```
5.5インチ用画像
6.5インチ用画像
iPadPro用12.9インチ画像
iPadPro第3世代用12.9インチ画像
```

の4種類になります。

従って、

```
{num}_ipadPro_{num}.{name}.png
{num}_ipadPro129_{num}.{name}.png <- 第3世代用
{num}_iphone55_{num}.{name}.png
{num}_iphone65_{num}.{name}.png
```
といった4種類の `deviceType` 用画像が必要になります。

#### 固有の画像名

最後に必要となるのは {name} の部分ですが、ここには画像固有の名前を入れれば大丈夫です。
なので `image0` とでも入れておけば良いと思います。


これで必要な画像に対して、正しい命名規則の名前を当て込めると思います。
ex.
`0_ipadPro_0.image1.png`


## 画像のアップロード

fastlane の deliver を利用してスクリーンショットを登録するには下記のように指定して実行します。

```swift
    deliver(
      api_key: {app_store_connect_key},
      submit_for_review: false,   # 申請を出さずにスクショだけ送信するなら false
      skip_binary_upload: true,   # アプリのバイナリをアップしないなら true
      skip_screenshots: false,    # スクショのアップロードをskipしないので false
      screenshots_path: "fastlane/screenshots",  # スクショの保存先フォルダPath
      overwrite_screenshots: true,   # スクリーンショットは常にファイル内のもので更新したいので true
      run_precheck_before_submit: false    # 2021/08現在、api_keyを利用すると検証がこけるので false
    )
```

特に、`screenshots_path` にフォルダpathを指定するのを忘れないようにしてください。
また現在（2021/08現在）では、api_key を利用しないと 2FA でコマンド処理が止まるので、CIなどで管理したい場合はそちらを利用することをお勧めします。

関連ドキュメントは [こちら](https://docs.fastlane.tools/app-store-connect-api/)

正しい命名規則の画像が用意されていれば、これでアップロードできると思います。
ただ、AppStoreにあるのが申請済みのアプリバージョンだとこけますので、新規の申請バージョンを用意してください。

`deliver` を実行するレポジトリ内の xcode projectfile に新規バージョンを指定するか、AppStoreで直接作成すれば良いと思います。
JavaScriptを基本からまとめてみた【18】【WebAPIを叩く】

##はじめに

####学習するに至った経緯
2020年より、未経験からエンジニアへの転職を目指し、某プログラミングスクールへ通う。入学後、『Ruby』を未経験から学ぶ人が多いのと『Ruby』の求人が思っていた以上に少ないので、卒業後、フロントエンドのエンジニアを目指す事に。
Javascriptの学習した事を言語化し、認識の深化による備忘録として記載。

##WebAPIを叩くとは
『WebAPIを叩く』とは、プログラマー的表現でプログラミング上から外部とデータのやり取りをする事を指す。

##UIとは
『UI』とは、ユーザーインターフェイス（User Interface）の略称で、一般的にユーザー（利用者）と製品やサービスとのインターフェース（接点）すべてのことを意味する。
WebサイトでいうところのUIは、サイトの見た目や、使いやすさのことを指す。よくUI＝見た目、と勘違いをしている方もいるが、レイアウトや使用されている画像はもちろん、文字のフォント、メニューやボタンの操作性などユーザーが目にするもの・操作するものすべてが含まれる。

##index.htmlを作成

```index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <title>WebAPIの練習</title>
</head>
<body>
    <p>Chorome DevTools で console を開いてね</p>
    <script src="main.js"></script>
</body>
</html>
```

##JavaScriptでAPIを叩くコードを書く

#####①　実際に呼び出しが出来ているか、consoleで確認

```main.js
function callApi() {
  //実際にAPIを叩く処理
  console.log("foo");
}
callApi();
```

#####② WebAPIを叩いて、console上に表示する

```main.js
function callApi() {
  //windowオブジェクトにあるfetchというメソッドを使用し、APIを叩く
  const res = fetch("https://jsonplaceholder.typicode.com/users");
  console.log("res");
}
callApi();
```

#####③ async/await を使用する

```main.js
async function callApi() {
  //windowオブジェクトにあるfetchというメソッドを使用し、APIを叩く
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  console.log("res");
}
callApi();
```

#####④ Jsonメソッドを使用する

```main.js
async function callApi() {
  //windowオブジェクトにあるfetchというメソッドを使用し、APIを叩く
  const res = await fetch("https://jsonplaceholder.typicode.com/users");
  const users = await res.json();
  console.log("users");
}
callApi();
```


##参考サイト
[【JavaScript入門 #8】WebAPIを叩いてみよう！async await構文を使うと簡単！【ヤフー出身エンジニアの入門プログラミング講座】]
(https://www.youtube.com/watch?v=QugDLcOo_EE&t=70s)
[今さら聞けない！ UI（ユーザーインターフェース）とは？]
(https://www.m-hand.co.jp/design/7161/)
【UiPath】SAPのGUIを操作してみる（UiAutomation編）


# はじめに

この投稿は、RPAツール「UiPath」で SAPのGUI操作をする 記事です。

以下の 4日目の投稿でもあります。

https://note.com/chillsap/n/n08ef5ec73b4c

今回は「UiAutomation編」として、GUI操作について記載します。

# UiAutomationとは

SAPのGUIを操作する場合、画面の要素を「セレクター」として解釈しますが、解釈は「UiAutomation」が実施します。

UiAutomationはUiPathがパッケージとして提供していて、随時アップデートされています。

https://docs.uipath.com/releasenotes/lang-ja/docs/uipath-ui-automation-activities

基本的には「バージョンが新しいほど、正確に読み取ることができる」ようになっているので「できるかぎり新しいもの」を使ったほうが良いのですが、使用できるバージョンの範囲は、購入しているUiPathライセンスのバージョンによって異なります。

| UiAutomationのバージョン | 使用できるUiPathのバージョン |
|:-:|:-:|
|20.10 - 21.4　| V20.10以上 |
|19.5 - 20.4　| V2019.2以上 |
|18.3 - 19.4　| V2018.3以上 |

# UiAutomationとSAP

上で書いたとおり「UiAutomationは新しいほどよい」のですが、
SAPのGUI操作でいえば「UiAutomationのv20.10」で大きく改善されています。

なので、SAPのGUI操作したいのなら、

- UiAutomation「v20.10」以降
- UiPath自体のバージョン「20.10」以降

にしたほうが圧倒的に良いと思います。

以下で、UiAutomationが「SAP」の操作に関して、どのようにアップデートを行ってきたかを見てみます。

| Version | Date | Description |
|:-:|:-:|:-|
| v21.4  | 2021 年 4 月 26 日  | SAP GUI for Windows の最新バージョンである 7.70 をサポート<br>SAP ALV テーブルのデータを抽出できるように|
|v20.10 | 2020 年 10 月 12 日 |SAP WinGUI の自動化に特化した「表のセル スコープ」アクティビティの追加<br>SAP Fiori 用のセレクタ強化<br>SAPのテーブル列セレクターの改良（数字の代わりに列名を返す）|
|v20.4|2020 年 5 月 6 日|SAP 向けに特別に調整された一連のアクティビティを新しく提供（SAPにログオンなど）|
|v19.10|2019 年 11 月 11 日|SAP のポップアップ ウィンドウ上でも対話型の UI 選択／セレクター生成がされるように<br>「構造化データを抽出」アクティビティが SAP GUI の表形式ヘッダー名をサポート<br>「クリック・チェック」アクティビティが、SAP のグリッド テーブルの制御と対話できるように|
|v19.7|2019 年 7 月 16 日|セレクター生成が改善され、SAP セッション ウィンドウを一意に識別できるように<br>SAP要素を示す場合、既定の SAP セレクター以外の AA セレクターを生成できるように|
|v19.6|2019 年 6 月 24 日|SAP における要素検出について、いくつかの改善が行われました|
|v19.5|2019 年 5 月 21 日|SAP Business Client 6.5 のツリーに対してセレクタを生成できるように|

先の述べたとおり「v20.10」で要素認識の技術がかなり改善がされていて、セレクタをより早く正確に取れるようになっている印象があります。

もちろん、操作したい画面によっては「セレクタ取れない」こともあるとは思います。


# 鬼門のポップアップ

SAPのGUI操作では「ポップアップウィンドウ」は以下の点で厄介です。

```
1。予想していない場面で出現してくる
2。ポップアップは何種類かあり、要素・セレクタが微妙に違う
3。データ次第では、ポップアップが順不同で大量に連続で表示される
```

例えば「受注伝票入力」で、型番を入力してEnterを押すと、確認として「商品情報」が表示されますが、その際に商品に「アラート情報」が設定されているだと、急に画面に「ポップアップ」が表示されることがあります。（商品にアラート情報が設定されていないと表示されない）

なので「Enter後にポップアップが出るかもしれない」と予測して、画面検出する必要があります。そして、このポップアップは1種類ではなく、複数の種類があります。

＜確認ポップアップの例＞
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/0b945208-29b6-4a12-4aeb-289c3e0de98c.png)

一番厄介なのが「ポップアップが順不同で、複数種が同時多発的に表示される」ケースです。

この場合、以下のようにすれば制御ができます。

```
1）考えられる種類のポップアップ画面で「並列」アクティビティを配置
2）並列処理内で「要素を取得」と「要素のIsVisible」を確認する処理を実施
　　＝ 「visible=true」なら表示されていると判定
3）表示されているポップアップを判定し、処理する
4）1に戻る（次のポップアップ判定へ（以降、ポップアップが無くなるまで繰り返し））
```

複数のポップアップが連続で表示されたとき、現在表示されているポップアップは「要素は残っているが、画面上は非表示になっている」のがポイントです。

# 終わりに

いかがでしたでしょうか？開発の参考になれば幸いです。
この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
BlenderでLaserPacker2向けの出力設定

#はじめに
備忘録です
[この動画（How To Design & Export A Laser Cutting File From Blender 2.83 | Tutorial |(Blender To Laser Cutter)）]
(https://www.youtube.com/watch?v=mDddxy3Hqzc&t=300s)
を参考に

以下のSVGプラグインで出力設定
-Video Showcasing Outline To SVG: https://youtu.be/4BGDLjUaMgQ
Outline To SVG download: [bit.ly/Outline2SVG](bit.ly/Outline2SVG)

を調べてみた備忘録。


blenderで作図し
LaserPacker2向けにInkscapeのSVGを出力する設定を探していて
いろいろ試した結果

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/00761d4e-302d-0334-b4ae-4113b41d8680.png)
サイズ：1m
DPI:24  (72/3)


という設定で書き出すと
Inkscape上ではスケールがずれてしまっているのですが、
[laserPacker2のプラグイン](https://github.com/yy502/inkscape-laserpecker)
を通し、
実際にカットしてみると
実寸5cmになり、

blenderで用意した5cmのボックスの輪郭と同じサイズになりました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/976366ab-6329-28e7-d2d6-84f065005ed2.png)

![A789D794-93B3-4B1A-92B8-1E9F553F45CC.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/c8619ac0-b75b-af35-369f-9a1eef973a53.jpeg)


#おわりに
それぞれのプラグインの解釈部分の謎が多いのと、
うまく動いていない部分もあるような気がしています。
何か設定をミスしているかもですが、ひとまずこれで、blenderで作図ができそうです。


# 追記テスト（2021-08-29)
Blenderでモデルのスケールがおかしいことに気が付く。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/614859d3-82e6-ef96-bba2-d5a691b66ae5.png)
オブジェクトのアイテムのスケールが0.25になっているので、
これを　
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/9f7ecf29-0883-c824-d1e7-40de0f7b7e52.png)
オブジェクト＞クリア＞スケール
すると
サイズが大きくなる・・・
じゃなくて、
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96808/785c2520-5f92-ea74-7e5a-3ec9dd3b81bb.png)
オブジェクト＞適用＞スケール
とすると、見た目の大きさを保ったまま
スケールだけ1.00にもどる。

・・・としても変わらなかった・・・　うーむ。　やはり謎のまま。
【UiPath】SAPのGUIを操作してみる（準備編）

# はじめに

この投稿は、RPAツール「UiPath」で SAPのGUI操作をする 記事です。

以下の 28日目の投稿でもあります。

https://note.com/chillsap/n/n08ef5ec73b4c

今回は「準備編」として、基礎的な知識について記載します。

# 1. Guiスクリプティングを有効にする

UiPath で SAP GUI 版の操作をするためには、SAPサーバー側とクライアント（UiPathが動くマシン）で「GUIスクリプティング」を有効にする必要があります。

有効にしていないと、以下のようなポップアップが表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/c084ddce-abfa-e9ff-da9d-a2a0f6f0e053.png)

クライアント側の設定は以下の手順で行います。

```
ツールバー > 右側の歯車マーク > オプション（O) 
 >  SAP GUI オプションウィンドウ > アクセシビリティ＆スクリプト
   > スクリプト > ユーザー設定 > スクリプト有効化（E） にチェック
```

![27920c8-4_SAP_GUI_Options.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154139/05f1bc36-d5ba-7046-f30d-0378d4d3ca0f.png)

この「有効化」は「UiPathで 初めてSAPを触る人（SAPに詳しい人は除く）」は、知らないとハマって時間をロスします。以下は UiPath の公式ドキュメントです。

https://docs.uipath.com/studio/lang-ja/v2018.4/docs/enabling-sap-gui-scripting


# 2. marketPlaceを覗いてみる

準備ができたら、早速実装したくなりますが、その前に「すでに提供されている部品が無いか、使えないか」をチェックしたほうが良いかも知れません。


UiPathにはマーケットプレイスという場所があり、再利用可能なさまざまな自動化部品が、コンポーネントとしてデベロッパーや企業、団体から提供されています。利用は、基本的に無料です。

https://marketplace.uipath.com/ja/listings?query=SAP

SAPは、他の企業も同じインターフェース・APIで自動化しているので、流用できる可能性が高くなります。

勿論、要件・仕様によっては「ちょっとこれは使えないなぁ」というものもあります。


# 終わりに

いかがでしたでしょうか？開発の参考になれば幸いです。
この記事が参考になったら、 LGTMをお願いします。閲覧ありがとうございました。
RAM、ROM、メモリって？？

#目次
[1.問い](#1-問い)
[2.回答](#2-回答)
[3.参考](#3-参考)

#1. 問い

### Q：RAM、ROM、メモリってなに？

#2. 回答

## ○RAM、ROM、メモリの大まかな説明

**メモリ：必要なデータを記録する装置のこと。**

### ●＜では、RAMと、ROMは？＞

| メモリ | 説明・特徴 |
|---|---|
| RAM(Random Access Memory) | 読み書き可 / 揮発性 |
| ROM(Read Only Memory) | 読み出しのみ(*例外あり) / 不揮発性 |

### ●＜読み書きについて＞
その名の通り、
・読み：データの読み込み
・書き：データの書き込み

### ●＜揮発性 / 不揮発性＞
・揮発性：電源を切ると、データが消える。
→OSやアプリケーションが動作する際の作業スペースの役割がある。

・不揮発性：電源を切っても、データが残る
→データを保存・記録するためのストレージとして使用される。

## ○RAMを詳しく

RAMからさらに2種類に分かれます。

| RAM | 説明・特徴 |
|---|---|
| DRAM(Dynamic RAM) | 主記憶装置に使用 / ¥安い / 容量大 / SRAMより遅い  |
| SROM(Static RAM) | キャッシュメモリに使用 / ¥高い / 容量小 / DRAMより高速 |

### ●＜主記憶装置とは？＞

**起動するプログラムを一時的に記憶しておく装置。**

揮発性ですね。

では、なぜ揮発性の主記憶装置にわざわざ一時保存をするのか？（不揮発性じゃダメなのか？）

###●＜なぜ揮発性の主記憶装置にわざわざ一時保存をするのか？＞

まずは、３つの関係性から。

**CPU - 主記憶装置 - 補助記憶装置（ハードディスクなど）**

- CPU：主記憶装置にあるOSやアプリケーションを動作させる。
- 主記憶装置：補助記憶装置からデータを取り出す
- 補助記憶装置：主記憶装置にデータを渡す

それぞれに上記の役割があります。

（補助記憶装置から直接、CPUにデータを渡せばいいじゃないのか？）

そうではなく、
**補助記憶装置は処理速度が遅く、CPUの早さについていけるのは、主記憶装置だから**です

以下の記事がわかりやすかったです。

https://www.yamanjo.net/knowledge/structure/structure_03.html

## ○ROMを詳しく

**※ ROMは、読み出しのみと上記で記載したが実は、読み書きができるROMもあります。**

| ROM | 説明・特徴 |
|---|---|
| マスクROM | 一般的 / 読み出し専用 / 製造時点でデータが書き込まれている。 |
| PROM(Programmable ROM) | ユーザーが書き換え可 |

PROMも3種類に分かれる
1. EPROM・・・紫外線で書き換え
2. EEPROM・・・電気的にデータを消去して書き換え
3. フラッシュメモリ・・・EEPROMの１種。ブロック単位でデータを消去して書き換え。（例：SDカード）

#3. 参考
https://www.amazon.co.jp/%E3%82%AD%E3%82%BF%E3%83%9F%E5%BC%8F%E3%82%A4%E3%83%A9%E3%82%B9%E3%83%88IT%E5%A1%BE-%E5%9F%BA%E6%9C%AC%E6%83%85%E5%A0%B1%E6%8A%80%E8%A1%93%E8%80%85-%E4%BB%A4%E5%92%8C03%E5%B9%B4-%E3%81%8D%E3%81%9F%E3%81%BF%E3%82%8A%E3%82%85%E3%81%86%E3%81%98/dp/4297117819

https://www.pro.logitec.co.jp/houjin/usernavigation/hddssd/20191220/
CRC-32 in C#

# まえがき

標準では用意されていなさそうだったので、[Wikipedia](https://ja.wikipedia.org/wiki/%E5%B7%A1%E5%9B%9E%E5%86%97%E9%95%B7%E6%A4%9C%E6%9F%BB)に載っているCのソースコードをもとにC#に移植してみた。
※32bitのCRCは1種類ではないので注意。

通常、「CRC-32」とだけ書いた場合は、生成多項式として
$$x^{32} + x^{26} + x^{23} + x^{22} + x^{16} + x^{12} + x^{11} + x^{10} + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1$$
を使うものを指すよう。
ソースコード上にでてくる`0xEDB88320`は、生成多項式を16進数表記にした`0x04C11DB7`のビット順序を反転させたものになっている。

# ソースコード

```csharp:Crc32.cs

using System;

public static class Crc32
{
    static uint[] crcTable = MakeCrcTable();

    static uint[] MakeCrcTable()
    {
        uint[] a = new uint[256];
        for (uint i = 0; i < a.Length; i++) {
            uint c = i;
            for (int j = 0; j < 8; j++) {
                c = ((c&1)!=0) ? (0xEDB88320 ^ (c >> 1)) : (c >> 1);
            }
            a[i] = c;
        }
        return a;
    }

    public static uint Calculate(byte[] buf)
    {
        return Calculate(buf, 0, buf.Length);
    }

    public static uint Calculate(byte[] buf, int start, int len)
    {
        uint c = 0xFFFFFFFF;
        checked{
            if (len<0) {
                throw new ArgumentException();
            }
            if (start<0 || start+len>buf.Length){
                throw new IndexOutOfRangeException();
            }
        }
        for (int i=0; i<len; i++) {
            c = crcTable[(c ^ buf[start+i]) & 0xFF] ^ (c >> 8);
        }
        return c ^ 0xFFFFFFFF;
    }
}

class CrcSample
{
    [STAThread]
    static void Main(string[] args)
    {
        byte[] t = new System.Text.ASCIIEncoding().GetBytes("123456789");
        uint crcResult = Crc32.Calculate(t);
        Console.WriteLine("0x" + crcResult.ToString("X08"));
    }
}
```

# 参考サイト

 - [巡回冗長検査 - Wikipedia](https://ja.wikipedia.org/wiki/%E5%B7%A1%E5%9B%9E%E5%86%97%E9%95%B7%E6%A4%9C%E6%9F%BB)
 - [Online CRC-8 CRC-16 CRC-32 Calculator](https://crccalc.com/)
 - [Catalogue of parametrised CRC algorithms](https://reveng.sourceforge.io/crc-catalogue/17plus.htm)
業務未経験者のコーディング試験のチェックポイント

本記事は採用担当向けです。

業務未経験者のコーディング試験は10分間のFizzBuzzもどきで十分だと思っています。全く同じテストを数百人にテストしていますが、割とはっきり結果が出ます。学習経路に依存せず「知ってる・知ってない」レベルでもないからです。

例えば、プログラミングスクールでRailsアプリを作っていても、FizzBuzzができない人はいます。コマンド叩くだけでアプリケーションが作れてしまうので、Railsの完成度に感動してしまいます。

最近はオンラインでの面接ができるようになってきたので、画面共有をしてもらってコーディング作業そのものを見せてもらっています。

以下チェックポイントです。

- 自分のPCが使えるか
    - 今どきの求人サイトはスマホで履歴書まで作れちゃうのでPCが触れなくても書類選考までは通ってしまいます
    - PCでメールが使えるか
        - スマホのメールしか使えないと厳しい
        - docomo.ne.jpとかicloudが履歴書に記載されているメールアドレスの時点でPCベースでのIT接点が薄いことは分かる
    - PCメールの添付PDFを開けるか（ダウンロードフォルダをみたり、PDF何かしらのアプリで開けるということが必要）
    - PCでググってるか（スマホでないと検索できない人もいる）
    - よく知らないスパイウェアを入れすぎてPCが激重になってる人は会社にとってリスク要因
- カレントディレクトリの概念があるか
    - 作ったつもりのファイルの場所を探すのに時間がかかっちゃう人は、「やってない」です。Railsの前に一旦HelloWorldができるようになってください、というケースはあります。
    - 最悪ファイルをコピーすることができず「ソースのコピペでもいいですか？」「画面をスマホで撮影して提出でもいいですか？」というケースはある。スマホネイティブで育ってPCそのものに慣れていないと、ファイルが置かれてる場所を意識することがありません。
    - 恐ろしいことに手元でファイルを実行することもなく「競技プログラミングしてるけどブラウザ上でしか実行したことがない」という人もいます。しかしながらブラウザのテキストエリアにプログラムを書くだけの仕事はないんです。
- 小さく実行しているか
    - 全部書き終わってから、コンパイルや実行をしてどこで構文エラーが起きたかわかんなくなっちゃう人は慣れてない人です（本当に賢い人は一発で通るけど）
- 不慣れな関数をどうやって試しているか
    - irbなどの別の環境で関数の挙動を確認するなどせずに、いきなり初経験の関数を本物プログラムに組み込んじゃう人ははまります。
- 駄目なサイトをググってないか
    - 私のコーディング試験はググるのはありにしていますが、会話形式の無意味なコンテンツを見てる時点で「調べることに慣れてない」です
- 公式ドキュメント見慣れてるか
    - 公式ドキュメントは一見とっつきにくいですが「文字ばっかりの資料」を読む耐性があるかどうかは大事です。「動画なら理解できます」という人もいますが、残念ながら2021年時点でリファレンスは文字ベースです
- エディタの使い方
    - Wordでプログラムを書いちゃう人はテキストファイルの概念からやりなおし
    - メモ帳で書いて一発でコンパイルが通ればそれは天才だけど、普通の人はコンパイルさえとおらないプログラムができて終わり
    - エディタが早く起動できるかということも大事（道具を大事にしているかどうかが分かる）
- Macの仮想デスクトップで迷子になってないか
    - Macの仮想デスクトップでめちゃくちゃ迷子になってる人がいます。エンジニアリング以前の問題ですが、「こりゃぁ効率が悪いな」と思えるかどうかは仕事をする上で大事です

クラウドベースで開発できる環境も整っては来てはいるものの、2021年時点ではITエンジニアは基本は「ファイル作るマシーン」という点はまだ変わっていません。「良いプログラムを書く」以前に、適切なディレクトリに適切なファイル名で保存し徐々にファイルを育てるというのは、仕事の基本です。これはプログラマーも漫画家も変わりません。
【始め方】firebase functions + TypeScript + ESLint + prettier の始め方

## はじめに

firebase functions, TypeScript, ESLint, prettier を使用したプロジェクトの始め方を書いていきます。

https://qiita.com/hasehiro0828/items/d8f1dd2a72c7999c9b76　　　　　　　　　　　

この記事に書いていることを前提にしていたりするので、こちらも是非ご覧ください！

## プロジェクト作成

使用する node を用意します。

anyenv 経由で入れた nodenv でダウンロードしています。

【🚨**注意】**
M1 Mac は 14 以下に対応していないです。(Rosseta を入れれば使えるらしい）
Rosetta 入れたくないなぁって思っているので、とりあえず 16 使ってみてます。

```bash
nodenv local 16.7.0
```

`firebase-tools` をインストール

```bash
yarn global add firebase-tools
```

（一度もしていなければ）firebase のログイン

```bash
 firebase login
```

firebase functions の作成 & 移動

```bash
firebase init functions
cd functions
```

prettier 導入

【🚨**注意】**package.json の engins が node 14 想定なので、 一旦削除しないと出来ない

```bash
yarn add -D prettier eslint-config-prettier
```

@types/node 追加

```bash
yarn add -D @types/node@"14.17.12"
```

`@typescript-eslint/explicit-function-return-type` の rule を有効化する

```bash
rules: {
  "@typescript-eslint/explicit-function-return-type": "warn",
  ...
}
```

prettier に対応させるために、`.eslintrc.js` を修正して extends の**最後**に `"prettier"`を入れる

```bash
extends: [... "prettier"],
```

prettier の設定ファイルの作成

```bash
echo "module.exports = {\n\tprintWidth: 120\n}" > .prettierrc.js
echo "tsconfig.json" > .prettierignore
```

## import 周りいい感じにする

```bash
yarn add -D eslint-import-resolver-typescript
```

`.eslintrc.js` を編集

```bash
module.exports = {
  ...
  extends: [..., "plugin:import/recommended", "plugin:import/typescript", "prettier"],
  ...
  rules: {
    "import/order": [
      "error",
      {
        groups: ["builtin", "external", "parent", "sibling", "index", "object", "type"],
        // pathGroups: [
        //   {
        //     pattern: "@alias/**",
        //     group: "parent",
        //     position: "before",
        //   },
        // ],
        alphabetize: {
          order: "asc",
        },
        "newlines-between": "always",
      },
    ],
  },
};
```

`import/order` についてはこちらに記載されています

https://github.com/import-js/eslint-plugin-import/blob/master/docs/rules/order.md

`functions/src/index.ts`を見ると `Parsing error: Cannot read file`という eslint のエラーが出ていました。

https://stackoverflow.com/questions/64933543/parsing-error-cannot-read-file-tsconfig-json-eslint

を参考に、 `.eslintrc.js` を編集します

```bash
module.exports = {
  // ...
  parserOptions: {
    project: "tsconfig.json",
    tsconfigRootDir: __dirname,
    sourceType: "module",
  },
  // ...
}
```

## ホットリロード

Cloud Functions for Firebaseはローカルで実行することができます。

とても便利なのですが、デフォルトの状態ではtypescriptでホットリロードができないので、少し修正します。

`package.json` の `scripts` を編集

```diff
"scripts": {
  "lint": "eslint --ext .js,.ts .",
  "build": "tsc",
+ "watch": "yarn build -w",
- "serve": "npm run build && firebase emulators:start --only functions",
+ "serve": "firebase emulators:start --only functions",
- "shell": "npm run build && firebase functions:shell",
+ "shell": "firebase functions:shell",
  "start": "npm run shell",
  "deploy": "firebase deploy --only functions",
  "logs": "firebase functions:log"
}
```

`yarn watch` を実行し、別のタームナルで `yarn serve` を実行すると Hot Reload ができています。

## おわりに

以上で、firabase functions を快適に開発していく環境ができました🎉

`functions/src/index.ts` を編集していきましょう💪
2021-08-28 Godot Engine > 信号機のアニメーション > 二次元Array, 円の描画, Timer処理

### 動作環境

```
Windows 10 Pro v21H1
Godot Engine v3.3.2.stable.official
```

### 参考

- [信号機の点灯パターン](https://ameblo.jp/yuu09200920/entry-11166847103.html)
- [2Dカスタム描画](https://docs.godotengine.org/ja/stable/tutorials/2d/custom_drawing_in_2d.html)
- [How do I create a 2D array ?](https://godotengine.org/qa/5122/how-do-i-create-a-2d-array)


### 実装

```python:Main.gd
extends Node2D


# Called when the node enters the scene tree for the first time.
func _ready():
	pass # Replace with function body.

func draw_circle_arc_poly(center, radius, angle_from, angle_to, color):
	var nb_points = 32
	var points_arc = PoolVector2Array()
	points_arc.push_back(center)
	var colors = PoolColorArray([color])

	for i in range(nb_points + 1):
		var angle_point = deg2rad(angle_from + i * (angle_to - angle_from) / nb_points - 90)
		points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius)
	draw_polygon(points_arc, colors)
	
func draw_circle_arc(center, radius, angle_from, angle_to, color):
	var nb_points = 32
	var points_arc = PoolVector2Array()

	for i in range(nb_points + 1):
		var angle_point = deg2rad(angle_from + i * (angle_to-angle_from) / nb_points - 90)
		points_arc.push_back(center + Vector2(cos(angle_point), sin(angle_point)) * radius)

	for index_point in range(nb_points):
		draw_line(points_arc[index_point], points_arc[index_point + 1], color)

var array_1 = [1, 0, 0]
var array_2 = [1, 1, 0]
var array_3 = [0, 0, 1]
var array_4 = [0, 1, 0]
var array_2d = [array_1, array_2, array_3, array_4]
var pos_array = 0
const MAX_SIZE = 3

func _draw():
	var center = Vector2(200, 200)
	var radius = 40
	var color = Color(1.0, 0.0, 0.0)
	var angle_from = 0.0
	var angle_to = 360.0

	var onR = array_2d[pos_array][0]
	var onY = array_2d[pos_array][1]
	var onG = array_2d[pos_array][2]

	if onR:
		draw_circle_arc_poly( center, radius, angle_from, angle_to, color )	  # Red

	center = Vector2(300,200)
	color = Color(1.0, 0.8, 0.0)
	if onY:
		draw_circle_arc_poly( center, radius, angle_from, angle_to, color )	  # Yellow

	center = Vector2(400,200)
	color = Color(0.0, 1.0, 0.0)
	if  onG:
		draw_circle_arc_poly( center, radius, angle_from, angle_to, color )	  # Green

# Called every frame. 'delta' is the elapsed time since the previous frame.
#func _process(delta):
#	pass


func _on_Timer_timeout():
	pos_array += 1
	if pos_array >= MAX_SIZE:
		pos_array = 0
	update()
```

### 実行例

以下のようなものがアニメーションとして表示される。

![210828-0849-_DEBUG_-2021-08-28-09-28-18.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/602ef315-6bc7-d9d1-756d-668dede6d9de.gif)