OmniAICreator/Qiita-1.07M huggingface dataset:
Noodlでポップアップメッセージを表示するコンポーネントを作ってみた

今年もやってきましたねアドベントカレンダー！
[Noodl Advent Calendar 2020](https://qiita.com/advent-calendar/2020/noodl)
[Noodl](https://www.tds-g.co.jp/noodl-jp/)の活用情報はまだまだ少ないので、この機会にジャンジャン増やしていきましょう！

この記事ではNoodlを活用して個人開発している、[保活支援アプリ](https://qiita.com/kmaepu/items/f317bc3c9b99646d6ae1)で作ってみたポップアップメッセージの作り方について解説しています。
#実際に作ったもの
 記録ボタンを押すとポップアップメッセージが表示されます！

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">Noodlで保活支援アプリのプロトタイピングをしています。今日はポップアップメッセージを作ってみました！<a href="https://twitter.com/hashtag/Noodl?src=hash&amp;ref_src=twsrc%5Etfw">#Noodl</a> <a href="https://t.co/NLNt117zXM">pic.twitter.com/NLNt117zXM</a></p>&mdash; まえぷー@アドカレ奮闘中 (@kmaepu) <a href="https://twitter.com/kmaepu/status/1336959150194974722?ref_src=twsrc%5Etfw">December 10, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

#フローの解説

ポップアップ表示部分フローとUIは次のとおりです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/f062257a-e475-7c54-daf7-f716e766f923.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/58cc894b-74ab-837d-3724-b0a00a1e261d.png)

使用するノードは次の3つです。
- **Animationノード**
- **Timerノード**
- **Groupノード**

 +α 表示させたいポップアップメッセージに使用するノード

##Aniamtionノード
**Animationノード**で特定のパラメータを時間変化させることができます。
今回は**Opacity**（不透明度）を0～1に変化させています。**Duration**（変化時間）により0から1まで変化するまでの時間を設定しています。

Animationノードの設定は次の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/487cebbb-6c3b-24ca-cc82-9a4bec35f253.png)

##TImerノード
**Timerノード**でポップアップメッセージを表示させる時間を制御しています。
Timerノードの設定は次の通りです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/6fefc413-554b-6b0a-c838-685497c8f4b9.png)
次の図のようにTImerノードとAnimationノードを接続しています。Animationノードの実行終了時に**Has Reached End**トリガが発生するので、それをTimerノードのRestartに接続しています。

TImerノードのカウントが終了すると**Finishedトリガ**が発生します。それをAnimationノードの**Play From End To Start**に接続しています。こうする事で、タイマー貨運ｔの終了時にAniamationノードをEndの値からStartの値へと実行する事ができます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/8395b728-339b-e57b-3a58-615b69cbc94d.png)

##Groupノード
今回はGroupノードをコンポーネントにして「msg」という名前にしています。msgコンポーネントの中身は次のようにしています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/183282/56e96abb-1936-f8f2-4a00-e16649a97267.png)

**Component Inputsノード**でmsgコンポーネントの外部からプロパティを受取れるようにしています。今回必要なのは**opacity**と**text**です。
（その他は拡張できるように加えています）

**opecity**は表示されるポップアップメッセー時の不透過度を表しています。
**text**はポップアップメッセージに表示されるテキストです。

#さいごに
以上でざっくりとした解説でしたが、ポップアップメッセージの作り方でした！

Animationノードを使いこなせるようになると、よりインタラクティブなUIを簡単に作れるようになると思いますので、いろいろ試していきましょう！🎄
Django/Flaskでソース変更後のリロード

Djangoでサイトを作ってサーバーにあげられたのは良いもののgit pullをしてからのソース変更を反映する仕方がわからなかったのですが、調べたら出てきたので備忘録的に残します。

なお、デプロイの仕方については、@kantackyさんの記事を参考にさせていただきました。この場を借りてお礼申し上げます。とてもわかりやすかったです。

