OmniAICreator/Qiita-1.07M huggingface dataset:
githubをwebサーバとして公開する手順の備忘録

# 目的
githubをwebサーバとして公開する手順の備忘録です

# 手順
色々検索したが、以下の公式サイトの手順が最も分かり易かった。

> [https://pages.github.com/](https://pages.github.com/)

日本語サイトならば以下の手順が分かり易かった。

> [GitHubのmasterブランチをWebページとして公開する手順（GitHub Pages）](https://qiita.com/tonkotsuboy_com/items/f98667b89228b98bc096)

# memo

Create New Repository —> Settings —> Github Pages —> master branch/Docs と設定を進めるとGithub Pages URLが表示される。
<img width="305" alt="スクリーンショット 2020-05-04 1.32.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/344880/3d61342f-8b30-6fd9-2af0-4071c6b501bb.png">

# 制約

[GitHub Pages について](https://help.github.com/ja/github/working-with-github-pages/about-github-pages)
> GitHub アカウントごとに、ユーザまたは Organization サイトを 1 つだけ作成できます。

# 参考
[https://pages.github.com/](https://pages.github.com/)
[GitHubのmasterブランチをWebページとして公開する手順（GitHub Pages）](https://qiita.com/tonkotsuboy_com/items/f98667b89228b98bc096)
[GitHubを使って3分でHPを公開する。](https://qiita.com/budougumi0617/items/221bb946d1c90d6769e9)
[無料で使える！GitHub Pagesを使ってWebページを公開する方法](https://techacademy.jp/magazine/6445)
【第4回】pythonで某Authenticator的なツールを作ってみた

# 今回は、DBを片付けてみた。
- 各DBの動作をdefで書き出した。
- root = tk.Tk()以下のあたりから表示系
- うまい具合にまとめられた感じがする。

```python
#!/usr/bin/env python
# -*- coding: utf-8 -*-

import tkinter as tk
import pyotp
import sqlite3
import os

def create_table():
    # データベースに接続する
    conn = sqlite3.connect('gauth.db')
    c = conn.cursor()
    # テーブルの作成
    sql='''CREATE TABLE gauth
    (id integer primary key AUTOINCREMENT,
     name text,
     private_key text)'''

    c.execute(sql)
    # 挿入した結果を保存（コミット）する
    conn.commit()
    # データベースへのアクセスが終わったら close する
    conn.close()

def view():
    # データベースに接続する
    conn = sqlite3.connect('gauth.db')
    c = conn.cursor()
    for a in c.execute("select * from gauth"):
        totp = pyotp.TOTP(a[2])  # 鍵的な値
        totp.now()
        # 表示用ラベル
        Static1 = tk.Label(text=a[1])
        Static1.pack(side='left')

        Static2 = tk.Label(text=totp.now())
        Static2.pack(side='left')
    # 挿入した結果を保存（コミット）する
    conn.commit()
    # データベースへのアクセスが終わったら close する
    conn.close()

def insert(id,username,private_key):
    # データベースに接続する
    conn = sqlite3.connect('gauth.db')
    c = conn.cursor()
    # データの挿入
    c.execute(
        "INSERT INTO gauth VALUES (?,?,?)",(id,username,private_key))
    # 挿入した結果を保存（コミット）する
    conn.commit()
    # データベースへのアクセスが終わったら close する
    conn.close()

# tkinterでwindowの作成とタイトルを作る
# windowサイズの指定
root = tk.Tk()
root.title(u"g_authentication_tool")
root.geometry("300x200")
# メニューバー
menubar = tk.Menu(root)
filemenu = tk.Menu(menubar)
filemenu.add_command(label="新規登録")
filemenu.add_command(label="登録削除")
filemenu.add_command(label="閉じる")
menubar.add_cascade(label="ファイル", menu=filemenu)
root.config(menu=menubar)
if(os.path.exists('gauth.db')):
    view()
else:
    create_table()
    #insert(1,"user1",'base32secret3232')
    view()
root.mainloop()

```
Monaco Editorで便利な機能「アクション」を使う

# はじめに

　久々にMonaco Editorについて書く今回は、Monaco Editorの便利な機能の一つである、IEditorAction（わかりやすさのためここではアクションと呼ぶ）を紹介してみる。
　これはVisual Studio Codeでいうところのコマンドパレットにあたる機能で、Monaco Editorの定義ではIEditorActionとドキュメントに書かれるものだ。
　これはMonaco Editorを利用したウェブアプリ上（つまりUI上）で利用者が使えるのはもちろんだが、これの便利なところはプログラミングの最中でも各アクションを呼び出してウェブアプリ中の様々な機能の実現に活用することができる。

# アプリ上(UI上)で使う

　もっともかんたんな作成方法でMonaco Editorを自分のアプリ上で作っても、デフォルトでアクションはコマンドパレットとして使うことができる。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/27591fea-e246-2171-4f17-b03b5ccb6d61.png)
※適当にエディタを作成した例

　どんなに適当に作ってもVisual Studio Codeと同等レベルのコマンドを利用することができるのでありがたい。

# コマンドパレットにアクションを追加する

　ではコマンドパレットに新たなアクションを追加する方法を紹介したい。

　これには `addAction` メソッドを使う。

```javascript:test.js
var myeditor = monaco.editor.create(this.element,{...});
var cmd1 = {
    id : "wordwrapAction001",
    label : "wordwrap off",

    keybindings : [monaco.KeyMod.CtrlCmd | monaco.KeyCode.KEY_V],
    contextMenuGroupId: 'clipboadAction',
    contextMenuOrder: 5,

    run : function (editor) {
        editor.updateOptions({
            wordWrap : "off"
        });
        return null;
    }
};
myeditor.addAction(cmd1);

```
プロパティは他にもあるが、基本の使い方でこれだけ使っておけばよいというものを抜粋して紹介する。

変数 **cmd1** で示すものはIActionDescriptorと称される型だ。Javascriptでは普通にJSON形式で生成して問題ない。

**id** は、エディタ（ICodeEditor）上で判別される値だ。一意のものでこれを使ってアクションを後で取得できたりする。

**label** は、UI上で表示する名称だ。翻訳等をうまく実装してここを適切にセットしておきたいところだ。

**keybindings** はショートカットキーを定義するのに使う。
主要なキーコードは `monaco.KeyCode` に存在する。
Ctrlなどの特殊なキーは `monaco.KeyMod` にあるものを使う。ちなみにmonaco.KeyCode.Ctrlなども存在するので間違えないよう注意。そしてこれらを | で定義する。
複数のショートカットキーを定義したい場合は配列で定義しているため、, でつなげていけばよい。

**contextMenuGroupId** は右クリックで出てくるコンテキストメニューに配置する場合のグループIDを定義する。
デフォルトでは次のものがある。

・1_modification ・・・ Visual Studio Codeでいうところの「ドキュメントのフォーマット」「すべての出現箇所を変更」が表示されているアクションのグループのこと。
・9_cutcopypaste ・・・ 「コピー」「切り取り」があるグループのこと。

これらを指定すると新たなコマンドはそれらのグループの中に表示されるようになる。
もちろんまったく新しいグループIDを指定すれば新たなグルーピングとして表示される。

**contextMenuOrder** はそれらのグループの中の表示位置を指定する。

**run** が実行する処理内容である。これが一番のキモだろう。
このメソッドは引数にICodeEditorを受け渡してくる。また、追加で可変の引数も指定できる。

ICodeEditorの型で受け渡されるため、ITextModel（AceでいうところのEditSession）などもすべて呼び出せる。つまり、あらゆる機能を実現可能だ。

これら必要な項目を定義したらいざ `addAction` に受け渡せば、このように利用できるようになる。（例：ほげほげ貼り付け）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/8f2dda6b-85eb-004f-9af7-c0d9779d19ed.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/38416/2e5a85fa-0b23-8f53-0f3d-e889ae0e8232.png)


# コーディング中に使う

　定義したアクションはコーディング時に使うこともできる。自分で定義したアクション以外にデフォルトで用意されているアクションも利用可能だ。

```javascript:test.js
var actions = editor.getActions();
actions[49].run();     //---49番目のアクションを実行

var act2 = editor.getAction("actions.find");
act2.run();    //---検索アクションを呼び出す．
```
`getActions` メソッドは定義されているすべてのアクションを取得する。何があるのかわからないという場合にはこれを使ってメモしておこう。

`getAction` メソッドは各アクションで定義されている *id* を指定して特定のアクションを取得する。よく呼び出したいアクションは別途このIDを退避しておけばどのコード中でも手軽に呼び出せる。


# 終わりに

　Monaco Editorは単にプログラミング言語のソースに直接便利なだけではなく、うまく利用すれば単なるソースコードのエディタを超える機能を実現できるだろう。
　アクション（IEditorAction）もそんな可能性を秘めた機能の一つだ。みなさんうまく使いこなそう。
簡単VBAマクロの手順

1.EXcel.exeを起動します
2.マクロの記録を選択(Alt+W → M → R)
※セルを操作すればコードが記憶されます
3.マクロの名前を決めてOK
4.マクロの記録を終了(Alt+W → M → R)
5.マクロの表示(Alt+W → M → V)
6-1.マクロの名前を選択して実行 →　マクロ実行
6-2.マクロの名前を選択して編集 →  VBAコードを修正できる
[UE4]WidgetComponentでDynamicMaterialInstanceを使おうとしたら詰まった話



# 概要
WidgetComponentでDynamicMaterialInstanceを使おうとしたら詰まったので、解決策のメモとして。
環境はUE4.24。

# やろうとしたこと
Widgetの見た目の変更を、Widgetのアニメーションや表示切り替えを使わずに、WidgetComponentのMaterialだけでやろうとした。
※Materialで見た目を変えた場合、Widgetの見た目をRenderTargetに再描画する処理が入らない為、パーツの多いWidgetの場合軽量化が見込める。

今回はサンプルとして、テキストのColorを変える。
取り敢えずWidgetでテキストを配置して、赤いMaterialをWidgetComponentに割り当てた。
![コメント 2020-04-18 183254.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/19affea1-45bf-4c7a-8de4-fae00d2191cb.png)

# 問題発生
ここまでは順調だったのだが、いざパラメーターをMaterialに渡そうとしたところで問題が発生した。

UE4でMaterialにパラメーターを渡し、動的に見た目を変える場合、DynamicMaterialInstanceを作成する必要がある。
StaticMeshComponentなどで使う時と同様に、BeginPlayでWidgetComponentのDynamicMaterialInstanceを作成した。
![コメント 2020-04-18 181713.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/acf617af-f805-0ae3-fac8-73d5169e8846.png)

すると、先程まで表示されていたテキストが、デフォルトマテリアルの見た目になってしまった。
![コメント 2020-04-18 183228.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/693ed761-c5d7-9bce-ff79-d3a71763d619.png)

# 原因
もしかして未対応なのかと考えながらログを見てみると、下記のようなログが出力されていた。
`LogMaterial: Warning: MaterialInstanceDynamic MaterialInstanceDynamic_2 is not a valid parent for MaterialInstanceDynamic MaterialInstanceDynamic_3. Only Materials and Material InstanceConstants are valid parents for a material instance.`

これだけだとなんのこっちゃといった感じだが、ログを出力している箇所から処理を追ってみると、原因が分かった。


WidgetComponentは、**RenderTargetに描画する為に元々DynamicMaterialInstanceを変数に保持**していて、それが`UWidgetComponent::SetMaterial`が呼ばれる度に更新される。
DynamicMaterialInstanceを作った場合SetMaterialも呼ばれる為、保持していた描画用のDynamicMaterialInstanceも更新されるが、ここで問題が発生する。

現在のMaterialを元にDynamicMaterialInstanceを作成し、描画用の変数を更新しようとするが、現在のMaterialは自分で作ったDynamicMaterialInstanceになっているので、DynamicMaterialInstanceを親にしてDynamicMaterialInstanceを作ることになる。
これには対応していないようで、結果的に上に貼ったログが出力される。(DynamicMaterialInstanceはDynamicMaterialInstanceの有効な親ではありません)

# 結論
WidgetComponentでDynamicMaterialInstanceを使いたい場合は、描画用にDynamicMaterialInstanceが勝手に作られているので、それを参照するだけでいい。
`UWidgetComponent::GetMaterialInstance`で参照出来、Blueprintからも呼ぶことが出来る。
![コメント 2020-04-18 191909.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/68efe8ee-8109-052a-a510-0f1e8529d91e.png)

無事色を変えることが出来た。
![コメント 2020-04-18 191704.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/601695/2be7fab0-b105-1857-080c-8b58707d6e34.png)
コマンドライン引数処理（Python の docopt）

こんにちは
Python の [docopt](http://docopt.org/)（コマンドライン引数処理）[^1] を試してみました。

下記例で、```--oo```、```--pp```、 ```--qq``` の記述の違いを試しました。```--qq``` の場合には結果がリストとして返ってきました（この記述は公式にはお勧めではないような気もします）。のかもしれません）。

```console
$ ./docopt_test.py
{'--help': False,
 '--oo': None,
 '--pp': None,
 '--qq': [],
 'X': []}
$
$ ./docopt_test.py -o 0 -p 1 -q 2 3 4
{'--help': False,
 '--oo': '0',
 '--pp': '1',
 '--qq': ['2'],
 'X': ['3', '4']}
$
```

```docopt_test.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-

def argsdocopt(doc):
    import docopt, textwrap
    return docopt.docopt(textwrap.dedent(doc))    

def main():
    """
    {f}: Test a docopt library.

    usage: {f} [-h] [-o O] [-p <P>|--pp <P>] [-q|--qq <Q>] [X...]
    
    options:
        -h, --help        show this help message and exit
        -o, --oo O        parameter O
        -p <P>, --pp <P>  parameter P
        -q, --qq <Q>      parameter Q
    """
    args = argsdocopt(main.__doc__.format(f=__file__))
    print(args)

if __name__ == '__main__':
    main()
```

[^1]: 「[Pythonのdocopt使い方メモ](https://qiita.com/ymdymd/items/651245d80964393b12c5)」も参考にしました。
【icrawler】Googleの仕様変更後でも画像をダウンロードする方法(2020.3月以降)

初めまして。
ペーペーの文系大学生です。
趣味程度でディープラーニングをかじっております。

好きなアイドルやキャラクターの写真を画像認識させたい時にいつもicrawlerを使っていました。
ですが、今までのやり方だと急に出来まくなってて、、、
（2020.03から仕様変更があったそうです。）
今まで使えていたコードが下のです。（これではエラーが出ます。）

```python:get_image.py
from icrawler.builtin import GoogleImageCrawler
import sys
import os

argv = sys.argv

if not os.path.isdir(argv[1]):
    os.makedirs(argv[1])


crawler = GoogleImageCrawler(storage = {"root_dir" : argv[1]})
crawler.crawl(keyword = argv[2], max_num = 1000)
```

変更後に使えるコードは

```python:get_image.py
from icrawler.builtin import BingImageCrawler
import sys
import os

argv = sys.argv

if not os.path.isdir(argv[1]):
    os.makedirs(argv[1])


crawler = BingImageCrawler(storage = {"root_dir" : argv[1]})
crawler.crawl(keyword = argv[2], max_num = 1000)
```
です。
これで動きました!!!!!!!
GoogleImageCrawlerをBingImageCrawlerに置き換えたら動くそうです。


ちなみにこのプログラムを実行したいときは、ターミナルに以下のように打ち込むといけると思います！！

```
$　python get_imeg.py */保存したいディレクトリ　検索したい画像名
```

```commend
python get_image.py */ダウンロードした画像を保存したいディレクトリ　ダウンロードしたい画像の名前（例えば　白石麻衣　とか）　
````
爆笑問題　田中で実行すると、下のように自動で回収してくれます。
<img width="744" alt="スクリーンショット 2020-04-19 17.16.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/342322/5cd97222-4cb4-a10d-e3f7-04b5c3b8ce63.png">

ディープラーニングの際には是非！！！
これで、１連の流れは網羅してあります！！
[爆笑問題の太田派？田中派？(画像認識入門）](https://qiita.com/kumakuma324/items/58091d0a1c3f39f47333)

>
引用
https://qiita.com/NakaokaRei/items/8c7e7b1f2c0c7ef8b3a3
API Gatewayとバックエンドの疎通確認で時間を無駄にしないための手順書


API Gateway(HTTP API)の疎通確認は、段階ごとに進めないと混乱します。
リクエストがバックエンドに到達するまでと、各段階の調査方法をまとめました。

# API Gateway → バックエンドのリクエスト解決順

1. カスタムドメインをStageごとのInvoke URLに解決する。
2. ステージ内の指定したリソースに対するアクセス権が存在するかを確認する。
3. メソッドリクエスト実行のための認証を行う
4. メソッドリクエストを受け付けた後、API Gatewayからバックエンド（例えばAWS Lambda）に統合リクエストを行う（終了）


# 1. カスタムドメインをStageごとのInvoke URLに解決する

普通に`dig`してCNAMEレコードが返ってくるか確認してください。
ここで失敗していると、当然ですがそもそもAPIからレスポンスが返ってきません。

# 2. ステージ内の指定したリソースに対するアクセス権が存在するかを確認する

疎通確認のため、API GatewayのStageから`Enable CloudWatch Logs` を必ず有効にしてください。
CloudFormationで設定している場合は `TracingEnabled: true` で有効になります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/96286/4b53a52c-b1c7-5769-8f48-a81281c21a35.png)

その後、普通に `curl` や `Postman` でAPIにアクセスしてください。
私がよく遭遇するエラーは以下のとおりです。  

### Missing Authentication Token

API Gatewayの指定したリソースが存在しない場合に表示されます。
要するにURLやメソッドが間違ってるか、API Gatewayのリソースポリシーが間違っています。

```
{
    "message": "Missing Authentication Token"
}
```

# 3. メソッドリクエスト実行のための認証を行う

メソッドリクエストの実行に失敗した時によく遭遇するエラーは以下の通りです。

### Forbidden

例えばAPI_KEYが間違っています。

```
{
    "message": "Forbidden"
}
```

### The security token included in the request is invalid

メソッドリクエストの AuthorizerをIAMに指定している場合で、かつAWSのセッションが切れている場合です。

```
{
    "message": "The security token included in the request is invalid"
}
```


# 4. メソッドリクエストを受け付けた後、API Gatewayからバックエンド（例えばAWS Lambda）に統合リクエストを行う

ここまでくれば、後は API Gateway自体の CloudWatch Logsでデバッグできるでしょう。

よくやらかすのはAPI GatewayにLambdaを実行する権限がない場合などです。
複数の証明書が結合されたファイルの内容をopensslで表示する

X.509形式の証明書が複数結合されて1つのファイルになっている場合、`openssl x509 -in <証明書ファイル> -text -noout`では、一番最初の証明書の情報しか表示されない。

すべての証明書の情報を表示する方法として、1つずつ分割してopenssl x509 ～ で表示する方法もあるが、下記の方法でも簡単に表示できる。

```
openssl crl2pkcs7 -nocrl -certfile <証明書ファイル> | openssl pkcs7 -print_certs -text -noout
```


# 参考
https://serverfault.com/questions/590870/how-to-view-all-ssl-certificates-in-a-bundle
こちらに載ってました。結構重要なのにあまり日本語の情報がなかったので、転載させていただきました。

http://moca.wide.ad.jp/moca_guide/about_fileformat.html

* opensslはX.509ファイルの"-----BEGIN CERTIFICATE-----"の前の文字列や"-----END CERTIFICATE-----"の後の文字列を無視して扱う。

https://security.data-site.info/35.html

* X.509は単体の証明書用の形式のため、複数証明書を格納可能なPKCS#7形式に変換した上で、内容を表示している。
【AWS】CloudWatchで利用料金をメール通知する

##やりたいこと
自宅学習用にAWSアカウント取得したが、気になるのは使用料金。
気づいたらすごい金額になっていた、というのを避けるべく、1万円を超えたときにメール通知で知らせるようにしたい！

##手順
（※2020年4月18日時点での画面なので、仕様が変わっている場合があります。）

リージョンを「バージニア北部、US-EAST-1」に変更する。
（請求のメトリクスデータは、バージニア北部リージョンに保存されているため）
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/579d123c-513b-fa15-8d2e-b1d3a84a1ffe.png)

AWSのコンソール画面から「CloudWatch」→「アラーム」を選択。
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/f11f08be-dcda-63d1-28f3-a42315714d5e.png)

右上の「アラームの作成」を選択。
![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/14d0da7c-3db5-6bb1-03f3-9db3498be0fa.png)

##CloudWatchの監視対象となるメトリクスを指定する
「メトリクスの選択」→「次へ」
![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/076e669a-3956-3316-6ac3-d628b7b01dfc.png)
「請求」を選択。
※ここで、「請求」が表示されていない場合は、予想請求額のモニタリングを有効にする必要があります。
参考: https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html
![5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/5da5b0bd-6bff-c54c-9f3d-3db73d78ab1e.png)
「概算合計請求額」を選択。
![6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/fc4f4326-1f48-f7a9-23c9-3c931d6a8fe6.png)
「USD」を選択。
![7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/2f79185f-435d-06eb-776f-4787c9e942a5.png)
メトリクスの条件として、利用料金の閾値を指定する。
USD表記なので、自分の場合は100USDとして設定。（約1万円を超えたら通知）
それ以外の項目は特に触らなくてよさそう。「次へ」
![8.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/badedc7a-3327-80e6-0d57-fe8e8567ffcf.png)
##通知先の指定
すでに作成済みのSNSトピックがあり、そこに通知したい場合は、「既存のSNSトピックを選択」から作成済みのトピックを選択する。
今回は新たにSNSトピックを作成し、そこに向けて通知を行う。
「新しいトピックを作成」を選択し、トピック名と通知先のEメールアドレスを入力する。
入力後、トピックの作成を押下。
![9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/1fb760c2-0741-e928-50fc-247b26d9c069.png)

すると、作成したトピックが通知先として選択された状態になる。「次へ」
![10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/b3864977-054e-67ce-306a-6014a5cf4f63.png)
確認画面を「次へ」
![11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/bddca1ab-c933-0e7f-1642-11ceac1d81d0.png)
「アラームの作成」
![12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/e8ea1ab3-d15d-3c5b-5922-f11a3b8e041f.png)
CloudWatchのダッシュボード画面を確認して、アラームが追加されていればOK！
下記の画像のように、「一部サブスクリプションが・・・」が表示されている場合は、SNSの通知先に指定したアドレスにAWSから送られた認証メールを確認する必要がある。
![13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/328551/f4f58411-06ff-9701-59c9-5ed40f74538f.png)
Macでとりあえず覚えておきたいショートカット

エンジニア向けメモ。
数年業務をしてきて息をするように使っているショートカットを改めてまとめてみる。
コピー＆ペーストなどは知ってるものとして省く。
主に `controlボタン(以下Ctrl)` との組み合わせ。

## 事前準備: キー配列確認

ショートカットを覚える前にまず自身のCtrlボタンの位置を確認する。

前提として、Ctrlボタンの位置は `A` の左隣が小指でアクセスしやすいのでそうじゃない場合は変更することをおすすめする。
JIS配列ならそのままでok。

US配列なら caps lock を `システム環境設定 → キーボード → 修飾キー` から変更しておく。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/149698/3e9cff61-2fa4-a9e7-33e2-e18865f87bfa.png)

また、US配列の方はこの記事から、⌘ボタンの左右をJIS配列のように `英数` `かな` に対応させることをおすすめする。
[Mac用 Apple英字配列(US)キーボードにおける日本語入力切替のおすすめ：Commandキーのみで実現](https://qiita.com/daichi87gi/items/ded35e9d9a54c8fcb9d6)

自分はJIS配列もUS配列も使ってきたけど、US配列にして`Karabiner`でハイブリッドな配列にするのが最適解な気がしてる。


## カーソル移動

### とにかくめっちゃ使う

* Ctrl + a

行の先頭に移動する

* Ctrl + e

行末に移動する

* Ctrl + k

その行を削除する。`Ctrl + a` した後に `Ctrl + k` はよく使う。

* Ctrl + d

次の文字を1文字削除。ちなみにdelete相当は `Ctrl + h`。

### 矢印ボタンが遠くて使いたくない人向け

慣れると爆速で移動できるのでおすすめ。

* Ctrl + f

カーソルを右へ移動。

* Ctrl + b

カーソルを左へ移動。

* Ctrl + n

カーソルを下へ移動。
ちなみにterminalのhistory検索にも対応してる。

* Ctrl + p

カーソルを上へ移動。
ちなみにterminalのhistory検索にも対応してる。

### 単語単位で移動したい

* Alt + 矢印

単語単位で移動。ここでは矢印を使うしかない。
shiftと組み合わせれば単語単位で選択できる。

## 変換

* 日本語入力中に`英数` ボタンを2回連続タップ(Karabinerで変換した人は左⌘ボタン)

日本語文字列をローマ字に変換する。
間違えて途中まで日本語で書いてしまったときとかよくやる。

* 日本語入力中に Ctrl + k

日本語文字列をカタカナに変換する。
たまにカタカナ変換してくれないときにやる。

## スクリーンショット

* ⌘ + shift + ctrl + 4

クリップボードに選択範囲をコピー。
デスクトップなどに保存されず、そのままSlackなどにペーストできるので便利。


# まとめ

ショートカットなどの効率化系は自分は教わる機会があまりなかったなと思い少しだけまとめてみました。
自分の時はこれショートカットないかなというスタンスで調べていた気がします。
【超アバウト注意！！】Let's C++プログラミング

#今回は初心者向けでアバウトな講座です。
今回の講座で

- C/C++言語非常に簡単に使うことができるようになれます。
- C/C++での基本的な書き方が学べます。
- char型の扱い方が学べます。

```chara.hpp
#include <string>

class ZipStream
{
public:
	ZipStream(int val);
	ZipStream(std::string val);
	ZipStream(std::string val, bool zipped);
	~ZipStream();
	ZipStream Zipped();
	ZipStream UnZipped();
	ZipStream operator+(ZipStream Z);
	ZipStream operator+=(ZipStream Z);
	inline std::string Get_Value() {
		return this->values;
	}
private:
	std::string values;
	bool now_zip;
	inline char Reter(int Oh) {
		return (char)Oh;
	}
	inline int Purse(char t) {
		return t & 0xff;
	}
};
```

```chara.cpp
#include"chara.hpp"
#include <array>
#include <sstream>
using sstr = std::stringstream;

ZipStream::ZipStream(int val)
	:values(std::to_string(val))
	,now_zip(false)
{
}

ZipStream::ZipStream(std::string val)
	:values(val)
	,now_zip(false)
{
}

ZipStream::ZipStream(std::string val, bool zipped) 
	: values(val)
	,now_zip(zipped)
{

}

ZipStream ZipStream::operator+(ZipStream Z){
    if((Z.now_zip ^ this->now_zip) == false){
        ZipStream V(this->values + '\n' + Z.values,this->now_zip);
        return V;
    }
    else{
        return *this;
    }
}

ZipStream ZipStream::operator+=(ZipStream Z){
    if((Z.now_zip ^ this->now_zip) == false){
        this->values = this->values + '\n' + Z.values;
    }
    return *this;
}

ZipStream::~ZipStream()
{
}

ZipStream ZipStream::Zipped ()
{
	if (this->now_zip)
	{
		return *this;
	}
	sstr ss;
	for (auto l : this->values)
	{
		ss << std::hex << Purse(l) <<",";
	}
	this->values = ss.str();
	this->now_zip = true;
	return *this;
}

ZipStream ZipStream::UnZipped() {
	if (!this->now_zip)
	{
		return *this;
	}
	std::string ok, ret;
	int k;
	for (auto st : this->values)
	{
		if (st == ',') {
			std::istringstream(ok) >> std::hex >> k;
			ret += Reter(k);
			ok = "";
		}
		else
		{
			ok += st;
		}
	}
	this->values = ret.c_str();
	this->now_zip = false;
	return *this;
}

```

```AbeOut.cpp
#include<iostream>
#include"chara.hpp"
using std::cout;
void AbeOut(int num) {
	ZipStream Z("e5,ae,89,e5,80,8d,e3,81,af,e8,be,9e,e3,82,81,e3,82,8d,", true);
	if (num>0)
	{
		cout << Z.UnZipped().Get_Value() << std::to_string(num) << std::endl;
	}
	else
	{
		cout << Z.UnZipped().Get_Value() << std::endl;
	}
}

int main(void) {
	AbeOut(210);
	AbeOut(0);
}
```

```batch:ターミナル
>>> cl /EHsc About.cpp chara.cpp
```

問題

1. AbeOut(210)の答えを述べよ
2. AbeOut(0)の答えを述べよ
プログラミング講座3

##講座内容
・バグ調査
・ライブラリ起因バグの調査

##バグ調査
コードを書いて、あってるかどうか悩むよりも
さっさと実行して試した方が速いですよね

ブレークポイント無しでデバッグ実行をすれば、Exceptionがあった場合にそのままデバッグでの調査につなげられます

eclipseのショートカットキーF11で前回の実行をデバッグ起動 が便利です

デバッグ中は変数に何が入っているか、処理の順は想定通りか、をしっかりと確認しましょう

Exceptionを豊富に知っていればいるほど、コードを書く際の考慮の幅が増えるので
スタックトレースはしっかりと呼んでおきましょう
注意するべきなのは主にnull、空、境界値です
・そもそも値が存在しないnull
・値は存在するが枠だけで空っぽな場合
・100以上なのか100より上なのか
などですね

また、1行ずつ実行していった場合
ブレークポイントが貼ってあるメソッドにしか潜りません
メソッド内部で別のメソッドを呼んでいる際は、そのメソッドにF3で飛んでから
どこかにブレークポイントを貼って、デバッグを続行しましょう

実装元検索や呼び出し元検索に引っかからない厄介な処理として
抽象メソッドがあります

独自での実装ならメソッド名検索でどうにか追えるかもしれませんが
ライブラリ内部の抽象メソッドは、リソース検索でも引っかからず、継承関係なども追いにくく、かなり厄介ですね
eclipseならCtrl + Tでどこで実装されているのかをみられるので便利です

##ライブラリ起因バグの調査
例えばFilterクラスなどは、doFilterが勝手に呼ばれますよね
ライブラリ既存のフィルタを編集したい場合や、フィルタでどういう処理をしているかを追いたい場合は
使用しているフィルタクラスをどこかにインポートして、new宣言でもしてとにかく書いてみましょう

そして、そこからF3で飛び、doFilterメソッドの実装にブレークポイントを付けます

あとはデバッグ実行したら勝手にそこに止まると思うので、以降F6でステップ実行しつつ
呼び出されているメソッドが見たければF3で飛んでブレークポイントを貼って潜り

と、続けていけば、ライブラリが内部でどういう処理をやってくれているのか追うことができます

場合によってはその実装を丸々コピーして、まったく同じ内容の処理をOverrideし
一部分だけ処理を追加する、とかもできますね

extendsやoverrideはfinalやprivate修飾子に対して無力なので
ライブラリの処理に介入して実装を改造するにはさすがに限度があったりします

finalはどうしようもありませんが、private程度ならリフレクションで無理やりどうにかできたりもしますね

このようなライブラリ改造は、主にフロントからサーバ間のやり取りに対するものが多いかもしれません

サーバ上での処理はjava.langなどの自由度の高いロジック組み立てができるので
あくまで、すでに塗り固められてしまっているフレームワーク実装を上書きする必要がある場合、またはjavadocなどのドキュメントだでは情報が不足している場合にのみ調査するようにしましょう

まじでめっちゃ時間かかります...かなりのクラス、メソッドをまたぐことがほとんどな上に、閲覧可能なソースが取得できない場合もあります
stream in streamで内側のstreamに終端操作を使わないこと

##一度終端させたstreamは再開できない
できないんです

```.java
	public static void asd() {

		List<Map<Long, String>> condition = new LinkedList<>();
		
		Map<Long, String> map1 = new HashMap<>();
		map1.put(new Long(1), "a");
		condition.add(map1);
		
//		Map<Long, String> map2 = new HashMap<>();
//		map1.put(new Long(2), "b");
//		condition.add(map2);
//		
		for (Map<Long, String> a : condition) {
			for(Entry<Long, String> e : a.entrySet()) {
				System.out.println(e.getValue());
			}
		}
		
		List<Long> keys = condition.stream()
				.map(Map::entrySet)
				.map(Set::stream)
				.map(Stream::findFirst)
				.map(Optional::get)
				.map(Entry::getKey)
				.collect(Collectors.toList());
		
		keys.forEach(System.out::println);
		
		List<String> values = condition.stream()
				.map(Map::entrySet)
				.map(Set::stream)
				.map(Stream::findFirst)
				.map(Optional::get)
				.map(Entry::getValue)
				.collect(Collectors.toList());
		
		values.forEach(System.out::println);
	}
```

この、for文の処理を、streamでやったやつを見てみてください
このままではエラーになりません


コメントアウトしてあるところをアクティブにすると...
findFirstからのgetでNoSuchElementExceptionになります

流れとしては
`.map(Set::stream)`
`.map(Stream::findFirst)`
`.map(Optional::get)`
これを、stream中にやっていますね

外枠のリストの中で、内枠のMapがループしている感じ

内側のループでfindFirstを使っているので、Listの中に2つ目の要素が入っていた場合
一度Mapのstreamを終端させてしまったので、もうこれ以上できませんということになります、というか空っぽになります
なのでfindFirstした結果がOptionalのemptyになり、getでExceptionになるわけですね

<b>ループの中でループさせるときにstreamを使う場合、内側のstreamで終端操作を使えない</b>
ということに注意しましょう
[firestore] Error: 7 PERMISSION_DENIED: Missing or insufficient permissions

# 前提
GOOGLE_APPLICATION_CREDENTIALSを利用してサービスアカウントを設定している。

# 問題
firestoreにwriteする際に、タイトルエラーが出て書き込めなかった。

``` firestore.rules
rules_version = '2';
service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}
```

firestore.rulesを見ても、特に問題は見当たらない。

# 解決
以下のコードが原因

``` typescript
import { initializeApp } from 'firebase-admin'
initializeApp({ projectId: "YOUR_PROJECTID" })
```

GOOGLE_APPLICATION_CREDENTIALSを利用して設定している場合、initializeAppで余計な設定は不要

``` typescript
import { initializeApp } from 'firebase-admin'
initializeApp()
```
これでよし。
Railsのソース変更がテスト実行に反映されない

#環境
OS：Windows10
Rails環境：WSL
エディタ&ターミナル：VSCode

#Railsのソース変更がテスト実行に反映されない
[Railsチュートリアル第3章](https://railstutorial.jp/chapters/static_pages?version=5.1#sec-green)のわざとテストを失敗させて、徐々に解消していく作業を行っていた時に、ソースコードの変更が反映されず、チュートリアル通りのエラーメッセージが表示されない現象が起きました。

以下のようなエラーから一切変わらなかったので

```
StaticPagesControllerTest#test_should_get_contact:
NameError: undefined local variable or method `static_pages_contact_url' for #<StaticPagesControllerTest:0x007fffe51b14e8>
    test/controllers/static_pages_controller_test.rb:28:in `block in <class:StaticPagesControllerTest>'
```
その文言で調べたところ同じような人が・・・
[Ruby on Rails チュートリアル３章のテストのバグとその対応メモ](https://qiita.com/miihon_ani/items/1ab1b5733258374efa33)

##Rails、minitestのバージョンを変更しまくる
私の環境ではチュートリアルよりも新しいバージョンのRailsを使用していたので(6.0.2.2)、まさしくこれかな？と思い
参考に、minitest、Railsのバージョンを変更してみるが・・・ダメ。
いろんなバージョンの組み合わせでもダメ・・・。
Rubyのバージョンも変えてもダメ・・・。
チュートリアルと全く一緒のバージョン、gemファイルの内容にしてもダメ・・・。

##キャッシュか？
キャッシュか？と思ってググって

```
Rails tmp:clear
```

```
bin/rails r 'Rails.cache.clear'
```
等を試してみたがダメ・・・。

しまいにはアプリケーションルート直下の`tmp`フォルダを無理やり頑張ってコマンド上から全削除してみたがダメ。
というかRailsが動かなくなり、再インストールするハメに・・・。

`app/enviroment/test.rb`の`config.cache_classes`や`config.action_controller.perform_caching`も`false`にしてみたが変化なし。

この時点で半日くらい潰れた・・・。

なぜか`rails server`でブラウザでアクセスすると、変更は反映されているようでした。

```
rails s
```

##springが原因の可能性
その後もググりまくっていると`spring`というものがrailsコマンドの実行を早めるためにキャッシュしているとかなんとか・・・。
たしかにこの`spring`はgemファイルの中身や`rails t`実行時のコンソール出力内で見かけたなぁ・・・と思い、こいつを停止させてみることに

```
bin/spring stop
```
停止されたか確認するため`bin/spring status`

```
test@DESKTOP-SAU5360:~/sample_app$ bin/spring status
Spring is not running.
test@DESKTOP-SAU5360:~/sample_app$
```
止まっている模様。

この状態から`rails t`でテスト実行したところ
　
　
　
　
　
　
**うまくいきました**

解決まで計8時間くらいかかりました。
~~時間を返して～~~

私の環境が悪いのかな・・・。
そもそもみんなWSLじゃなくCloud9だから、こんなこと起きないか！？

今後もテストを流す際は毎回これをしなきゃいけないのはめんどいなぁ・・・。もう止めておくか。
gemでtestの時に除外すればいいのか！？
Python（anaconda）の開発環境構築手順（SpringToolsSuites ）_2020.6時点


pythonの開発をする事になり、AnacondaをSpringToolsSuitesに導入したため、 記事を書きました。

##Anacondaのインストール
　Anacondaはpythonのディストリビューションです。pythonで開発をする場合、ライブラリをすぐにインストールできるのが便利な点であると理解していますが、pipコマンドだと依存関係のチェックが手間であるところが、condaだと依存関係を自動で解決してくれるというので、こちらを選択しました。
(2020.4時点では、conda3.7が最新でした。)
[　■最新版のインストーラ](https://www.anaconda.com/distribution/)
[　※過去のインストーラはこちらにあります。](https://repo.anaconda.com/archive/)

##Anacondaで仮想環境を作成
　今回はpy37という名前の仮想環境をpython3.7で作成します。（-nは　-nameでもOK）
　作成できたら、activateしておきます。

 　まずは、Anaconda　Promptを起動します。

```
(base)conda info -e
# conda environments:
#   
base                  *  C:\Users\XXXX\anaconda3
(base)$>conda create -n py37 python=3.7
(base)$>activate py37
(py37)$>conda info -e
# conda environments:
#
base                     C:\Users\XXXX\anaconda3
py37                  *  C:\Users\XXXX\anaconda3\envs\py37
```

##Anacondaでライブラリをインストールする。

※プロキシがある場合以下のようにプロキシを設定する。

```
$set HTTP_PROXY=http://ユーザ名:パスワード@プロキシ:ポート
$set HTTPS_PROXY=https://ユーザ名:パスワード@プロキシ:ポート
```
あとは、必要なライブラリをインストールします。

```
$conda install pyinstaller
$conda install -c conda-forge selenium
$conda install -c conda-forge python-chromedriver-binary
・・・など
```

##STSでPythonを使えるようにする。
　①STSを起動します。
　　└ヘルプ　→Eclipseマーケットプレイス　→pyDevで検索
　　pyDevがヒットしたらインストールします(python IDE for Eclipse 7.5.0※2020.4時点)。

　②pythonインタプリターの設定。
　　└ウインドウ　→設定　→pyDev→pythonインタプリター
　　ダイアログが開くのでインタプリタ名とインタプリター実行可能ファイルを設定します。
　　インタプリタ名：py32
　　インタプリター実行可能ファイル：　C:\Users\XXXX\anaconda3\envs\py37\python.exe　

　ここまですれば、プロジェクトエクスプローラーから新規でPydev→Pydevプロジェクトを選択できるようになっているはずです。

##STSでファイルの実行
　適当なPYファイルを作成します。サンプルはhelloworldです。
　<img width="303" alt="py1.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/7dc6b412-0c23-1675-1356-e660e2f328c9.png">

　作成後、右クリックから実行→2 python 実行を選択します。
　<img width="298" alt="py2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/cabf8f5a-1d4e-4399-9224-3c562e24df45.png">
　
　コンソールにhelloworldが出力されました。
　<img width="319" alt="py3.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/41d5de92-cf1b-a6e4-4c6d-1e97a9d3043a.png">

##STSでファイルのデバッグ実行

　今度は作成後、右クリックからデバッグ→2 python 実行を選択します。
　この時点でブレイクポイントを打っておきます。
　<img width="456" alt="py4.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/8c3a01d4-8aa4-7dfd-98a9-9862b8286a77.png">

　パースペクティブが切り替わってデバッグになり、ブレイクポイントで止まっています。
<img width="288" alt="py5.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264141/878bfb04-51b3-55ba-a331-93dfa3bcd22c.png">


　あとは、javaなんかでの開発と同じ感覚で利用できると思います。

---
 こちらの記事を参考にさせていただきました。有難うございました。
[【Eclipse×Python】Python開発環境の構築手順]
(https://takilog.com/eclipse-python-environment/)
[【初心者向け】Anacondaで仮想環境を作ってみる]
(https://qiita.com/ozaki_physics/items/985188feb92570e5b82d)
[　Anaconda備忘録](https://qiita.com/tsugar/items/af716954e8e1b94e9965)
pygletをmulti threadで実行するとexceptionとなる場合はmulti processを使うと良い

## Background
強化学習でエピソードを蓄えるために、OpenAI GymのCarRacing-v0をmulti threadを用いて実行しようとしたところexceptionが発生してしまった。
Exceptionの内容はこちら。CarRacing-v0のwindowを準備するためのpygletがマルチスレッドで実行できない模様。

```
Exception has occurred: RuntimeError
EventLoop.run() must be called from the same thread that imports pyglet.app
```

## Multi process
いろいろ調てみてもmulti threadでpygletを実行する方法が見つからなかったが、代わりにmulti processを使ってみたところすんなり実行できた。

Pythonではmultiprocessingで実現でき、使い方はほぼthreadingと一緒。

## パラメータ受け渡しについて
私はmain processでGPUを用いてagentのtrainingに専念させて、sub processでエピソードを生成するようにしていた。(Sub processはdaemonとしておく)
Main processで学習したパラメータはPythonのmultiprocessingのドキュメントで勧められている通りQueueを使ってsub processに渡していたが、tensorを直接渡すようにしているとmain processを終了させてもdaemonにしたはずのsub processが終了されなくなってしまった。
Parameterを渡す際はnumpy arrayなどに変換して渡してあげると、daemon processもmain processと一緒に終了してくれるようになった。
【GitHub】featureブランチを切ってpushする

##はじめに
前回[【GitHub】git-flowについて](https://qiita.com/yukachin0414/items/09ce61f23081cb813ed5)について解説しました。
今回は実際にfeatureブランチを切ってpushしたいと思います。

##featureブランチを切ってpushする

###featureブランチの作成
```php:command
//現在の位置がdevelopブランチか確認
$ git branch 
//feature作成
$ git branch feature/(任意の名称) 
//移動
$ git checkout feature/(任意の名称) 

//※feature作成と移動は合わせて行うこともできます
$ git checkout -b feature/(任意の名称) 
```

###改修後のpushまで
```php:command
//サブディレクトリも含めたファイルをインデックス領域へアップ
$ git add .
//ローカルリポジトリへコミット
$ git commit -m "message" 
//feature/(任意の名称)ブランチの内容をoriginへアップロード
$ git push origin feature/(任意の名称) 
```

##さいごに
ブランチ切ってpushするところまでわかれば基本的なGitHubの操作は問題ないかなと思います。
Dataikuを使って、プレゼンで使用するデータをサクッと取り出す 

プレゼンの際、実際のデータを示しながら説明することってありませんか？
私は時々あるのですが、その際にプログラミングして必要なデータを取り出すのがめんどくさいと感じていました。

ですが、Dataiku DSSを使うと簡単にできることがわかったので紹介します。大まかな流れは次の通りです。

1 LabのVisual analysisを使う。
2 そして、ScriptのProcessors libraryを使い、必要なデータを取り出す。 
3 取り出したデータをダウンロードする。

[東京都のオープンデータカタログサイト](https://portal.data.metro.tokyo.lg.jp/)から[宿泊施設](https://catalog.data.metro.tokyo.lg.jp/dataset/t000029d0000000003/resource/a40ecdb3-c768-45b5-af87-26431cf41019)に関するデータをダウンロードして、上記操作を行ってみます（下記アニメーション参照）。

![(15) Flow _ Dataiku - Google Chrome 2020-04-18 17-20-28_3.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/531352/66aeca28-c3f6-3d78-3359-c6f45862dff9.gif)

上記アニメーションでは、まず、取り出したい4列（施設名、都道府県名、市区町村名、町丁目名）以外の列を削除しています。次に、市区町村名に「豊島区」を含む行以外を削除しています。そして、最終的に残った行をCSVファイル形式でダウンロードしています。

プログラムするよりも素早くデータを取り出せ便利に感じています。
zoomの入室管理における注意点まとめ

オンライン会議やイベントの開催が多くなっている昨今ですが、zoomを使われる方も多いと思いますのでzoomを使ったオンライン会議やイベントでの入室管理における注意点をまとめてみました。

## 参加URL、ミーティングID、パスワードの共有時に気をつけること

勝手にミーティングに入ってくる、いわゆる「zoom Bomber」を避けるためには、参加URL、ミーティングID、パスワードなどの情報を参加者のみに共有することが望ましい。具体的には、以下の点があります。

（以下の内容は、参加者も接続先情報をSNSなどで公開しないようにしてもらうことが前提です）

- 参加者だけがみられるクローズな方法で接続情報を共有する。
    - Peatixなどのイベントサイトを使い、参加者へのメール送信機能で接続情報を連絡する。 
これが一番手間がかからず確実かなと思います。中にはメールを見てくれていない参加者もいるので、何度かリマインドした方が良いでしょう。
    - Facebookイベントの場合は「非公開」イベントにし、イベントページ内で共有する。  
    この場合、イベント参加者を招待制になるため集客時の手間が生じます。
    - 「公開」Facebookイベントの場合は、参加者のメッセージグループを作ってメッセージでシェアする。  
    ぶっちゃけ面倒と思います。が、しかしFacebookイベントであれば公開であっても、検索などで見つかることがないので、まだ接続先情報は漏れにくいかもしれません。

## 待機室利用時に気をつけること

待機室とは、ミーティングに接続してきた参加者がミーティングに参加する前にホストの承認が必要になる機能で、ランダム生成のミーティングIDを使う場合はオプションですが、パーソナルミーティングIDの場合は必須となります。

これを使うことで接続してきた人を確認した上でミーティングに参加させることができますが、以下の問題点があります。

1. 確認・承認の手間が増える。  
当然ですが、ひとりひとり確認して承認しなければならないので、ホストの手間が増えます。共同ホストが承認できれば、運営スタッフを共同ホストに指名して手伝っって貰えばいいのですが、今のところ共同ホストには入室者の承認権限はないようです。ここは仕様を変えて欲しいところです。
1. zoom上の名前で個人を特定できない場合がある。  
zoom上で表示される名前が本名であればいいのですが、そうでない場合は事前に参加申し込みしてきた人かどうかを確認できないことがあります。あらかじめ本名やイベントページで参加申し込みした時のIDや名前にしておいてもらえれば照合できますが、そこまでやってもらうのはなかなか難しいかもしれません。

待機室は少人数の内輪のミーティングでは使いやすいかもしれませんが、事前申し込み制であっても不特定多数の参加者に対するオンラインイベントでは運用が難しいかもしれません。

## ミーティングのロック

zoomにはミーティングのロックという機能があり、ロックするとそれ以降は他の参加者が接続できなくなります。すでに参加者が揃ったことが確認できている場合は、ロックをかければzoom Bomberの侵入をふせぐことができます。

ただし、中には一旦入室した後（カメラ、マイクの不調などで）接続し直す参加者がいるケースもあり、そういうケースが発生した場合の対応ができないというリスクはあります。

## 絶対さけなければならないこと

接続先を検索できる場所に書くのは絶対に避けてください。例えば、Twitterのタイムラインなどがそれにあたります。zoom BomberはこういうところにzoomのURLや接続情報が流れてくるのを見つけて侵入してくるようです。

以前、自分のパーソナルミーティングIDをTwitterに流したところ、何名か英語名のアカウントで接続が試みられました。もちろんスルーしましたが。

## 結論
というわけで「Peatixなどのイベントサイトを使い、参加者へのメール送信機能で接続情報を連絡」し「待機室を使用しない」というのが、現実的な落とし所かもしれません。

## 参考
この数ヶ月でユーザーが20倍になったと言われるzoomですが、一方でセキュリティ上の問題が指摘される自体になり、いくつかのセキュリティ対策が取られました。その対策の中の入室管理に関するものとして以下のものがあります。

1. ランダム生成のミーティングIDを使った場合、パスワードの設定が必須になった（待機室の有無はオプション）。  
→zoomはミーティングIDが9桁の数字で決まる仕様のため、パスワード無しの設定だと適当な数字を入力しても実在する会議に接続できる可能性があるため、数字の
2. パーソナルミーティングID（ユーザーごとの固定のID）を使った場合は待機室が必須（入室時にホストの承認が必要）になった。  
→パーソナルミーティングIDは固定であることがメリットなのでパスワードは必須にせず、その代わりに待機室を必須としてホストに確認してもらおうという意図と思われる。
React axiosを使ってPOSTメソッドにヘッダーをつけてリクエストする

## axios
ざっくり説明するとnodeからHTTPリクエストを送るためのライブラリです。
https://www.npmjs.com/package/axios

詳しい説明や使い方は、下記リンクを参照ください。
https://qiita.com/reoisym/items/245e3cdedc194a9f4062

今回は、axiosのなかでも、POSTメソッドにヘッダーをつけてリクエストする方法を紹介します。

## コード

```tsx:sample.tsx
import axios from "axios";


export function HttpAccess(): any {
  //リクエストに付加するヘッダーの定義
  const headers = {
            'Content-Type': 'application/json',
            'any-header': '付加したいヘッダー'
  }

  axios.post(url, data, {headers: headers});

}
```

上記の方法で、POSTメソッドにヘッダーをつけてリクエストすることができます。

参考になれば幸いです！
rubyの気づきにくい代入 やばい or and

# 問題

単純に`and`、`or`を代入で使うと死ぬ

# 例

```rb
x = false or true # => true なのに ...
p x # => false !!!!

x = true or false # => true
p x # => true
```

```rb
x = false and true # => false
p x # => false 

x = true and false # => false なのに ...
p x # => true !!!!
```


# なぜか

`and`、`or`は`=`より[優先順位が低い][1]
![演算子式__Ruby_2_7_0_リファレンスマニュアル_-2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/16757/fb81f2cb-2764-86c7-dff1-d76b8e4a32a0.png)


```rb
x = false or true
# は (x = false) or true と解釈されるので ...
```

# 回避方法

```rb
x = (false or true)
x = false || true

x = (false and true)
x = false && true
```




[1]: https://docs.ruby-lang.org/ja/latest/doc/spec=2foperator.html
credentials.yml.encの使用法

環境変数設定にcredentials.yml.encを使用しました。
お問い合わせフォーム作成のためにGメールアドレスと２段階認証のパスワードが必要だったので、環境変数に設定しました。

参考
https://qiita.com/akizora/items/936f57dd2d3cb11fc840

## credentials.yml.encの編集
ターミナル

```
$ EDITOR="vim" bin/rails credentials:edit
```
iで入力モードになります。

## 認証情報を記載
ターミナル

```
# aws:
#   access_key_id: 123
#   secret_access_key: 345

　g_mail:
    g_mail: Gメールアドレス
    g_pass: ２段階認証パスワード

# Used as the base secret for all MessageVerifiers in Rails, including the one protecting cookies.
secret_key_base: 8be8e637d755f79c799048bed8be0c...
```
：の後には必ず半角スペースを入れてください。
escキー　:wqで終了

## 入力の確認
ターミナル

```
$ rails c

irb(main):001:0> Rails.application.credentials.g_mail[:g_mail]
=> Gメールアドレス

irb(main):002:0> Rails.application.credentials.g_mail[:g_pass]
=> 2段階認証パスワード

```
確認ができればOKです。

## コードの入力

```rb
  config.action_mailer.delivery_method = :smtp
  config.action_mailer.smtp_settings = {
      :address => "smtp.gmail.com",
      :port => 587,
      :domain => "gmail.com",
      :user_name => Rails.application.credentials.g_mail[:g_mail], # 送信先アドレス
      :password => Rails.application.credentials.g_mail[:g_pass], #2段階認証パスワード
      :authentication => :plain,
      :enable_starttls_auto => true
  }
```

こんな感じでセットができます。

## 最後に
環境変数の設定は使用頻度も多いので、習得できてよかったです。
ラズパイでUSBのWiFiドングルを刺した時にオンボードの物を無効化する方法

ラズパイでWiFiドングルを刺したときに、WiFiドングルの方で優先して通信するようにしたい。
ただし、WiFiドングルが刺さってないときは、ラズパイオンボードのWiFiモジュールを使うようにしたい。

こんな時に使える方法です。

# やること

やるべきことは2つ。

- `/etc/dhcpcd.conf` に優先度情報を記述
- `/etc/udev/rules.d/70-persistent-net.rules` でNICのデバイス名(wlan0, wlan1とか)を固定

# `/etc/dhcpcd.conf` に優先度情報を記述

今回は、wlan0をオンボードのWiFiモジュール、wlan1をUSBドングルのWiFiとします。
ファイルの末尾に次のような行を追記して保存してください。
metricの値が小さいほうが優先されます。

```
interface wlan1
    metric 201
interface wlan0
    metric 202
interface eth0
    metric 300
```

# `/etc/udev/rules.d/70-persistent-net.rules` でNICのデバイス名(wlan0, wlan1とか)を固定

次に、`/etc/udev/rules.d/70-persistent-net.rules`を新規作成し、次のようにします。

```
SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="XX:XX:XX:XX:XX:XX",NAME="wlan0"
SUBSYSTEM=="net",ACTION=="add",ATTR{address}=="YY:YY:YY:YY:YY:YY",NAME="wlan1"
```

ここで、wlan0は、USBドングルを抜いて`ifconfig -a`をした時のwlanのetherを、wlan1にはUSBを刺した時に追記されるwlanのetherを指定してください。

あとは再起動すれば設定が反映されています。

# 参考
https://raspberry-projects.com/pi/pi-operating-systems/raspbian/network-settings/routing-table
https://qiita.com/gm_kou/items/e4ec250557628958a6b4
istio-proxy(Envoy)を通過するhttp  accessログを出力させる(Pod個別設定)

###istioのconfigmapを確認してみます
```
kubectl edit configmap istio -n istio-system
```
###事前確認
```yaml

accessLogFile: ""   # ここを修正します。
accessLogFormat: ""
accessLogEncoding: 'TEXT'
```

###修正後
```yaml
accessLogFile: "/dev/stdout"
accessLogFormat: ""
accessLogEncoding: 'TEXT'
```

###ついでにistio-proxy側のログレベルも変更しておきます
```
istioctl proxy-config log --level http:info -n [Namespace] [podName] -c istio-proxy
```

###その後に実際にログを確認してみます
```
kubectl logs [podName] -n [Namespace] -c istio-proxy -f
```
- -f (tail -fと同じモード)


###出力イメージ(istioのバージョンによって異なる(?)
`
[2020-04-18T06:42:18.630Z] "GET /nginx HTTP/1.1" 200 - "-" "-" 0 612 4 1 "10.1.10.1" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.92 Safari/537.36" "00c83e93-0eb0-920f-b059-0a5120826b7c" "localhost:31380" "10.1.10.104:80" outbound|80||nginx.default.svc.cluster.local - 10.1.10.84:80 10.1.10.1:39754 - -
`
###気になる点
アクセスして即座にログ出力されるかと思いきや、時間差で出力される。
1分〜2分は待つのはなぜ？単なるI/Oの負荷とは思えない。

4/23 追記
@yteraoka さんコメントありがとうございます！
コメントに記載頂いたEnvoyのページにこのような記述が。
`Asynchronous IO flushing architecture. Access logging will never block the main network processing threads.`
メインのネットワーク処理を邪魔するようなログ出力はしないぞ。という設計みたいですね。
Envoy（サイドカー）のネットワーク処理が忙しくなるほどログへの吐き出しは遅れる......ということに。
laravel-mix yarn run dev で vue-template-compiler ライブラリが依存してた

## 環境

- PHP 7.4.4
- Laravel 7.5.1
- Node 12.16.1
- yarn 1.22.0

```json:package.json
{
    "private": true,
    "scripts": {
        "dev": "yarn run development",
        "development": "cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js",
        "watch": "yarn run development -- --watch",
        "watch-poll": "yarn run watch -- --watch-poll",
        "hot": "cross-env NODE_ENV=development node_modules/webpack-dev-server/bin/webpack-dev-server.js --inline --hot --config=node_modules/laravel-mix/setup/webpack.config.js",
        "prod": "yarn run production",
        "production": "cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
    },
    "devDependencies": {
        "axios": "^0.19",
        "cross-env": "^7.0",
        "laravel-mix": "^5.0.1",
        "lodash": "^4.17.13",
        "resolve-url-loader": "^3.1.0",
        "sass": "^1.15.2",
        "sass-loader": "^8.0.0"
    }
}
```

## 問題

```shell-session
$ yarn run development
$ cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js
 	Additional dependencies must be installed. This will only take a moment.
 
 	Running: npm install vue-template-compiler --save-dev --production=false
 
/bin/sh: npm: not found
```

私の環境では`npm`コマンドは入ってないのでエラーとなりました。
`laravel-mix` は `vue-template-compiler` に依存してるのか...🤔
なんだか気持ち悪いがそれならそれで初めから同梱して欲しい。。

```shell-session
$ yarn add vue-template-compiler --dev --production=false
```

`vue-template-compiler` 入れて解決。
まぁないんだからそうですよね。

```shell-session
$ yarn run dev
yarn run v1.22.0
$ yarn run development
$ cross-env NODE_ENV=development node_modules/webpack/bin/webpack.js --progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js
98% after emitting SizeLimitsPlugin

 DONE  Compiled successfully in 6532ms                                                                                       5:09:41 PM

       Asset     Size   Chunks             Chunk Names
/css/app.css  0 bytes  /js/app  [emitted]  /js/app
  /js/app.js  592 KiB  /js/app  [emitted]  /js/app
Done in 18.62s
```

## 参考

- https://github.com/JeffreyWay/laravel-mix/issues/1891
【UE4】AssetRegistryなどでブループリントクラスを取得・作成する方法

# 本題の主旨
ブループリント内で使用できる AssetRegistry で、任意のコンテンツディレクトリからアセットを取得することが可能ですが、この方法でブループリントクラスを取得したい場合に問題が発生します。
具体的に説明すると、 AssetRegistry は「アセットオブジェクト」を取得するため、ブループリントを取得するということは、「ブループリントアセット（UBlueprint クラス）」として取得されるということ。
これを解決する方法を紹介します。

UE4.24での内容です。

## 方法
やり方は（C++を使えば）簡単。
以下のようなブループリント公開関数を用意するだけです。

```cpp:BlueprintUtilityLibrary.cpp
bool UBlueprintUtilityLibrary::GetClassFromBlueprintAsset(UObject *BlueprintAsset, UClass *&Class)
{
	if (UBlueprint *BP = Cast<UBlueprint>(BlueprintAsset))
	{
		Class = BP->GeneratedClass;
		return true;
	}
	return false;
}
```

UBlueprint クラス自体はブループリント非公開のクラスのため、ブループリント内ではアクセスできません。上記の関数ではその部分だけを記述しています。
渡されたブループリントアセットから内部で定義された実際のブループリントクラスを取り出し、それを返すだけです。

使い方は以下のような感じになります。
![ss.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/512539/622de9e7-8a24-7881-100c-5a5dcabbdd41.jpeg)

AssetRegistry に限らず、アセットオブジェクトを取得する処理にこの関数を使うことが出来るので、意外と使える幅は広いと思います。
pandasで重複したカラムを持つcsvを読み込んで

教えてください。
pandasでcsvファイルを読み込もうとしています。
csvファイルのカラム名には完全に名前が重複したものがあり、その行のどちらかに値が記載されているものがあるとします![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/426068/7b357270-5a95-83fc-8eb6-2f2f88b6a531.png)
このまま、pandasで読み込むと"重さ", ”重さ.1"となります。
これは、簡単な例なのですが、実際には重複したカラム名は数十列あって、panndasで読み込んでから、一つ一つのカラム名にアクセスするのは、非常にめんどくさいです。これらのカラムを一つに統一して、新しいデータフレームを作る方法を教えてください。
一つの行は同じ名前のカラムにはどちらかしか記載されていません。
Windows10でCentOS8を構築してみる1

## Windows10でCentOS8を構築してみる　その１  

### win10環境でcentos8の構築ができるのか
そもそもやってみようと思ったけどできるのかどうか…?(ガチ初心者)  

色々調べてみたところ…  
→[CentOSをWindowsで使う方法まとめ -エンジニアの入り口](https://eng-entrance.com/linux-centos-windows)  
このサイトがわかりやすかったような気がする

### VirtualBoxのインストール
VirtualBoxとはなんぞやと思いましたが


"仮想化ソフト界では超有名"
  
と私は認識しました。多分。  

早速Oracle VM VirtualBoxをインストールしてみようと公式サイトに…
https://www.virtualbox.org/

<img width="808" alt="コメント 2020-04-18 165249.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/06266f58-4968-a433-c71d-d51002905474.png">


はい、英語。英語苦手なんですよね…。

とりあえずダウンロードしてみる

<img width="947" alt="コメント 2020-04-18 165503.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/f65b3e83-a296-96ec-878e-a69a4aaf50d2.png">

最新版が 
`VirtualBox 6.1.6 platform packages`
windows環境なんで、windows hostsをインストール。

ダウンロード終わったので起動してみる。
<img width="371" alt="コメント 2020-04-18 170105.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/7a9aac16-895a-408d-c4af-299667272f68.png">
特になにもないのでNEXT

<img width="371" alt="コメント 2020-04-18 170142.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/854aa796-be7d-b052-ec01-23523f1e6202.png">
セットアップに関して色々出てきました…カスタマイズですかね。
今回はデフォルトでいきます。

<img width="371" alt="コメント 2020-04-18 170512.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/2c88b129-a8dc-ebfb-643a-440ad275e41b.png">
・スタートメニューにショートカット作るか？
・デスクトップにショートカット作るか？
・クイックランチャーバーにショートカット作るか？
・ファイルを関連付けするのか？
と聞かれていますので、個人で適当に設定してください。僕はよくわからなかったのでととりあえずデフォルトで・・・。

<img width="371" alt="コメント 2020-04-18 170536.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/ef113830-e9b0-ef6f-faf8-78ab9d9f0867.png">
ネットワークに関する警告ですね。
インストールする際にネットワークが切断されるけど大丈夫？って聞かれてるのでYESで次に進みます。

<img width="371" alt="コメント 2020-04-18 170558.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/656a05d7-8774-ab10-467b-729e8d97b168.png">
インストールして終わったら下の画面が
<img width="371" alt="コメント 2020-04-18 170613.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/086f72cb-db78-be8a-4360-ada46f148c01.png">

はい。とりあえずVirtualBoxインストールできました。

### VirtualBoxインストール完了！
<img width="499" alt="コメント 2020-04-18 171611.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/621302/583668e7-e9ef-9dff-5a67-c76c079ca8f2.png">

うーん可愛いペンギンが。タックスっていうらしい。
[タックス -Wikipedia](https://ja.wikipedia.org/wiki/%E3%82%BF%E3%83%83%E3%82%AF%E3%82%B9)

では、次回はVirtualBoxにCentOSを入れて実際に起動してみようかな。
aws-cli v2でECRへget-login-passwordする

## 背景
* Kubernetes上で運用するアプリケーションを作成していて、コンテナレジストリが必要になったため。
* 1GBまで無料らしいのでおそらく料金かからずに済むだろうという想定
* 手順書通りに実行してもログインに失敗しまくったので自分なりに解決した方法をメモ

## 事前準備
1. [IAMユーザの作成](https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/id_users_create.html)
1. [AWS CLI v2のインストール](https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/install-cliv2.html)

## ログイン成功までの流れ
1. ECRリポジトリを作成
2. リポジトリ一覧画面で1で作成したリポジトリを選択し、「プッシュコマンドの表示」ボタンを押下する
3. aws configureを実行し、事前準備で作成していたユーザを登録する
4. 2で表示されたコマンドを手元のターミナルで実行

## ECRにイメージをpushする
以下のコンテナイメージがあったとする

|REPOSITORY|TAG|
|---|---|
|hello-world|latest|

### リポジトリーとタグ付
```
docker tag hello-world:latest <リポジトリID>.dkr.ecr.<リージョン>.amazonaws.com/<リポジトリ名>:hello-world
```

### ECRへpush
```
docker push <リポジトリID>.dkr.ecr.<リージョン>.amazonaws.com/<リポジトリ名>:hello-world
```
vscodeで任意の行をセレクトして、githubへのリンクを簡単に生成する方法

コードのレビューをしていたり、わからないところがあったときに、対象箇所のgithubのリンクを送って質問したい時ありますよね。
以下のvisual studio codeのプラグインは、セレクトした行のgithubへのリンクを簡単に生成できて非常に便利です。

[Github Linker](https://marketplace.visualstudio.com/items?itemName=gimenete.github-linker)


![alt](https://github.com/gimenete/github-linker/raw/master/gifs/github-linker.gif)


**注意**
残念ながら、このプラグインはgithub enterprizeのリンクは生成できません。
この問題を解決するための[プルリク](https://github.com/gimenete/github-linker/pull/11)がありますが、まだマージされていないです。(openされたのは2020/02)
上のプルリクがマージされたものをパッケージ化したのでよろしければご利用ください。(インストール方法は以下のリンクに記載しています)
[パッケージ](https://github.com/shrft/github-linker/releases/tag/v1)
python multiprocessing の使い方（続） Pool編

pythonでmultiprocessingの使い方を調査しています。
先ほど投稿した記事の調査の続き。別プロセスで動かしたい関数をProcess で一つ一つ起動するのでなく、まとめて実行してくれる関数Pool を利用します。

- 並列処理で使用するコアの数（上限数）を指定できる。
- 指定した処理を別コアで動かしてくれる。感じ。
- 並列処理をしたい関数が同じで引数が違うだけの時、Pool　を使って簡単に書ける。

を確認しました。

### テストコード

- CPUの数は ```cpu_count()``` で取得できる
- ```Pool(num_cpu) ``` で Pool のインスタンスを作り、```map(method, iterable_arg)``

```python

from multiprocessing import Pool, cpu_count
from time import sleep
from os import getpid, getppid
from numpy import exp, log

def f(args):
    print("[{}---{}] args {}".format(getpid(), getppid(), args))
    if isinstance(args, dict):
        y = args["x"]
    elif isinstance(args, int):
        y = args
    retValue =0.0
    try:
        sleep(1)
        for i in range(1000000):
            retValue = retValue/float(i+1) + log(exp(y * y + 1) - 0.1)
        print("here=", 100/0.0)
    except Exception as e:
        print("[{}---{}]  {}".format(getpid(), getppid(), e))
        raise e
    finally:
        print('[{}---{}] return: {}'.format(getpid(), getppid(), retValue))
        return(retValue)

if __name__ == "__main__":
    print("main pid={} cpu_count={}".format(getpid(), cpu_count()))
    p = Pool(6) # プロセス数を指定する
    try:
        result = p.map(f, [{"x":1}, 2, 3, 4, 5, 6, 7, 8, 9, 10, -1, -2, -3, -4, -5, -6, -7, -8, -9, -10])  # リストで引数を指定する
        print(result)
    except Exception as e:
        print("main", e)
```

### 実行結果

ちゃんとＣＰＵを分けて使ってくれています。８コアのＰＣですが、```Pool(10)``` としてもエラーは出ません。8個すべてを使って全力で処理してくれているようです。

![コメント 2020-04-18 163925.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294040/9bd5b77f-d51a-3a70-6cdf-48c620b51f95.jpeg)


他に気が付いたこと。基礎知識が無いので実験的に学んでいます。汗;

- プロセスＩＤは再利用されている。（ので、関数の実行のunique な識別には利用できませんね。）
- 発生したException は親プロセスではキャッチされない。（そりゃそうか）
- ```map```で実行させる関数の引数は、型が違ってもＯＫ。map はIterable なもので、実行させる関数できちんと処理をしていれば。

またCPU数については、ドキュメントには
```multiprocessing.cpu_count()``` については、APIの説明で

> This number is not equivalent to the number of CPUs the current process can use. The number of usable CPUs can be obtained with len(os.sched_getaffinity(0))

と書かれていましたが、私が実行したときは、```os.sched_getaffinity(0)```はいつも ```{0, 1, 2, 3, 4, 5, 6, 7}``` でした。CPUの割り当て方とか何か実装方法があるのかな。

### 参考にさせていただいた情報

- 実は記事の一番最初にPool の使い方を紹介されている。https://docs.python.org/3/library/multiprocessing.html 
- 実際に使うときの不都合等についての情報も。https://qiita.com/yukitaka13-1110/items/2580b4fc6c8a30d34661 
 
- 並列処理 https://qiita.com/studio_haneya/items/1cf192a0185e12c7559b 
- こちらではmultiprocessing.py のソースコードを読まれていました。https://qiita.com/bananaumai/items/48ee1b4b069a5c17bc6f

来週、何とかなるといいな。
(2020/04/18)

追記(2020/04/18 17:40)
- よく読むと、Pool を使うときは``` with Pool(processes=4) as pool: ``` としたほうが良いみたい。with を抜けるときにPool のprocessが close されるみたい。
@csrfを記入したのに419エラーになる

#解決方法
formタグの中に"＠csrf"を記入。
解決。

```php

<form action="aaa">
  @csrf
  <label for="xxx" >記入欄</label>
  <input type="text" name="xxx" >
  <input type="submit" >
</form>

```