>[Djangoのデプロイで追い詰められているあなたへ。Ubuntu18.04+NginxでDjango2.2デプロイ完全版](https://qiita.com/kantacky/items/b7d21d509aab7ef29672)

#### 追記
Flaskでも同様にリロードできたので含めておきます。


# 前提条件

> Ubuntu 20.04 amd64
> Nginx 1.18.0
> Gunicorn 20.0.4
> Python 3.8.5
> Django 3.1.2
> (Flask 1.1.2)

※プロジェクトをgitで管理していることを前提とする

# 手順
## サーバーが起動している場合
### git pull

まずはソースをgitからpullします。

```
sudo git pull
```

privateで管理している場合はこの後にパスワードなど諸々を打ち込んでpullしてください。

### gunicornのkill

一旦gunicornをkillします。[こちら](https://stackoverflow.com/questions/25230704/why-cant-i-start-my-gunicorn-server-connection-in-use)のサイトを参考にしました。

```
sudo killall gunicorn
```

### リロードなど

この後はもろもろのリロードを行います。

```
sudo systemctl daemon-reload

sudo systemctl restart nginx
sudo systemctl restart YourProjectName
```

ここは脳死状態でやったため、もしかしたら必要ない項目も紛れているかもしれません。

## サーバーが停止していた場合

### git pull

ここは起動している場合と同じです。

```
sudo git pull
```

privateで管理している場合はこの後にパスワードなど諸々を打ち込んでpullしてください。


### リロードなど

ここが起動している場合と異なります。

```
sudo systemctl daemon-reload

sudo systemctl start nginx
sudo systemctl enable nginx

sudo systemctl start YourProjectName
sudo systemctl enable YourProjectName
```

つまり、全てstartし直すということです！

# おわりに

今後は自動でリロードする設定をできたらいいなと...
Ubuntuのterminalのタブ名変更

## 環境

Ubuntu 20.04

## ターミナルでタブ名を変更する方法

デフォルトで以下のようにタブ名が固定されてしまっているので、変えたい。

![Screenshot from 2020-12-14 16-57-51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/3f2334d7-fd0d-2587-989b-913d4c8beb1e.png)

とくにたくさんタブを開く場合は、タブ名から作業内容がわかるようにしたい。
以下のコマンドを打てば変わる。

```
echo -en "\033]0;change tab name\a"
```

![Screenshot from 2020-12-14 16-58-41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/396623/b7ac6813-a0dd-9088-88c9-f3a7bc5a3d1e.png)

以上
PHP クロージャ（無名関数）に変数を引き継ぐ

# 目的

- クロージャ内で変数を呼び出すことができずちょっと詰まったためメモとして記載する

# 詳細

- 下記のようにuseを用いてクロージャに変数を共有する。

    ```php
    $foo = 'str';
    function() use ($foo){
        echo $foo;
    }
    ```
- 下記だと「$fooなんてないぜ」というエラーが出るので注意する。あくまでクロージャは無名だったとしても関数なので名前がついている関数と同じように外で定義した変数などは共有してあげないとクロージャ内で使用することはできない。

    ```php
    $foo = 'str';
    function(){
        echo $foo;
    }
    ```
Rubyで中国剰余定理



[Advent of Code 2020の13日目](https://adventofcode.com/2020/day/13) で必要だったので、調べて出てきた情報を参考にRubyへ移植しました。
アルゴリズムの詳細は、[けんちょんさんの記事](https://qiita.com/drken/items/ae02240cd1f8edfc86fd)が詳しいです。

ざっくり何ができるかを書くと、
「3で割ると2余り、10で割ると8余り、31で割ると9余る数」を求めるような場合に使えます。

## コード
`crt` メソッドに余りの数(`b`)と割る数(`m`)の配列を渡します。
返り値を `(r, m)` とすると、解は `x ≡ r (mod m)` になります。

```rb
def ext_gcd(a, b, values)
  d = a

  if b.zero?
    values[:x] = 1
    values[:y] = 0
  else
    d = ext_gcd(b, a % b, values)

    x = values[:x]
    y = values[:y]
    values[:x] = y
    values[:y] = x - (a / b) * y
  end

  d
end

def crt(b, m)
  r = 0
  mM = 1
  b.zip(m) do |bi, mi|
    val = {}
    d = extgcd_h(mM, mi, val)
    p = val[:x]
    q = val[:y]
    return [0, -1] if (bi - r) % d != 0
    tmp = (bi - r) / d * p % (mi / d)
    r += mM * tmp
    mM *= mi / d
  end

  [r % mM, mM]
end
```

## 利用例
19で割って0余り、
37で割って24余り、
523で割って504余るような数を求めたいとき

```rb
b = [0, 24, 504]
m = [19, 37, 523]
ans = crt(b, m) # => [317965, 367669]
```

`n` を整数として `367669n + 317965` が答えになる。
また、条件を満たす最小の自然数は `317965`。

## 参考にしたサイト
* http://ochaochaocha3.blogspot.com/2013/10/extgcd-on-javascript-and-ruby.html
* https://qiita.com/drken/items/ae02240cd1f8edfc86fd
SAKURAエディタマクロ集




## 始まり
現場だと使われるエディタは大体「サクラエディタ」の確率が高い
（フリーで高性能ってところがそうなるのかな…）

それでよく自分が使うマクロがあるが、そのマクロファイルを持ち出せない
（いわゆるセキュリティ関連で）

そのためのメモ

## マクロ

### 日付線

```text:ライン引き.mac
//線を引くマクロ
GoFileEnd(0);                        // ファイルの最後に移動
S_InsText("------------------ 【");   // ライン引き
S_InsertDate(0);                    // 日付挿入
S_InsText("  ");                    // スペース
S_InsertTime(0);                    // 時刻挿入
S_InsText("】 ------------------");   // ライン引き
S_Char(13);                         // 改行
S_InsText("【");                    // タイトルフィード
S_InsertDate(0);                    // 日付挿入
S_InsText("】[]");                  // タイトルフィード
S_Char(13);                         // 改行
S_Char(13);                         // 改行
S_Char(13);                         // 改行
Up(0);                              // カーソル上移動
Up(0);                              // カーソル上移動

```

### カラムテキスト変換

```カラムテキスト変換.mac

//縦文字列をカンマ区切りで横に並べる
ReplaceAll('\\t', '', 60);		// タブ削除
ReplaceAll('^', ',A\.', 60);		// 行頭に「,A.」を入れる
ReplaceAll('\\r\\n', '', 60);	// 改行を削除
ReplaceAll('(^,|,$)', '', 60);	// 最初と最後の「,」を消す
Char(13);						// 文字入力
Char(13);						// 文字入力


```
### カラムテキスト変換　A5名称用

```カラム変換_A5名称用,.mac

//縦文字列をカンマ区切りで横に並べる
ReplaceAll('\\t', '', 60);		// タブ削除
ReplaceAll('^', ',', 60);		// 行頭に「,」を入れる
ReplaceAll('\\r\\n', '', 60);	// 改行を削除
ReplaceAll('(^,|,$)', '', 60);	// 最初と最後の「,」を消す
ReplaceAll('^', '\-\-\*Captions ', 60);		// 行頭に「--*Captions 」を入れる
SearchClearMark(0);				// 検索マークの切替え
Char(13);						// 文字入力
Char(13);						// 文字入力

```

### カラム変換_テーブル名称用

```カラム変換_テーブル名称用.mac

//縦文字列をカンマ区切りで横に並べる
ReplaceAll('\\t', '', 60);		// タブ削除
ReplaceAll('^', ',A\.', 60);	// 行頭に「,A.」を入れる
ReplaceAll('\\r\\n', '', 60);	// 改行を削除
ReplaceAll('(^,|,$)', '', 60);	// 最初と最後の「,」を消す
SearchClearMark(0);				// 検索マークの切替え
Char(13);						// 文字入力
Char(13);						// 文字入力

```
OWASP ZAPで送信されるリクエストにBearer Tokenを付与する方法

備忘録
参考サイト：https://www.pupha.net/archives/2654/
脆弱性診断をはじめて2日目。
.NETCoreで作成したAPIを脆弱性診断してみよう。


## スクリプトを作成

[表示] -> [スクリプト] -> スクリプトタブを選択  

- Type：Stand Alone
- Script engine: ECMAScript: Oracle Nashorn
- テンプレート：なし

👇貼り付け。

```javascript
 // HttpSenderListenerというインタフェースを持ったリスナーを HttpSender に登録する
 org.parosproxy.paros.network.HttpSender.addListener(
   new org.zaproxy.zap.network.HttpSenderListener {
     getListenerOrder: function() {
       return 1;
     },

     // リクエスト送信前に呼ばれる
     onHttpRequestSend: function(msg, initiator) {
       msg.getRequestHeader().setHeader(
         "Authorization", "Bearer [myToken]");
     },

     // レスポンス取得後に呼ばれる
     onHttpResponseReceive: function(msg, initiator) {
     }
 });
```

[myToken]を置き換える。  
置き換えたら実行しよう。

スクリプトでToken取得の処理書いてもいけそう。
今回はAuthorizationヘッダを追加しているが他のヘッダを追加するときにも同様の方法ができそう。
Unity でAndroid 向けにビルドするとき困ったこと


# 概要

Unity でAndroid 向けにビルドするときに自分が困ったポイント集です。
随時更新していきます。過去の自分に向けて書いてます。
間違っていたらご指摘くださると助かります。

# 難読化解除ファイル/ デバッグ シンボル/ シンボル ファイル

なんやかんやあって、PlayConsoleにアップロードできるところまで行ったとします。
そのとき、下記のようなメッセージが表示されます。

```text
警告
この App Bundle に含まれている Java / Kotlin コードは難読化されている可能性があります。クラッシュや ANR を簡単に分析、デバッグできるよう、難読化解除ファイルをアップロードすることをおすすめします。詳細

警告
この App Bundle にはネイティブ コードが含まれ、デバッグ シンボルがアップロードされていません。クラッシュや ANR を簡単に分析、デバッグできるよう、シンボル ファイルをアップロードすることをおすすめします。詳細
```

難読化解除ファイル→これが、「ReTraceマッピングファイル」らしいです。
デバッグシンボル＝シンボルファイルが、「ネイティブ・デバッグ・シンボル」らしいです。

これは、ユーザーが使用中に起きた問題をPlayConsole上でグラフ化するために必要な設定です。

「Unityでビルドした時に暗号化されるので、C#としてどこでエラーが起きてるのか分かりません。」的なことを言っています。

そこで、PlayConsole君のために、暗号解読のヒントをZIPファイルで渡してあげます。
そのための設定が下記の画像です。
特に、`Create Symbol.zip`という部分が重要です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/05815f5c-e4c0-706a-e2fe-e429aa9a4400.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/9862b1ec-b18d-8b15-7d10-ed36adf0992d.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/7622e65d-140e-749e-9672-8b53a53bc132.png)

```Unityのプロジェクトフォルダ\Assets\Plugins\Android\proguard-user.txt
-keep class android.support.v4.content.** {
    *;
}
-keep public class com.google.android.gms.ads.** {
   public *;
}
-keep public class com.google.ads.** {
   public *;
}
-keep class com.google.unity.** {
   public *;
}
-keep class android.support.v4.content.** {
    *;
}
```

# Your native debug symbols are too large

前述のZIPファイルをアップロードするときにファイルが大きいといわれます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/940b66dc-f9fc-896f-1839-b9d7edfc4211.png)
Your native debug symbols are too large (413.56 MB). Must be 300 MB or smaller.

そこで、ZIPを解凍して再圧縮します。
すると急にサイズが小さくなります。
圧縮アプリは7zipを使っています。
グローバルスタンダードな7zipはお勧めです。

# Only Android ABIs are supported

ネイティブ デバッグ シンボルのアップロードにて

```text
The native debug symbols contain an invalid directory fighterx-0.1-v1.symbols. Only Android ABIs are supported.
```

ARMv7を外し、
ARM64にチェックを入れる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/db6c236c-60fe-f6ac-7e9b-a4a73c6cc9cf.png)![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134703/9773b030-e852-214a-1376-6eb6df2cdb13.png)
64bit化が必須になるそうです。
https://android-developers.googleblog.com/2017/12/improving-app-security-and-performance.html

`プロジェクト名-バージョン番号-ビルド番号.symbols.zip`を解凍する。
`arm64-v8a`というフォルダが入っているので、これを圧縮し、`arm64-v8a.zip`にする。で、アップロード。

# 環境

Unity 2019 LTS

**Excelsior!**
【Rails・ActiveRecord::Migration】削除用のマイグレーションの作成 `rails g migration DropUsers`

削除用マイグレーションファイルを作成したら、

```bash
$ rails g migration DropUsers
```

オフィシャルなものが見当たらなかったが、ロールバックできるこんな形で編集すると良さそう。

```db/migrate/20201214000000_drop_users.rb
class DropUsers < ActiveRecord::Migration
  def change
    drop_table :users do |t|
      t.string :email, null: false

      t.timestamps  # Rails 5 で t.timestamps で作成するカラムはデフォルトで NOT NULL になったため不要とのこと
    end
  end
end
```

- https://qiita.com/YumaInaura/items/05949d99b42516716685
- https://stackoverflow.com/questions/4020131/rails-db-migration-how-to-drop-a-table/31657066#31657066
- https://qiita.com/cho_co/items/b50e18967e03da458f6f
VMware vCenter Converter Standalone Client がオフライン環境で起動しなくなる事象の対処法

オフライン環境にVMware vCenter Converter Standalone Clientをインストールすると、起動しなくなる事がある。  
症状としては次の通り

- プログラムが起動しない（暫くしたのちエラー表示）

  - 次のメッセージが表示される

  - Error 1053: The service did not respond to the start or control request in a timely fashion.

- サービスの起動に失敗する

  - VMware vCenter Converter Standalone Agent
  - VMware vCenter Converter Standalone Server
  - VMware vCenter Converter Standalone Worker

リリースノートには「インターネット環境が必要」とあり、オフラインの場合はレジストリを編集する必要がある

## レジストリの編集

1. `HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control`にキー`ServicesPipeTimeout`(DWORD32)を作成
2. 値を10進で300000ミリ秒以上（5分）に設定する
3. 再起動する

# 参考

https://docs.vmware.com/en/vCenter-Converter-Standalone/6.2/rn/conv_sa_62_rel_notes.html
pythonのevalは文を実行できる。

# 1.非常によくある矛盾

よく「`eval("式")`は式の評価を行うものであるため文の実行はできない。文の実行は`exec("文")`で行う。」という説明がある。
実はこの2文、内容が矛盾していることに気が付けるだろうか。

# 2. 矛盾 = eval("exec('文')")

矛盾の正体は、`exec('文')`自体が式であるにもかかわらず、文を実行できてしまうことにある。
そのため、**「式の評価をおこなう 故に 文の実行はできない」が崩れる**のである。


以下の例で試してみよう。

`exec('文')`自体が式なのだから、`eval("")`に入れることが出来るのだ。

```python:本当は怖い家庭のeval
ほげ = "evalは変数の値を変えられないはずだよ"
print(ほげ) # evalは変数の値を変えられないはずだよ
eval("exec('ほげ = \"変えられるんだよなぁ\"')")
print(ほげ) # 変えられるんだよなぁ
```

# 3. 結論
「`eval`だから安心」ってことはない。

そのまま放って置くと、大変なことになりますよ
Simulatorで特定のiOSバージョンで発生するバグを調査する

## Simulatorとは

Simulatorは、Xcodeに含まれる開発者ツールの一つで、iPhoneなどのiOSを搭載し、PC上で実機デバイスのシミュレーションができます。iPhone、iPad、Apple TV、Apple Watchなどの端末からiOS、tvOSまで様々なシュミレーションでテストをすることができます。



## 実際に使ってみる

### iOSのインストール
Xcode > Preferenceをクリックします。

![スクリーンショット 2020-10-30 15.58.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375495/6544a4e4-e6dd-e2a6-f425-ca1c4bcaf432.png)


Componentsタブに移動して使用したいiOSをクリックしてインストールします。
![スクリーンショット 2020-10-30 15.56.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375495/c1c0487b-b6ea-418a-4225-ba16d230736a.png)


Xcode > Open Developer Tool > Simulatorをクリックして起動。
![スクリーンショット 2020-10-30 15.54.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375495/165c5b2c-b851-f702-eede-6b3a720b8680.png)

iOSのバージョンから機種まで選ぶことができます。

![スクリーンショット 2020-10-30 15.53.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375495/4d405ed2-2bd7-5268-f986-9741e21bdae3.png)


<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375495/02fc4acd-e7c3-7744-40c8-547b56f79707.png">

### ファイルのアップロード
SettingでログインしてiCloudアカウントを同期します。


<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375495/13111792-9204-479f-153a-cb90b3436cc3.png">


Browseから任意のファイルを選びます。

<img width="400"  src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/375495/5a688cfe-14b4-4d76-6e69-ed4acbcffc65.png">

## Simulatorを使う時の注意
XcodeとSimulatorはインストールするのにすごく時間がかかります（数時間単位）。
なので、もし使うかもしれないと思ったらあらかじめインストールしておくことをおすすめします。
cshでxargsによる並列実行

# 疑似関数


コマンド`xargs`を使うと、並列実行ができる。
https://qiita.com/shungok/items/f852be01f08568991f18

この`xargs`に与えるコマンドが複雑な時、`bash`なら関数をつくってあげればよいと思う。
しかし、`csh`では関数が使えない。

シェルスクリプトを生成して、そのコマンドを`xargs`に食わせるとうまくいった。

```shell
echo 'echo $argv[1]' > func.tmp
csh ./func.tmp hoge
```
とすると、

```shell
echo $argv[1]
```

というシェルスクリプトが生成される。これを早速次の行で使うことで、疑似関数が作れる。

# xargsによる並列実行

たとえば、sleepコマンドを1~10秒を4並列実行する場合、

```shell
echo 'echo "sleep $argv[1]" ; sleep $argv[1]' > func.tmp
seq 1 10 | xargs -L1 -P4 csh ./func.tmp 
rm func.tmp
```
となる。
もちろん、`func/tmp`は使い終わったら消しておく。
Slackのfiles.upload APIにはreply_broadcastが設定出来ないので

今日もSlack Botについてのpostです。
表題の件ですが、[APIドキュメントを見てみると分かるように](https://api.slack.com/methods/files.upload)、reply_broadcastオプションがありません。
アプリ上では出来ることが確認できるのですが。
![Slack___000-waigaya___Leave_a_Nest_Co__ltd_.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/22294/dd52ee16-5c52-023b-48be-5e0e66508140.png)

現状、Slack API経由では出来ないんですね。悲しい。

##Workaround
毎度おなじみになりつつある @seratch さんに助けを求めてみた所、現状の実装としては
- ファイルアップする
- ファイルのURLを取得する
- ファイルアップしたpostを消す
- Chat.messageAPIを使ってpostし直す

という流れになるようです。

### 参考コードはこちらです
```fileupload_reply_broadcast.py
import os
from slack_sdk import WebClient

client = WebClient(token=os.environ.get("SLACK_BOT_TOKEN"))

# 親メッセージ
new_message = client.chat_postMessage(channel="#random", text="Hi")
channel_id, ts = new_message["channel"], new_message["message"]["ts"]

# ファイルを一旦アップロード
f = client.files_upload(content="this is a test", channels=channel_id, thread_ts=ts)
file_url = f["file"]["permalink"]

# ファイル共有のために投稿したメッセージを消し込み
file_upload_message_ts = f["file"]["shares"]["public"][channel_id][0]["ts"]
deletion = client.chat_delete(channel=channel_id, ts=file_upload_message_ts)

# ファイルを引用するメッセージを投稿
reply = client.chat_postMessage(
    channel=channel_id,
    thread_ts=ts,
    reply_broadcast=True,
    text=f"Here is your file: {file_url}",
)
```

https://gist.github.com/seratch/7624211eac4469638ffa7eed281dfd54
【PHP】文字列の中に特定の文字がいくつ含まれているのか

# 文字列の中に特定の文字がいくつ含まれているのか？
文字列を与えられ、その中にある特定の文字の数をカウントしたい。
そんな時は

```php
 echo mb_substr_count("文字列", "カウントしたい文字");
```
これで文字が出現する回数をカウントできる。

例えば、

```php
 echo mb_substr_count("aaaabbbb", "a");
```
とすると、4が出力される。

### 参考
https://www.php.net/manual/ja/function.mb-substr-count.php
Sassについて

# Sassとは
Sass は Less, Stylus, Tass, PCSS などと同様の CSS を拡張したメタ言語のひとつです。

+ Sass は Syntactically Awesome Stylesheets (構文的にイケてるスタイルシート) の略です。「サス」と読みます。
+ CSS に対して変数、ネスティング、Mixins、インラインインポートなどの機能を強化します。
+ 色や値を操作するための多くの関数が用意されています。
+ if文や for文などの制御構文をサポートします。
+ Sass構文や SCSS構文で記述したファイルをコンパイラで CSS構文に変換して使用します。
+ ファイルサイズ圧縮のため、minify(compress)されたファイルを出力することが可能です。

## はじめに
冒頭にも記載しましたが、CSSメタ言語の中では比較的に構文がCSSに近く、とっつきやすい印象があります。
その中でも私が使ってききて、これは使えるな！っと思った機能をピックアップしてご紹介いたします。

## インターポレーション(#{...})
これインターポートレーションていうんだ。。。
って調べて思いました笑
俗にいう「変数埋め込み」です。
Sassは`$・・・`の形式で変数を作ることが可能です。
そして定義した変数を埋め込むことで無駄な繰り返しを省くという特性があります。

## ネスティング
これは基本中の基本ですね。
ノードの構成の合わせてスコープを小さくできるし、影響範囲の調査も不要になります。
開発効率も上がるし、保守性も高く、可読性も高い！
やらないてはないかと思います！

## 親セレクタ(&)
&で親のセレクタが取得できる。
擬似クラスなどを書く際に用いるととても可読性が上がるし、
スコープの限定もできるのででグレードが発生しにくい。


---
### ここまでのコード
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="trust-k-yamazaki" data-slug-hash="yLagQjP" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="sass convey">
  <span>See the Pen <a href="https://codepen.io/trust-k-yamazaki/pen/yLagQjP">
  sass convey</a> by Katsunari Yamazaki (<a href="https://codepen.io/trust-k-yamazaki">@trust-k-yamazaki</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>

##  ミックスイン(Mixin, @include)
基本スタイルを決めて何度も再利用できるものにするMixin

## 拡張(@extend)
既に定義済みのスタイルを拡張するExtend

---
### ここまでのコード
<p class="codepen" data-height="265" data-theme-id="light" data-default-tab="css,result" data-user="trust-k-yamazaki" data-slug-hash="rNMjoGb" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Sass extend mixins">
  <span>See the Pen <a href="https://codepen.io/trust-k-yamazaki/pen/rNMjoGb">
  Sass extend mixins</a> by Katsunari Yamazaki (<a href="https://codepen.io/trust-k-yamazaki">@trust-k-yamazaki</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>



## おわりに
ああ、時間がない、
ここらへんまでで！
次回またこれやります！
gitのツリー構造をターミナルで視覚的に表示する

この記事は株式会社シンプルウェイ 2020 アドベントカレンダーの参加記事です。
https://qiita.com/advent-calendar/2020/simpleway


gitのコミット履歴を確認するのにSourceTree等のフリーソフトを使うことがあるが、
現在チェックアウトしているブランチからの、コミット履歴を確認するのであれば、

```
git log
```

で確認できる。

ただし、そのままだと一つ一つのコミットのハッシュやコミット登録者や日付やコメントなど
すべて詳細に表示されて可読性が悪い。
あくまで確認したいのはコミットメッセージとその履歴の流れなのである。

git logにはオプションで色々見やすくできる。

```
graph = log --graph --oneline --decorate --date=short --all --pretty=format:\"<%h> %ad [%an] %Cgreen%d%Creset %s\"
```

上記のようにコマンドを叩けば、1コミット1行でコミット履歴やマージ履歴がわかりやすく表示される。

毎回上記のコマンドを打つのは骨が折れるので、
`$HOME/.gitconfig` のaliasのところにコマンドを設定すると良い。

```
graph = log --graph --oneline --decorate --date=short --all --pretty=format:\"<%h> %ad [%an] %Cgreen%d%Creset %s\"
```

上記のように設定しておくと、

```
git graph
```

と打つだけで視覚的にわかりやすくコミット履歴を確認できるようになる。
`--pretty=format:\"〜〜〜"` の部分を修正すれば、
自分が見たいと思う情報を取捨選択できる。


※参考記事
https://wp.pxdesign.jp/2014/08/23/git-hierarchy-structure/
https://blog.toshimaru.net/git-log-graph/
VSCodeでファイルを比較する

VSCodeで差分比較をする方法です。

# ローカルのファイルを比較
1. エクスプローラー ビューで比較したいファイルを2つ選択する。

2. 右クリックで[選択項目の比較]を選択する。


# ブランチ同士を比較

※Git Lensプラグインをインストールしておく。

1. サイドバーからGit Lensのアイコンを開く。

2. [SEARCH & COMPARE] の[+]を選択して、[Compare References...]を選択する。

3. 比較したいブランチを2つ選択すると、比較結果が[SEARCH & COMPARE]の下にツリー表示される。

<img width="400" alt="git lens image" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/461268/a5fd3b11-9fe7-c4fe-4da3-e31f50400d85.png">
Activiti6のサンプルをローカルで動かす

activitiのサンプルをローカルで動かし使ってみて、BPM及びactivitiの動作を一通り把握したい。
activiti7はクラウドを前提としているため、ハードルが高い。なので、まずactiviti6から。
# activiti6をとりあえず動かす
## activiti6ダウンロード
下記リンクからダウンロードする：
https://github.com/Activiti/Activiti/releases/download/activiti-6.0.0/activiti-6.0.0.zip
zipファイルを解凍したら、以下の3フォルダに分けられている：

* database：
 各種データベース環境作成・メンテ用sql一式
* libs：
activiti engine等、activitiのcoreライブラリ一式
* wars：
サンプルwarファイル三つ

## tomcat実行環境準備
tomcatの実行環境は、既に持っているため、ここで割愛。

## activiti実行
上記warファイルをtomcatのwebapps配下コピーし、tomcat配下binにあるstartupを実行する。

下記URLにアクセスし、ログイン画面が出ればOK。
http://localhost:8080/activiti-app

admin/testでログインできる。

これで、activitiはメモリ上のH2データベースを利用して動作するので、tomcatを停止すると、作成したすべての情報が消える。
なので、ローカルのPostgresと接続して、データが消えないようにしたい。

# activitiをpostgresと接続する
接続方法は2つ。どちらも`webapps/activiti-app/WEB-INF/classes/META-INF/activiti-app/activiti-app.properties`の編集が必要。
## jdbcドライバを直接利用して接続
上記activiti-app.propertiesファイル内の以下の設定を行う：

```properties:activiti-app.properties
datasource.driver=org.postgresql.Driver
datasource.url=jdbc:postgresql://localhost:5432/準備したDB名
datasource.username=準備したユーザ名
datasource.password=準備したユーザのパスワード
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
```
> urlは自分の環境に適宜合わせること

## JNDI Datasource経由して接続
activiti-app.propertiesファイル内jdbc関連をコメントアウトし、以下の設定を追加する：

```properties:activiti-app.properties
datasource.jndi.name=jdbc/activitiDB
datasource.jndi.resourceRef=true
```

`{tomcat_home}/conf/Catalina/localhost`に`activiti-app.xml`ファイルを以下の内容で作成する：

```xml:activiti-app.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context antiJARLocking="true" path="/activiti-app">
    <Resource auth="Container"
    name="jdbc/activitiDB"
    type="javax.sql.DataSource"
    description="JDBC DataSource"
    url="jdbc:postgresql://localhost:5432/準備したDB名"
    driverClassName="org.postgresql.Driver"
    username="準備したユーザ名"
    password="準備したユーザのパスワード"
    defaultAutoCommit="false"
    initialSize="5"
    maxWait="5000"
    maxActive="120"
    maxIdle="5"/>
</Context>
```
JNDI Datasourceを経由するいいところは、データベース接続先が変わっても、warファイルの作成し直すが必要ないってことかな。

## データ構造を準備する
postgresの管理ツールまたはpsqlでactiviti用ユーザとそのデータベースを作成した後、activitiが使うテーブル一式の作成は必要。
> 本来ならば、activitiのProcessEngineConfiguration初期化時の`setDatabaseSchemaUpdate`を`true`に設定すれば、自動的にテーブルを作成してくれるはずが、なぜかうまく行かない。

テーブル作成は、activiti解凍フォルダdatabase/create内の以下sqlを利用する：

* activiti.postgres.create.engine.sql
* activiti.postgres.create.history.sql
* activiti.postgres.create.identity.sql

## tomcat再起動
tomcatから特にエラーが出ていなければ、activitiがpostgresのDBを利用することとなる。
activitiにログインして適当ユーザを作成し、データベースの`act_id_user`にそのユーザ情報が追加されればOK。
[無料] AWS EC2 + RDS + Flask でWebアプリを作り HTTPS 化する [その8: ネームサーバー登録]

[その7](https://qiita.com/nozomiyamada/items/6a898860d5c455868859) の続きです。取得したドメインとEC2のIPアドレスを紐付けます。

## ホストゾーン作成

前回の最後でリダイレクト設定をしましたが、あれでは結局美しくなく、根本的な解決になっていませんでした。そこで今回は AWSのDNS（ドメインネームシステム）である **Route 53** を利用してネームサーバーの登録をします。

これは前回の繰り返しですが、**ここから先は課金が必要です**。月0.5$なのでガチャ1回分よりは安いですが、完全無料でやりたいならここで引き返して下さい。剥き出しのIPアドレスでもWebアプリとしては機能します。ただ見た目が情けないだけで。

また、不特定多数に公開するようなWebアプリではなく、身内でデータベースを管理するためのインターフェースを作ったり、Line や FB などの API の Webhook として使うということも考えられます。その場合は無理してドメインを登録する必要もありません。ただ後者の場合はHTTPS化は必要になります。

AWS のサービスから **Route 53** に入り、**Create hosted zone** をクリックします。
![Screen Shot 2563-12-14 at 13.05.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/576eaf6c-2948-8d01-04ae-d3ce9656e538.png)
**Domain name** に その7 で取得したドメインを入力します。他の部分は変えなくても良いです、*Create hosted zone** します。
![Screen Shot 2563-12-14 at 13.07.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/924ca06d-8ae3-0376-7b23-64154dde9060.png)
すると、自動的にレコードが2つ作られると思います。今回は、このうち `ns-` で始まる4つのネームサーバーを freenom に登録します。
![Screen Shot 2563-12-14 at 13.09.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/835d9118-045f-214f-25cd-beaa7eac26a3.png)

## ネームサーバー登録

別タブを開いて freenom にログインします。

Services > My Domains > Manage Domain > Management Tools から、**Nameservers** を選択します。
![Screen Shot 2563-12-14 at 13.17.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/38e39571-2501-86c4-fb49-189bbf8d619b.png)
ここに先ほどAWSで作ったホストゾーンのネームサーバーを4つともコピペします。
![Screen Shot 2563-12-14 at 13.19.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/317bb67e-617e-1aa7-aa4e-a0b348f6a67a.png)

これはあくまで「`hogehoge.ga` にアクセスするときは、住所=IPアドレスをこのネームサーバーに照会して下さいね」という設定をしただけであり、これだけではWebアプリにアクセスできません。ここで **Route 53** に戻って、EC2インスタンスとの紐付けをします。

**Create Record** を押すとこんな画面になります。この **Record name** でホスト名（ドメインの前にくる名前）を決めます。ここでは無難に `www.hogehoge.ga` としておきました。

その下の **Value** に、EC2インスタンスのIPアドレスを入力し、**Create records** します。
![Screen Shot 2563-12-14 at 13.28.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/5a29ab96-8e87-746a-cea8-ee5ed40c4d73.png)
するとダッシュボードにこのように表示されます。
![Screen Shot 2563-12-14 at 13.31.09.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/26af2c01-0778-c2dc-5355-36e21bc13cfe.png)
この状態で `www.hogehoge.ga` にアクセスしてみると...
![Screen Shot 2563-12-14 at 13.34.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/727634/edaf727c-ff15-27dc-06ed-00951f1eeacd.png)
はいできました。これで独自ドメインを利用したWebアプリが完成です。

ちなみにこの記事をアップした直後にこのホストゾーンは削除しましたので、現在は `www.hogehoge.ga` にアクセスしても残念ながら何も見られません。

このサイトはまだHTTPですので、画像のように **Not Secure** という警告が出ています。数年前からウェブサイトのHTTPS化が急に進んでおり、先述した Facebook Graph API の webhook なども HTTPS しか受け付けてくれません。[その9](https://qiita.com/nozomiyamada/items/d0e756a3492fe6c7f601) 以降では、これを HTTPS化していきます。
M1 で llvm ビルド時間のメモ

# 背景

M1 CPU(Apple Silicon)での C++ コンパイル性能を知りたい.

llvm(llvm-project) をビルドしてみます.
(llvm のみ. libclang などのビルドは行わない)

# 手順

2020/12/14 時点の llvm-project `master`

```
$ mkdir build && cd build
$ CXX=clang++ CC=clang cmake -G Ninja ../llvm
```

# 結果

総ファイル数は 2985 個くらいです.

x86 は Ryzen9 3950X と比較しました. 完全に同じ構成ではありませんが参考になるでしょう.

* clang10 + 96 GB mem + NVMe + Ryzen9 3950X(16 cores)
  * 6 分 52 秒
* 16 GB mem + 256 GB storage + 2020 Macbook Air(CPU 8 cores)
  * 18 分 54 秒
* 16 GB mem + 256 GB storage + 2020 M1 mac mini
  * 11 分!
  * `ninja  4831.54s user 178.10s system 758% cpu 11:00.60 total`
* clang10 + 16 GB mem + NVMe + Jetson AGX Xavier(aarch64 linux. 8 cores)
  * bfd だとリンク失敗するので, リンカには L`LD を利用. `-DLLVM_ENABLE_LLD=On`
  * `ninja -j 8` でビルド
  * 42 分 32 秒(うち sys	13m56.448s)


LLVM のビルドは完全並列にできるわけではありませんが, m1 macbook air(2020) は 3950X の 1/2.7 の性能となかなかかと思います.

M1 mac mini(2020) はフル性能が出せるからでしょうか, 11 分とかなり改善があります.
8 cores Ryzen あたりとの比較だと M1 mac mini のほうがコンパイル早いかもですね.

M1 は Jetson AGX の 2.2 倍くらいと良いですね.
bundlerのバージョンを切り替える

#はじめに
脱初心者にむけてアウトプットをしていこうと思って、
記事を書いております。
私は、まだ現場に出たことのない完全にど素人です。
間違ったことがありましたら、ぜひコメントいただけると幸いです。

##対象読者
私は開発環境にdocker-composeを導入しようとしたときに、bundlerのバージョンが間違っていると怒られたことがありました。
そして、bandlerのバージョンを変更することになったが意外と情報が少なかったです。
なので、bundlerのバージョンを切り替える必要がある方に、参考になればと思い記事を投稿しております。


##開発環境
Ruby: 2.6.5
Ruby on Rails: 6.0.0

##bundlerを更新する手順
4工程ありますが簡単なので、一瞬でできます。

###インストールしたいバージョンが使えるかどうか確認する。
```rb
$ gem search ^bundler$ --all
```
インストールできるバージョンが全てでてくるので、必要なバージョン見つける。

###必要なバージョンをインストールする
```rb
$ gem install bundler -v '1.3.4'
```
クォーテーションで囲ったバージョンがインストールされる。

###Gemfile.lockを削除する
```rb
$ rm Gemfile.lock
```
削除してもbundle install時に生成されるのでご安心を

###インストールしたバージョンでbundle install
```rb
$ bundle _1.3.4_ install
```
これでGemfile.lockの記述も変わっているはずです、

⚠️バージョンは全て適応なバージョンを入れてお使いください。
Bitriseのキャッシュに関する基礎知識

Bitriseのキャッシュと戯れる機会があったので、その過程でわかったことをまとめておきます。わかったことと言っても全部公式ドキュメントを探せば書いてある内容なのですが、一箇所にまとまっていると便利なので。

## 基本的な使い方

Bitriseでは、ユーザが指定したディレクトリをtarにしてS3にアップロードすることでキャッシュの仕組みが実現されています。これを利用するために、デフォルトで組み込まれている以下のステップを使います。

- [Cache:Pull](https://www.bitrise.io/integrations/steps/cache-pull): キャッシュを取得
- [Cache:Push](https://www.bitrise.io/integrations/steps/cache-push): キャッシュを保存

workflowの中でははじめの方にCache:Pull、終わりの方にCache:Pushを設定しておくことで、workflowの前回実行時にpushされたキャッシュをpullして使うことができます。具体的には、npmパッケージのキャッシュをしたい場合は `npm install`の前にCache:Pullを、後にCache:Pushを入れておけばOKですね。

キャッシュするパスの指定方法として、自分で書くパターンと組み込みのステップがよしなにやってくれるパターンの２つがあります。

自分で書くパターンでは、Cache:Pushステップの設定画面のCache pathsのフォームに、例えば

```
./node_modules
```

のようにキャッシュしたいパスを書きます。ここに書かれたパスはCache:Pushで保存され、次回workflow実行時のCache:Pullで同じ場所に展開されます。

組み込みのステップがやってくれるパターンには、例えば [Cocoapods Install](https://devcenter.bitrise.io/builds/caching/caching-cocoapods/) があり、この場合は単純にCache:PullとCache:Pushの間にCocoapods Installのステップを入れれば、明示的にキャッシュの設定を書くことなく自動でキャッシュの更新・取得をしてくれます。

workflowを書く際には、自分が使いたいステップがキャッシュに対応しているか確認し、対応していればステップにお任せし、対応していなければCache:Pushに自分で設定を書くのが良いでしょう。

## 知っておいた方が良いこと

Bitriseのキャッシュはちょっと癖がある印象で、色々と試す前に最初から知っておけたらよかったと思った点がいくつかありました。

#### キャッシュがない場合はデフォルトブランチのキャッシュが使われる

Bitriseのキャッシュはブランチに紐づいています。そのため、ブランチAで取得するキャッシュは基本的にはそれ以前にブランチAで保存されたものになります。
例外として、過去に保存されたキャッシュが存在しないブランチでは、デフォルトブランチのキャッシュが使われます。例えば、ローカルで作成したブランチをpushしてPRを作成する場合、そのブランチのキャッシュは確実に存在しないためデフォルトブランチのキャッシュが参照されることになります。そのため、PRのCIを速くするためには、デフォルトブランチの方でPRで使われそうなキャッシュを作っておく必要があるということになります。ちなみに、個人的にはPRビルドではデフォルトブランチよりもベースブランチのキャッシュを優先して利用した方が良さそうと思い、検索してみると [そういう声](https://github.com/bitrise-steplib/steps-cache-pull/issues/8) も上がっているのですが現状では対応されていないようです。
BitriseのデフォルトブランチはSettingsから変更できるので、キャッシュのことを考慮してデフォルトブランチを決めるのもありかもしれません。

#### PRビルドではキャッシュはpushされない

デフォルトの設定ではPRビルドではキャッシュはpushされません。そのため、PRを出してCIが完了してからちょっと変更を加えようと思ってpushしたときでも、１回目のCIで保存されたキャッシュが使えて速くCIが終わるみたいなことはありません。この挙動については、bitrise.ymlの `run_if` を上書きすることでPRでもpushするように変更することはできますが、推奨されてはいないようです。

参考: https://discuss.bitrise.io/t/cache-push-is-not-working-since-run-if-expression-is-false-which-should-not-be-false/3731

#### 保存されているキャッシュはwebから手動で削除/ダウンロードできる

Settings -> Manage Build Cachesからブランチごとにキャッシュの削除やダウンロードができて、トラブル時やデバッグ時に便利です。

## リンク集

公式ドキュメントが一番わかりやすいです。

- https://devcenter.bitrise.io/jp/builds/caching/about-caching-index/
- https://www.bitrise.io/integrations/steps/cache-push
- https://www.bitrise.io/integrations/steps/cache-pull
IGMCを試してみた

#IGMCを試してみた

GNNを作ったレコメンドシステムを探していたら、
面白そうな[論文](https://arxiv.org/abs/1904.12058)と[著者のgithub](https://github.com/muhanzhang/IGMC)(MITライセンス)を見つけたので試しに動かしてみました。

なので備忘録がわりにこの記事を書いています。
間違っている箇所も有るかも知れませんが、その時はご指摘いただけると幸いです。


#IGMCとは
側面情報を用いない行列補完をGNNを用いて行うモデル。
行列の補完を何に使うかと言うと、
例えばユーザーを行とアイテムを列としたときにそのアイテムへの評価を要素にすると評価の高いものを予測するレコメンドに使える。
このシステムの売りは

- 側面情報を用いないので情報を登録していないユーザーなどにも使える
- グラフ全体ではなく目標となるユーザーやアイテムの近傍のサブグラフを学習に用いるので、新しいユーザーやアイテムにも学習せずに対応できる
- 上の性質からスパースなデータにも対応できる
- 転移学習が容易

ちなみに側面情報を用いて学習を行うことも出来ます。

#何をしてるのか詳しく見てみる

入力されるデータはユーザーuがアイテムiに対して行った評価rのセット。u*iの行列で表されるものをu,vをノードとして評価が有るものだけを関係rのエッジとしてもつ2部グラフに置き換えます。
ユーザーとユーザー、アイテムとアイテムをつなぐノードは考えません。
評価rは離散値で例えば大変良かったを5大変悪かったを1とする5段階評価です。

学習ではその2部グラフ全てを使うのではなく関係を推定したいユーザーとアイテム周辺のサブグラフを用いて学習します。入力データには推定したいユーザーとアイテムをつなぐエッジは存在しません。(学習時にはこのエッジはもともと存在するので削除する)


サブグラフの取得方法は目標となるユーザー、アイテムからのh-hop近傍をとってきていています。
通常入力や出力はユーザーIDやアイテムIDをそのまま使いますが、この論文では違っていて、
これを取得する際にどのhopでサブグラフに始めて含まれたかによってノードにラベルづけを行っています。
つまり目標となるユーザー、アイテムには0,1のラベルが与えられ、そのノードから遠ければ遠いほど大きい数字のラベルがついていきま。す（ユーザーは奇数、アイテムは偶数に制限してユーザーのノードとアイテムのノードが混合しないようにしている）
図にするとこんな感じ
![graph.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/936496/5dfc4e27-9592-1b4d-3f3a-8d80f5c1d982.png)
橙が新ラベル、赤エッジが予測したいエッジ黒エッジが予測したいエッジの近傍のエッジ青文字が評価（関係）

特定のユーザーIDやアイテムIDを使っていないので新しいユーザーやアイテムに対しても対応できるということでしょう。

GNNの形はメッセージ通過層としてR-GCNを関係を評価rとして使用し、
2つの層の間にtanh活性化を持つL個のメッセージ通過層を積み重ね
その結果をconcatして
そのなかから目標のユーザーとアイテムを指すものだけを取り出しconcatしたものをプール層としてそれにMLPを掛けてその出力と正解ラベルのMSEで学習しているみたいです。
（正解ラベルは目標ユーザーが目標アイテムに行った評価の値）

……文章で書いてもわかりにくいのでgithubのコード見たほうがわかりやすいと思います。

また、評価一つ一つをR-GCNの関係として入れているため評価が連続値であり評価1よりも4のほうが5に近いことを教えてあげる必要が有るようで隣接する評価のR-GCNの重みが異なるほどlossに重みを加えているようです。

#実際に動かしてみる

実際に動かしてみます、作業OSはUbuntu16.04です。

githubからコードをcloneしてきて、
githubにかかれている通りpytorchとPyTorch_Geometricをインストールすれば動くはずです。

以下おまかんだと思うのですが躓いたところを書いていきます。

- PyTorch 1.4.0、なんたら.soがないと怒られてる
代わりに1.7.0を入れて解決しました。

- LIBCXX_3.4.22がないと怒られる
```
sudo add-apt-repository ppa:ubuntu-toolchain-r/test
sudo apt update
sudo apt install gcc-4.9
sudo apt upgrade libstdc++6
```
参考
[https://github.com/lhelontra/tensorflow-on-arm/issues/13](https://github.com/lhelontra/tensorflow-on-arm/issues/13)

- joblib内でTypeError: an integer is required (got type bytes)
joblibのバージョンを0.14以上にする

- RGCNConv' object has no attribute 'att
train_eval.pyの170-171行目を
```
gconv.comp,
gconv.weight.view(gconv.num_bases, -1)
```
にする
参考
[https://github.com/muhanzhang/IGMC/issues/7](https://github.com/muhanzhang/IGMC/issues/7)

自分で作ったデータを使いたい場合
data_utils.pyのml-10mのコードを使いまわすのが一番簡単
データをダウンロードする代わりに
ユーザーID,アイテムID,評価,タイムスタンプの形式で適当な区切り符号でつなげたものを自分で作成したデータとして読み込ませる。

実行結果はこんな感じ

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/936496/4944a2a2-d488-c9cb-8639-83ab27235e9a.png)

今回はIGMCを動かして見ました。
参考になれば幸いです。
! [remote rejected] master -> master (refusing to allow an OAuth App to create or update workflow .github/workflows/* without workflow scope)の対処方法

## はじめに

下記のエラーに遭遇しましたので、解決方法を記録、共有します。

```console
! [remote rejected] master -> master (refusing to allow an OAuth App to create or update workflow .github/workflows/main.yml without workflow scope)
```

### 環境

+ macOS 10.15.6
+ SourceTree 4.0.2
+ GitHub

### 再現手順

1. [Clone with HTTPS](https://docs.github.com/ja/free-pro-team@latest/github/creating-cloning-and-archiving-repositories/cloning-a-repository)でURLを取得、ローカルにクローンを作成する
2. ローカルのドキュメントを操作する
3. リモートにプッシュすると、上記のエラーが発生する

## 原因

```
refusing to allow an OAuth App to create or update workflow .github/workflows/main.yml without workflow scope
-> ワークフロースコープなしでは、OAuthアプリのワークフロー作成または更新を拒否します。
```

クローン元のリポジトリに、GitHub Workflowの設定ファイル`.github/workflows/main.yml`が含まれています。OAuthクライアントとHTTPSクローンでは、このファイルを操作する権限がないためエラーが発生します。

## 対処法

十分なパーミッションをもった認証方法でアクセスします。あなたがGitHubにSSHで接続できない場合は対処法1を、SSHで接続できる場合は対処法2で対処します。

### 対処法1. Personal Access Token

パーソナルアクセストークンとは、パスワードに変わってGitHub APIにアクセスするための個人認証方法です。パスワードと違い、同一アカウントで複数のトークンを生成し、それぞれのトークンに異なる操作権限を設定できます。万が一トークンが流出した場合は、トークンを個別に失効させることも可能です。

#### アクセストークンの発行

GitHubの[Personal access tokens](https://github.com/settings/tokens)設定ページを開き「Generate new token」ボタンでアクセストークンを生成します。

参考記事 : [GitHub : 個人アクセストークンを使用する](https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/creating-a-personal-access-token)

#### SourceTreeにアクセストークンを登録する

SourceTreeでアクセストークンを利用するには、GitHubアカウントのパスワードの代わりにアクセストークンを入力します。

参考記事

+ [Two-Factor Authentication (2FA) with GitHub in SourceTree](https://ja.confluence.atlassian.com/sourcetreekb/two-factor-authentication-2fa-with-github-in-sourcetree-402033499.html)
+ [GitHubの二段階認証が有効な環境でSourceTreeを使う](https://qiita.com/MATTENN/items/7009eed1de1e46f99544)

Windowsの場合、[資格情報マネージャー](https://support.microsoft.com/ja-jp/windows/%E8%B3%87%E6%A0%BC%E6%83%85%E5%A0%B1%E3%83%9E%E3%83%8D%E3%83%BC%E3%82%B8%E3%83%A3%E3%83%BC%E3%81%AB%E3%82%A2%E3%82%AF%E3%82%BB%E3%82%B9%E3%81%99%E3%82%8B-1b5c916a-6a16-889f-8581-fc16e8165ac0)にパーソナルアクセストークンを設定しても、この問題を回避できます。

参考記事 : [Git Extensions is a great tool but the credential management is very weak](https://github.com/gitextensions/gitextensions/issues/4916#issuecomment-557509451)

### 対処法2. SSH

GitHubにSSHで接続できる場合は、リポジトリのリモートURLを変更する事でこの問題を回避できます。
GitHubへSSH接続する手順は、公式ドキュメントの[GitHubにSSHで接続する](https://docs.github.com/ja/free-pro-team@latest/github/authenticating-to-github/connecting-to-github-with-ssh)をご参照ください。

リポジトリのページから、以下の手順でSSH接続用のURLをコピーします。ローカルリポジトリのリモートURLをこのURLに変更すればPushに成功します。
![](https://www.evernote.com/l/AAlZ-MQOiE9Mt7QVeaOe0QJE3IXQPklYQ1AB/image.png)

以上、ありがとうございました。
LookerのSSO Embedの権限について細かく調べてみた

LookerのSSO Embedの権限について、実際に動かしながら確認したので、自分の備忘録的に書いていきます。

# はじめに

- Lookerバージョン: 7.20.14
- [SSO Embedドキュメント](https://docs.looker.com/ja/reference/embedding/sso-embed)

# 各権限

## explore
```
Exploreページを閲覧することをユーザーに許可します。
```

- explore権限を設定することで、dashboardやlookを参照時に「ここから探索」メニューが見えてexploreに遷移できるようになる

## save_content
```
ダッシュボードやLookを変更して保存することをユーザーに許可します。
```

- 保存する先は個人ディレクトリか、グループディレクトリ、あるいは共有ディレクトリを選択することができる
    - 個人（Personal）はパラメータとして設定した`external_user_id`単位になる
    - グループはexternal_group_idで設定したグループに保存される
        - external_group_idを設定しない場合は保存先として、グループディレクトリは選択できない
    - 共有ディレクトリへの保存は共有ディレクトリの権限が設定されている場合のみ保存先として選択可
        - all usersに権限を付与しているとembedユーザーでも利用できる

## schedule_look_emails/schedule_external_look_emails
```
ユーザーが自分のメールアドレス（「email」というユーザー属性で設定）、またはメールのドメイン許可リストで設定された制限範囲内にあるメールアドレスに、ダッシュボードやLookの配信をスケジュールすることを許可します。
create_alerts権限を持つユーザーが、メールのドメイン許可リストで設定された制限範囲内のメールアドレスに、アラート通知を送信することを許可します。
```

```
任意のメールアドレスへのダッシュボードやLookの配信をスケジュールすることをユーザーに許可します。create_alerts権限を持つユーザーが任意のメールドメインにアラート通知を送信できるようにします。
```

- （おそらく）embedユーザーはemailアドレスがないので`schedule_look_emails`だけではメール送信設定ができない。 `schedule_external_look_emails` も設定してあげる必要がある

## download_with_limit/download_without_limit

- SSO Embedのドキュメントには記載されていないが、 `download_with_limit`は5,000件までに結果が制限される
    - Lookerのダウンロード画面上で5,000件以上設定してもダウンロードできないので注意

## see_drill_overlay

```
完全なExploreページに移動することなくドリルダウンすることをユーザーに許可します。
```

- measureにdrill_fields設定している場合、ドリルダウンした結果を見ることができる
    - ただし、explore権限もつけているとsee_drill_overlay権限がなくてもドリルダウン可

## embed_browse_spaces

```
コンテンツブラウザを有効にして、ユーザーが組み込みからフォルダを参照できるようにします。
embed_browse_spacesが付与された組み込みユーザーは、個人用の組み込みフォルダおよび組織用の共有フォルダ（存在する場合）にアクセスできます。
```

- 画面右上から、保存したlookやdashboardを呼び出すことができる
    - ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/48307/9577a9e1-a16c-78b9-7991-f80e1e249d6b.png)
WordPressでパーマリンク設定を変更後に403エラーが出たときの対処法

ワードプレスのテーマtwentytwentyを基盤に、管理画面からパーマリンク設定を変更後に403エラーが出たので、その時の対処法を備忘録的に残す。

# 環境情報

PHP：version 7.3.12
WordPress：version 5.5.3
WPテーマ：twentytwenty

# 作業

ディレクトリ直下にある.htaccessファイルに以下の一文を追記しなさいという記事をいくつか見かけたので試しました。

```.htaccess
Options +FollowSymLinks
```

しかし、これを追加すると私の場合500エラーになってしまいました。
一部のサーバでは上記は使えないそうなので、次の一文に変えると解決しました。

```.htaccess
Options +SymLinksIfOwnerMatch
```
Python: ジェネレータでちょうどいいflat / flat_mapを作ってみた

何かちょうどいいのが見当らなかったので自前で作ってみました。どっかにあるのかな?
「ちょうどいいの」 とは：

+ ```[[0], [1], [2]] -> [0, 1, 2]``` ：flatの基本機能。あたりまえか
+ ```[0, [1], [[2]]] -> [0, 1, [2]]``` ：リストでない要素はそのまま。一段だけ。再帰なし。
+ ```[(0, 1), {'a':2, 'b':3}, "45", [6, 7]] -> [(0, 1), {'a': 2, 'b': 3}, '45', 6, 7]``` ：listにだけ作用する。ほかの iterable には反応しない。

ぼくの方では、flat 単体で使うシーンはほぼないので、flatmapを成立させてくれればそれでよいのです。それがぼくにとっての「ちょうどよい」ってことになります。まあ人によりけりですが、あなたはどうですか?

```py

flat = lambda xs : (
    y
    for x in xs
    for y in (
        [x] if type(x) is not list else
        x
        )
    )
```
リストじゃないやつは一旦リストに持ち上げてからバラす作戦です。
Pythonの流儀に合わせて、ジェネレータにしました。

これを使えば flat_map はこうなります。

```py
flat_map = lambda f, xs : flat( map( f, xs ) )
```
他にちょうどいいのがあれば コメント よろしくお願いします。
Kasperskyが入っている環境でGoogleドキュメントの印刷機能が使えなくなる場合がある問題の対応

めも。

バージョンによるかもしれませんが、Kasperskyの証明書が適用されていると、印刷時にCORSエラーが出て、読み込みがずっと終わらないような状態になってしまうみたいです。

Kasperskyの画面を開き、
歯車マーク --> ネットワーク設定 --> 暗号化された接続のスキャン
ここの項目を「暗号化された接続をスキャンしない」にする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/40647/c0e6a491-2994-8502-1e8d-90f4209083a4.png)


その後、Chromeを全て閉じて開き直します。
私がやったときは、リロードやスーパーリロードでは証明書が更新されませんでしたが、Chromeの再起動で適用されました。

この状態で再度印刷操作を行うと、印刷出来ました。
Ubuntu16.04でgoogle chromeが正しく最大化されない（リモートデスクトップも正しく表示されない）

# 概要

4Kモニタを利用しているか原因はわからないのですが、
Ubuntu16.04でgoogle chromeを最大化すると以下のように上部分はめり込んでしまうし、横幅は画面に収まっていない状態になってしましました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77041/3fc7ea82-ca64-fe5a-122a-0a725c7f37f5.png)

google リモートデスクトップも正しく表示されないです。

# 解決方法

設定 > システム >
「ハードウェアアクセラレーションが使用可能な場合は使用する」を OFF で解決しました。

※リモートデスクトップが正しく表示されない現象もこれで解決できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77041/e2803d76-c790-f61e-d21c-f1cf78d3e447.png)
Chrome 87で「送信しようとしている情報は保護されません」って出て来ても焦るな！

# はじめに
私は超焦ったのですが、一応解決しましたので1つのワークアラウンドとして書きためておきます。

# 結論から
HTTPSでPOSTした結果、HTTPのページにリダイレクトするような状況でも引っかかるようです。
そもそもそんなリダイレクト設定になっている事が・・・・なのですが。
皆さんは私みたいなアホな事にならないよう気を付けましょう。

# 何が起こった
- ログイン画面からアカパス入力してログインしようとしたときにエラーが起こるようになった

![スクリーンショット 2020-12-14 14.42.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160080/581b14e5-bd6a-d1a2-0bbf-00229000f468.png)


# まず調べる
- ググっても「Mixed Contentだからじゃね？」で一蹴される
    - んなわけないよ全部httpsだよ。。。

# 状況整理する
- アプリケーションの経路的にHTTPになってるところありませんか？
    - AWS使ってて、ALBも使ってる
    - ALBでHTTPSの復号をしてるので、EC2まではHTTP ★これだ！！★

# よく見てみる
- https://にPOSTした結果、正常系でページリダイレクトするときのアプリケーション側でリダイレクトしている箇所がhttp://で返ってきてた。
    - なんでやねん・・・と思ったけど、Web/APから見たらHTTPでアクセスしてるのでこんなことになってた。

# なので
- リダイレクト先のURLを決定する際には必ずhttps://になるようにオーバーライド
iPhone のスクリーンタイムで、アプリが変な表示になってしまった…

# ０．はじめに

スクリーンタイムでアプリの表示が変な表示になってしまったので、対応しました。

こんな感じになっていました…

![IMG_0832.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/161939/5ddf561f-b854-baaf-635a-a99ea95e8eda.png)

- アプリ名が表示されない…
- タイム表示が中央に…

# １． `info.plist` を修正

`info.plist` から、以下を削除。

```plist
	<key>CFBundleDisplayName</key>
	<string></string>
```

`CFBundleDisplayName` が空になっていたのですが、何故こういう設定になっていたのかは不明…
私が何かしたのかもしれませんが、全く覚えていません…

とりあえず、`info.plist` が影響している気がしたので、設定色々変えてみたらここでした…

- [\[iOS\] アプリ名を変更する \- Qiita](https://qiita.com/hiroo0529/items/24b027b9708d14200b56)
- [iOSでホーム画面に表示されるアプリ名はどこで決まるのか？変更するには？ \- Qiita](https://qiita.com/temoki/items/fc3b62bc088f96184f8f)


# ９９．ハマりポイント

* どこが影響してスクリーンタイムの表示がおかしくなったのか、最初さっぱり検討がつかなかったので、少々時間が掛かりました…

* ちょうど、iOS14 にアップデートしたタイミングだったので、iOS のバグなのかよくわからず…

* ネットにも同様の事象が見つからず…

* とりあえず、解決出来てホッとしました。

# ＸＸ．まとめ

ご参考になれば ♪♪♪

👋👋👋
E.G.G. プログラムに参加してミニセッションを行いました

今年は「Expert of GCP for Gaming Japan プログラム」という Google さんのゲーム業界エンジニア向け GCP 特別トレーニングプログラムに参加して、無事に [Google Cloud Professional Cloud Architect](https://cloud.google.com/certification/cloud-architect?hl=ja) に合格することができました。

このトレーニングプログラムは今年2度開かれました。
私は1期の方に参加しましたが、2期の途中に「1期生によるE.G.G. 卒業生コメント」としてショートセッションをさせていただきましたので、その際のスライドをご紹介させていただきます。


# Expert of GCP for Gaming (E.G.G.) Japan プログラムとは

Expert of GCP for Gaming Japan プログラムは、略して E.G.G. Japan プログラム と呼び 4月から6月 にかけて第1期が開かれました。
プログラムには、セッションやハンズオンそして Coursera などの自習も含まれていました。
また、Google Cloud Professional Cloud Architect 試験の合格も含む修了条件があり、クリアすることで卒業となります。
セッションは、募集の段階ではGoogleさんの会場に集まってセッションするという予定でしたが、コロナの影響ですべてGoogle Meetによるオンラインでのリモート開催になりました。


# E.G.G. 卒業生コメント

第2期の際に卒業生コメントの機会をGoogleさんからお声がけいただき、以下のような資料を使ってもくもく会の途中にお話させていただきました。
[![slide](https://image.slidesharecdn.com/2020adventcalender-201212190050/95/egg-1-638.jpg?cb=1607799796)](https://www2.slideshare.net/gutio81/egg-240056784)

[E.G.G.卒業生コメント - SlideShare](https://www2.slideshare.net/gutio81/egg-240056784)

# おわりに
E.G.G. 参加以前は用意されたBigQueryを使う程度しかGCPの経験がなかった私ですが、受講以降は実験的な業務の中でGKEなどの利用をはじめました。
もし、この記事やスライドをみてGCPに興味が出たゲーム業界の方がいましたら、ぜひGoogleの営業の人にE.G.G.について聞いてみてください！
Y字路巡り（どう書く）

[http://nabetani.sakura.ne.jp/hena/ord3ynode/](http://nabetani.sakura.ne.jp/hena/ord3ynode/)

[あるグラフ](http://nabetani.sakura.ne.jp/hena/ord3ynode/map3.png)に対し、「右折して進む/左折して進む/後戻り」の連続する指示が与えられた場合、通過するノードの列を出力する問題です。

```ruby:Ruby
module YshapedRoadTour
  Graph = {"A"=>"DCB", "B"=>"CEA", "C"=>"FBA",
           "D"=>"EFA", "E"=>"DBF", "F"=>"ECD"}
           
  def self.solve(input)
    input = input.each_char
    result = ""
    
    go = ->(s, e) {
      result << e
      idx = Graph[e].index(s)
      case input.next
      when "b"
        go.(e, s)
      when "r"
        i = (idx - 1) % 3
      when "l"
        i = (idx + 1) % 3
      end
      go.(e, Graph[e][i])
    }
    go.("B", "A")
  rescue StopIteration
    result
  end
end


if __FILE__ == $0
  require 'minitest/autorun'
  describe 'YshapedRoadTour' do
    [
      ["b", "AB"],
      ["l", "AD"],
      ["r", "AC"],
      ["bbb", "ABAB"],
      ["rrr", "ACBA"],
      ["blll", "ABCAB"],
      ["llll", "ADEBA"],
      ["rbrl", "ACADE"],
      ["brrrr", "ABEDAB"],
      ["llrrr", "ADEFDE"],
      ["lrlll", "ADFEDF"],
      ["lrrrr", "ADFCAD"],
      ["rllll", "ACFDAC"],
      ["blrrrr", "ABCFEBC"],
      ["brllll", "ABEFCBE"],
      ["bbbrrlrl", "ABABEDFCB"],
      ["rbllrrrr", "ACABCFEBC"],
      ["lbrlrrblr", "ADABCFEFCA"],
      ["rlbrrrrbl", "ACFCADFCFD"],
      ["bllrlrbrrb", "ABCADEFEBCB"],
      ["rllrllllbb", "ACFDEBADEDE"],
      ["blblrlrrlbr", "ABCBEDFCABAC"],
      ["lrlrrrrrbrb", "ADFEBCFEBEDE"],
      ["rblllrlrrlrr", "ACABCADEFDABE"],
      ["rbrrlrblrllb", "ACADFEBEFDACA"],
      ["lrrrlrllrrllr", "ADFCABEFCADEBC"],
      ["rrlblllrrlrrb", "ACBEBADEFDABEB"],
      ["brbllrrbbrlrll", "ABEBADFCFCABEFC"],
      ["rrrbbrlbrlblrb", "ACBABACFCABADFD"],
      ["lllllllllllblrr", "ADEBADEBADEBEFDE"],
      ["llllllrllrlbrrr", "ADEBADEFCBADABED"]
    ].each do |input, expect|
      it input do
        assert_equal YshapedRoadTour.solve(input), expect 
      end
    end
  end
end
```

右折や左折を表現するのがむずかしいですね。ここではグラフを Hash で表しているのですが、`{"A"=>"DCB"}`なら、ノードAを中心として右回りにD, C, Bとなっているとの意味です。

入力は`each_char`で Enumerator に変換して、一文字ずつ`next`で取り出しています。取り出すべきものがなくなると例外`StopIteration`が発生するので、それを`rescue`で捕捉して結果を返すようにしています。

`go.(s, e)`というのは、`s`から`e`へ進むという意味です。

ここでは再帰を使っていますが、ループの方がいいのでしょうね。でも、再帰が何となく好きなので（笑）。

#ループ版
ループを使ったものはこんな感じでしょうか。やっぱりこの方がいいか（笑）。

```ruby
module YshapedRoadTour
  Graph = {"A"=>"DCB", "B"=>"CEA", "C"=>"FBA",
           "D"=>"EFA", "E"=>"DBF", "F"=>"ECD"}
           
  def self.solve(input)
    input = input.each_char
    result = ""
    s, e = "B", "A"
    
    loop do
      result << e
      idx = Graph[e].index(s)
      case input.next
      when "b"
        s, e = e, s
      when "r"
        i = (idx - 1) % 3
        s, e = e, Graph[e][i]
      when "l"
        i = (idx + 1) % 3
        s, e = e, Graph[e][i]
      end
    end
    result
  end
end
```

なお、`loop do ~ end` は例外 StopIteration を捕捉するようになっているので、Enumerator#next が素直に書けます。
Flutter + Firebase 簡単！メール認証の実装

### 今回やったこと
新規会員登録などで、会員登録後に登録したメールアドレスに届いたメールのリンクを踏むと登録完了となるアレです！
FirebaseAuthenticationを使ったお手軽なメール認証を、Flutterバージョンでお届けします。

コードだけサクッと知りたい方はこちらになります。
Firebase設定の手順を知りたい方は、さらに読み進んでください。

```dart
  String mail;
  String password;

  Future shinUp() async {
    try {
      final _auth = FirebaseAuth.instance();

      // バリデーション後のメールアドレスとパスワードでアカウント登録
      await _auth.createUserWithEmailAndPassword(email: mail, password: password);
      
      // 確認メール送信
      await _auth.currentUser.sendEmailVerification();
    } catch (error) {
      throw error;
    }
  }

  Future login() async {
    try {
      final _auth = FirebaseAuth.instance();

      // 一旦サインインします
      await _auth.signInWithEmailAndPassword(
        email: this.mail,
        password: this.password,
      );

      // メール認証完了しているか取得
      final _isVerified = await _auth.currentUser.emailVerified;

      if (!_isVerified) {
        // もう一度メール送信
        _auth.currentUser.sendEmailVerification();

        // サインアウトする
        await _auth.signOut();
        throw ('isNotVerified');
      }
    } catch (error) {
      throw error;
    }
  }
```

数行で会員登録からメール認証までを実装することができました！！！

### Firebaseの設定
手順①：対象のプロジェクトのサイドメニューからAuthenticationを選択します。
手順②：始めるボタンを押して、開始します。
![スクリーンショット 2020-12-14 13.22.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873366/e389baf7-d4ea-bbd2-34ae-abc898c4d6fa.png)

手順③プロバイダからメールを選択し、デフォルトが無効になっているので有効に変更します。
![スクリーンショット 2020-12-14 13.20.29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873366/42ff9855-36fe-ad9f-6fcb-560238d47c1f.png)


手順④：上のタブからTemplatesを選択、ここからユーザーに送るメールの内容を変更できます。
メールの言語はデフォルトが英語なのでプルダウンから簡単に日本語に変更することができます。
![スクリーンショット 2020-12-14 13.21.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/873366/56de3653-daf1-cbbf-3d89-4b5890c18c79.png)

### Firebaseの設定は以上で完了です。
お好みで、内容の設定をしてください。

### 所属しているFlutter大学について
サロン主催のアドベントカレンダーとのことで、初めて投稿させて頂きました。
間違っている点などございましたら、ご指摘ください。

Flutter大学ではいろんな人のプロジェクトが見放題です。
すでにある画面のUIやFirebase設定を自分用に少しアレンジするだけで
実装できるので、入会してから個人で開発している時よりも開発スピードが格段に早くなりました。

また、わからないことがあったらすぐ聞けたり、頑張っている人がたくさんいらっしゃるので
モチベーションが上がりました。

サロンでFirebaseの面白さを学んだので、これから色々な場面で活用していきたいと思います！

現在、iOSエンジニアからFlutterエンジニアになるため転職活動中です。
VMWare上でWindowsマシンのネットワーク速度が出ない時

## 概要

Windows 仮想マシンをVMWareで作成した場合にパフォーマンスが出ない場合があります。
ネットワーク速度が1Gbps(約125MByte/s)で頭打ちになっている場合、ネットワークドライバが原因であることがあります。
https://kb.vmware.com/s/article/1001805?lang=ja

自分の環境が該当する場合は、以下の作業を実施して10Gbpsのネットワークを利用可能にします。

## 作業

1. Windows 仮想マシンにVmWareツールを追加します。
![vmwaretools.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631668/87d72a08-42e8-fc02-92be-0ce2ba72e0db.png)
2. ネットワークアダプタを追加します。その際に、アダプタタイプをVMXNET3を選択します。
![Network.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/631668/1a36cbdd-eb21-14cc-afb1-4624adc35382.png)