OmniAICreator/Qiita-1.07M huggingface dataset:
TypeScriptの@typesパッケージをtypesyncで自動管理する

地味に面倒な型定義パッケージの追加。
自動で入れてくれないかな〜と思ったことはありませんか

今回はそんな悩みを解決してくれるパッケージをご紹介します。

# typesync
[GitHub - jeffijoe/typesync](https://github.com/jeffijoe/typesync)
![preview](https://github.com/jeffijoe/typesync/raw/master/typesync.gif)
> Install missing TypeScript typings for dependencies in your package.json.

package.jsonを見て足りない型定義パッケージがあれば自動で追加してくれるパッケージです。

# インストール
さっそくインストールしましょう

```shell
$ yarn add -D typesync

# もしくは
$ npm install -D typesync
```

あとはpreinstallで実行するように設定するだけです

```diff:package.json
  "scripts": {
    ...
     // 初回インストール時にはtypesyncがないので || : を付け加えてエラーを無視します。
+    "preinstall": "typesync || :"
  }
```

もしうまく動かない場合はpostinstallに設定します。
なお、postinstallの場合はpackage.jsonが変更されるだけなので、再度インストールを叩く必要があります。

```diff:package.json
  "scripts": {
    ...
+    "postinstall": "typesync"

     // @types追加後に自動インストールする場合は
+    "postinstall": "typesync && yarn install --ignore-scripts"
     // もしくは
+    "postinstall": "typesync && npm install --ignore-scripts"
  }
```


# 使ってみる
試しに   [react-redux-realworld-example-app](https://github.com/gothinkster/react-redux-realworld-example-app) というプロジェクトでtypesyncを使ってみます

```shell
$ yarn
yarn install v1.22.4
$ typesync | :
⠴  Syncing type definitions in package.json...
[1/4] 🔍  Resolving packages...
[2/4] 🚚  Fetching packages...
[3/4] 🔗  Linking dependencies...
[4/4] 🔨  Building fresh packages...

success Saved lockfile.
✨  Done in 6.63s.
```

インストール後

```diff:package.json
  "devDependencies": {
    ...
+    "@types/history": "^4.7.6",
+    "@types/marked": "^0.7.4",
+    "@types/prop-types": "^15.7.3",
+    "@types/react": "^16.9.35",
+    "@types/react-dom": "^16.9.8",
+    "@types/react-redux": "^5.0.21",
+    "@types/react-router": "^4.4.5",
+    "@types/react-router-dom": "^4.3.5",
+    "@types/react-router-redux": "^5.0.18",
+    "@types/redux-logger": "^3.0.7",
+    "@types/superagent": "^3.8.7",
  }
```

いい感じに追加されました。

もう一つ、 [vue-realworld-example-app](https://github.com/gothinkster/vue-realworld-example-app)  でも試してみます。

```diff:package.json
  "devDependencies": {
    ...
+    "@types/babel-core": "6.25.6",
+    "@types/babel__core": "^7.1.7",
+    "@types/babel__preset-env": "^7.9.0",
+    "@types/marked": "^0.7.4",
+    "@types/node-sass": "^4.11.1",
  }
```

ちゃんと追加されてますね
vueの型定義は本家に含まれてるのでスキップされたようです。

# 詳細設定
基本的にはこのままでも動くのですが、 `.typesyncrc` というファイルを追加することで `@types` を更新されたくないパッケージを指定することもできます。

```json
{
    "ignorePackages": ["react", "nodemon"]
}
```

詳しい使い方などは [こちら](https://github.com/jeffijoe/typesync#usage) を参考にしてください。

# 仕組み
結構シンプルな仕組みで動いています。

1. すべての@&#xFFF0;typesパッケージの情報を取得
2. package.jsonと照らし合わせる
3. いい感じに@&#xFFF0;typesパッケージをpackage.jsonに反映

ここで素晴らしいのが、

- できるだけ近いバージョンのものをsemver準拠で入れてくれる
- 型定義がすでに含まれているパッケージはスキップ
- 参照しなくなったパッケージの分は削除してくれる

ですね。

なお、@&#xFFF0;typesパッケージ情報は[TypeScript Types Search](https://microsoft.github.io/TypeSearch/)で読み込まれている[JSONファイル](https://typespublisher.blob.core.windows.net/typespublisher/data/search-index-min.json)を取得しているようです。



# まとめ
考えることが1つ減るので地味に嬉しいですね。

皆さんも型定義管理のちょっぴり無駄な時間から解放されましょう！
Nix on GitHub Actions in 2020

Chances are, you have now been exposed to some various projects on GitHub that use GitHub Actions, or you know of some various projects that use Travis or some other solutions that want to switch. It's understandable, given that many projects end up wasting hours, days, and weeks on CI setups that don't work, are unreliable, and/or are just too slow to provide meaningful feedback. Well, the last part isn't likely to be solved as long as you use someone else's basement toasters, but maybe we can more easily make it so that we can run the same build locally as we do in CI? To achieve this, I like to use Nix shell scripts.

For a while, installing Nix on GitHub Actions was kind of terrible. You could try running the installation script, but you would very readily run into segfaults and other nice failures running on GitHub's toasters. Thankfully, Domen from Cachix has been quite persevering in getting Nix to work on GitHub actions, so there is a working solution for that in `install-nix-action`: https://github.com/cachix/install-nix-action

## Example setup

Say you wanted to have rustup (https://rustup.rs/) in a Nix shell to work locally and to also have available on GitHub actions. We can set up a `shell.nix` like so:

```nix
{ pkgs ? import <nixpkgs> {} }:
pkgs.mkShell {
  buildInputs =
    builtins.attrValues {
      inherit (pkgs) rustup;
    };
}
```

Then we can make an executable script `test` that will be interpreted by Nix shell.

```bash
#!/usr/bin/env nix-shell
#!nix-shell shell.nix -i bash

rustup update stable
cargo build
```

We can try running this locally:

```bash
$ ./test
info: syncing channel updates for 'stable-x86_64-unknown-linux-gnu'

  stable-x86_64-unknown-linux-gnu unchanged - rustc 1.43.1 (8d69840ab 2020-05-04)

    Finished dev [unoptimized + debuginfo] target(s) in 0.00s
```

Then we need to define a workflow that will use this in GitHub actions using `install-nix-action`. In my case I put it in `.github/workflows/test.yml`:

```yml
name: "Test"
on:
  pull_request:
  push:
jobs:
  tests:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2
    - uses: cachix/install-nix-action@v8
    - run: ./test
```

This is the whole workflow definition. I do not try to put any more in here, because I do not want to deal with my CI having a completely different way of doing things than I can reproduce locally.

When this is pushed up, GitHub Actions will run.

### Result

You can look at the action that was run on GitHub here: https://github.com/justinwoo/rustup-test-gh-actions/runs/706966778?check_suite_focus=true

## Conclusion

I hope this has shown you how you can make use of Nix on GitHub Actions to make your life easier. I chose to write about this because there doesn't really seem to be many people writing about this at all, giving an illusion that there doesn't exist a solution that will work for most cases.

## Links

* install-nix-action https://github.com/cachix/install-nix-action
* this example https://github.com/justinwoo/rustup-test-gh-actions
【Golang】構造体②メソッド

#【Golang】構造体②メソッド
Golangの基礎学習〜Webアプリケーション作成までの学習を終えたので、復習を兼ねてまとめていく。 基礎〜応用まで。

```
package main 
//メソッドとポインタレシーバーと値レシーバー
//メソッド class内関数のselfを使えるようなイメージ（Goにはクラスが無い）
//コードがわかりやすい


import (
	"fmt"
)


//バーテックスを作成
type Vertex struct {
	X, Y int
}


//1
func Scale1(v *Vertex, i int) {
	v.X = v.X * i
	v.Y = v.Y * i	
}

//2
//メソッド
func (v Vertex) Area() int {
	return v.X * v.Y
}

//メソッド
//structのポインタを渡す 値を上書きする
//原則ポインタ型にする
//引数も渡す
func (v *Vertex) Scale2(i int) {
	v.X = v.X * i
	v.Y = v.Y * i
}

func main() {
	v := Vertex{3, 4}
	fmt.Println(v)

	//1
	//関数の場合
	Scale1(&v, 2)
	fmt.Println(v)
	//>>{6 8}

	//2 
	//メソッドの場合 pythonのselfのイメージ
	v.Scale2(2)
	fmt.Println(v)
	//>>{12 16}

	//scaleで書き換わった後なので
	fmt.Println(v.Area())
	//>192
}
```
MacでLogisimを使う

## Logisim
Logisimとは論理回路設計用アプリケーションです。
> http://www.cburch.com/logisim/

## Logisimのダウンロード
こちらのURLのDownloadボタンからダウンロードすることができます。
> https://sourceforge.net/projects/circuit/

ダウンロードしたtarファイルを Ctrl + Click から開きインストールします。
![スクリーンショット 2020-05-26 2.38.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/923aea85-4e6d-cd41-b1e6-8295104ee789.png)

## brewのインストール
brewを既にインストールしてる方は飛ばしてください。

```bash
$ xcode-select --install
```

```bash
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
```

brew caskのインストール

```bash
$ brew install cask
```
**参考記事**
> MacにHomebrewを導入する方法
> https://qiita.com/balius_1064/items/ac7dff5ef10eaf69996f


## Javaのインストール
Logisimを動作させるためjava6をインストールします。

#### Macにjavaが既にインストールされているか確認

```bash
$ /usr/libexec/java_home -V
```
何もインストールされてない場合の表示↓
<img width="434" alt="スクリーンショット 2020-05-26 2.01.30.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/de129c5c-eb8b-e62e-7be6-521720b57d06.png">

#### java6のインストール
brewを使ってインストールします。

```bash
$ brew tap homebrew/cask-versions
$ brew cask install java6
```

#### インストールされているか確認
```bash
$ /usr/libexec/java_home -V
```
正しくインストールできている場合の表示↓
<img width="871" alt="スクリーンショット 2020-05-26 2.02.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/faa65a65-67a5-7600-cc85-d9d89a5d40aa.png">


## Logisimを開く
LogisimもCtrlを押しながらクリックして開きます。
最初は開くときに警告？的なのがでますが無視して開いて大丈夫です。

![スクリーンショット 2020-05-26 2.44.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/8c1a3eef-d58c-bb74-5056-8524d233da30.png)

無事開くことができました！
<img width="752" alt="スクリーンショット 2020-05-26 2.48.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/264742/79924c04-05fb-c284-64f9-dbe1eb881483.png">



**参考記事**
> Homebrewでjava6をインストールする方法
> https://qiita.com/ponsuke0531/items/9be8dee67a91c6c78d4f
PythonでTAB補完したい

# 注：Windowsの場合
mac・Linuxの方は読み飛ばしてください
TAB補完には`readline`モジュールが必要ですが、Windowsにはデフォルトでは`readline`モジュールがありません
pipで入れようとしてもだめなので、以下を実行しましょう。

```:コマンドプロンプト
# Python3.9以前の場合
pip install pyreadline
# Python3.10以降の場合
pip install git+ssh://git@github.com/greyblue9/pyreadline.git
```

# TAB補完を有効化
Pythonのシェルを開いて、以下を貼り付けます

```Python3
import rlcompleter
import readline
readline.parse_and_bind('tab: complete')
```
これで、TAB補完が有効になりました。

# 自動で有効化したい
Pythonは実行時に`usercustomize.py`ファイルが実行されるらしいです。
場所は以下の方法で調べられます。

```python
import site
print(site.getusersitepackages())
```
このディレクトリはデフォルトだと存在しないので、作成しましょう。
次に、ここに`usercustomize.py`ファイルを作成し、以下のように編集します。

```python:usercustomize.py
import rlcompleter
import readline
readline.parse_and_bind('tab: complete')
```
これで、Pythonの実行時に自動的にTAB補完が有効になると思います。

# 追記：エラー処理
Windowsの何もない場所でTABを押すと以下のエラーが発生します

```
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\console\console.py", line 768, in hook_wrapper_23
    res = ensure_str(readline_hook(prompt))
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\rlmain.py", line 571, in readline
    self._readline_from_keyboard()
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\rlmain.py", line 536, in _readline_from_keyboard
    if self._readline_from_keyboard_poll():
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\rlmain.py", line 556, in _readline_from_keyboard_poll
    result = self.mode.process_keyevent(event.keyinfo)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\modes\emacs.py", line 243, in process_keyevent
    r = self.process_keyevent_queue[-1](keyinfo)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\modes\emacs.py", line 286, in _process_keyevent
    r = dispatch_func(keyinfo)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\modes\basemode.py", line 257, in complete
    completions = self._get_completions()
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\site-packages\pyreadline\modes\basemode.py", line 200, in _get_completions
    r = self.completer(ensure_unicode(text), i)
  File "C:\Users\user\AppData\Local\Programs\Python\Python38\lib\rlcompleter.py", line 80, in complete
    readline.redisplay()
AttributeError: module 'readline' has no attribute 'redisplay'
```

pyreadlineには`redisplay`関数が無いようです。なので、空の関数を書き加えましょう。
Pythonシェルで以下を実行します

```python
from readline import __file__
print(__file__)
```
ここに表示されたファイルを開き、importの後辺りに以下を書き加えます

```python
redisplay = lambda: None
```

これでエラーメッセージは表示されなくなるでしょう。

# 参考
https://kakurasan.hatenadiary.jp/entry/20101217/p1
https://qiita.com/tukiyo3/items/06c0821e5002eb73d43f
https://stackoverflow.com/questions/51157443/pythons-readline-module-not-available-for-windows#answer-51964654
GASでUrlFetchを実行すると「使用できないアドレス」とエラーが発生します

zipcodeという住所⇒郵便番号を検索できるサイトのAPIを使って
https://zipcoda.net/

スプレッドシートにある住所から郵便番号を検索する仕組みをGASで作りたいと思っています。
しかし実行すると必ず
『Exception: 使用できないアドレス: https://zipcoda.net/api?address=検索する住所』
とエラーが発生して原因不明で困っております。

どなたか原因がわかる方は教えて頂けないでしょうか。


```
//郵便番号検索
function getPostCode() {
  //シートを選択
  var sheet = SpreadsheetApp.openById('スプレッドシートのid').getSheetByName('シート1');
  //シートから住所を取り出す
  var address = sheet.getRange(2,1).getValue();
  //addressに住所の文字列を代入 
  var url = "https://zipcoda.net/api?address="+address;
  var response = UrlFetchApp.fetch(url);
  var json = JSON.parse(response.getContentText());
  var postCode = json.items[0]['zipcode'];
  sheet.getRange(2,2).setValue(postCode);
}
```
【MySQL】CSVからサクッとインポートしたかったけどハマった件

# 何をしたかったの？

いまのお仕事のテスト用に、DBに値をサクッと登録したかった。

そのために使えるCSV生成→DB登録機能は既に実装されていたが、
テスト環境でやっててもそのファイルを使ったらお客さんに通知が飛ぶし、
かといって、通知する部分をコメントアウトしたりってのも少し手間…

なんて思って、【やったことなかったけど】CSVから直接インポートしちゃえばよくね？？？
という軽い気持ちで試したら存外ハマったので、備忘録としてまとめていく。

# この記事で紹介すること

MySQLに、CLIからコマンド打ってCSVをインポートする方法。
ハマったところから紹介するので、答えだけ知りたい方は、最後の章だけ見てもらえれば。

# 紹介していく。

まず手元にCSVを用意する。

そして、MySQLにログインし、インポート先のDBを選択。
以下のコマンドを打つ。

```console:MySQL
$ load data local infile "/Users/[userName]/Import.csv" \
into table [tableName] \
fields terminated by ',' \
optionally enclosed by '"';
```

ちなみに、
terminatedは区切り文字、
optionally enclosedは囲い文字
となっているので、環境次第で変える必要がある。

実行結果は…

```console:実行結果
ERROR 1148 (42000): The used command is not allowed with this MySQL version
```

ググった結果、local_infileの設定が変なのではないか？とのことなので、
以下のコマンドを実行。（同じくMySQL内）

```console:MySQL
mysql> SELECT @@local_infile;
```

```console:実行結果
+----------------+
| @@local_infile |
+----------------+
|              1 |
+----------------+
1 row in set (0.00 sec)
```

このファイルの値が、先程のコマンドの権限？的なところを担っているらしいのだが、
僕はそもそも1だった。

ここが0の場合は、1に変えて再実行してみるのが良いかも。
それでもダメだったら、以下のコマンドを試してみると良いかも。

# ではどうするか

MySQLにログインする際に、`--local_infile=1`を指定する。

```console
$ mysql -u $userName -p -h $IP -P $port --local_infile=1
```

これでMySQLのログインパスワードを入力し、MySQLにログインできたら、
インポート先のデータベースを選択し、先程のコマンドをもう一度ためす。

```console:MySQL
$ load data local infile "/Users/[userName]/Import.csv" \
into table [tableName] \
fields terminated by ',' \
optionally enclosed by '"';
```

```console:実行結果
Query OK, 216 rows affected, 216 warnings (0.01 sec)
Records: 216  Deleted: 0  Skipped: 0  Warnings: 216
```

なんかやたらWarnings出てますが、phpMyAdminで値を確認したところ、
問題なく登録されていた。

こんなしょっぱい経験が、どなたかの役に立つことがもしあれば嬉しいです。
Azure ML で管理外のStorageに対してMSIでアクセスを試みた

## はじめに
備忘録です

リリースノートを見ていたらこんな記述が　
https://docs.microsoft.com/en-us/azure/machine-learning/azure-machine-learning-release-notes
>Added --grant-workspace-msi-access as an additional parameter for the Datastore CLI for registering Azure Blob Container which will allow you to register Blob Container that is behind a VNet.

> Azure Blob Containerを登録するためのDatastore CLIの追加パラメータとして--grant-workspace-msi-accessを追加し、VNetの後ろにあるBlob Containerを登録できるようにしました。

→やってみよう

というわけで既定のストレージはFirewall入っていても通常通りの手順で使えるのですが、管理外のストレージがFirewallで守られている場合、アクセスする手段がないか検証してみました

##前提

AzureMLでは管理下のストレージが一つ既定で作成されます。
ほかのストレージアカウント上のデータはDataStoreという形で登録します。

## 結果
登録はできるが、Computeからは現在利用する術がなさそう（2020/5時点）
おそらく既定のstorageにupするのが推奨なんでしょうね


### やったこと

#### データストア登録

APIリファレンスを読みあさって、なんとかMSIをつかうっぽいプロパティ「grant_workspace_access」が見つかりました
しかし非推奨・・・
https://docs.microsoft.com/ja-jp/python/api/azureml-core/azureml.core.datastore(class)?view=azure-ml-py#register-azure-blob-container-workspace--datastore-name--container-name--account-name--sas-token-none--account-key-none--protocol-none--endpoint-none--overwrite-false--create-if-not-exists-false--skip-validation-false--blob-cache-timeout-none--grant-workspace-access-false--subscription-id-none--resource-group-none-

ほかにも必要そうな設定をいれてみました
https://docs.microsoft.com/ja-jp/azure/machine-learning/how-to-create-register-datasets#create-a-tabulardataset
> ストレージが仮想ネットワークまたはファイアウォールの背後にある場合は、SDK を使用したデータセットの作成のみがサポートされます。 データセットを作成するには、from_delimited_files() メソッドにパラメーター validate=False および infer_column_types=False を必ず含めてください。 これにより、最初の検証チェックがバイパスされ、セキュリティで保護されたこれらのファイルからデータセットを作成できるようになります。


#### コード

一応通ります。wsとか、csvは事前に定義してください

``` python:python
import azureml.core
from azureml.core import Workspace, Datastore
blob_datastore = Datastore.register_azure_blob_container(
           workspace=ws,
           datastore_name="データストア名",
           account_name="ストレージアカウント名", # Storage account name
           container_name="コンテナ名", # Name of Azure blob container
           grant_workspace_access=True,
           subscription_id = ws.subscription_id,
           resource_group = ws.resource_group,
           skip_validation=True)

# パスからdatasetオブジェクト作成を試みる
datastore_paths = [(blob_datastore, 'data/temp/train_data.csv')]

train_ds = Dataset.Tabular.from_delimited_files(path=datastore_paths,validate=False,infer_column_types=False)
train_ds = train_ds.register(workspace=ws,
                                 name='train_ds',
                                 description='train_ds')
```

ml Studioからも確認できます。
プロファイル見ようとするとエラーになりますが。。。

#### 実験してみる
AutoMLを回してみるとdriverlogが不穏な感じでした。

なぜかDeviceLoginが走る
> To sign in, use a web browser to open the page https://microsoft.com/devicelogin and enter the code xxxx to authenticate.

Device Loginやってみると以下のようなエラー（Blobデータ共同作成者をaml,私のアカウント双方につけてもだめでした）

```json:json
"error": {
        "code": "System",
        "message": "Failed to authorize with Azure Blob Container. Please make sure the compute or login identity has \"Storage Blob Data Reader or Storage Blob Data Owner\" role in the storage IAM.|session_id=xxxxx"
    }
```

### 終わり
進展あったらメモしようかなと思います
Google スプレッドシート: GAS でシートを右端・左端に移動する

スプレッドシート内にシート（タブ）がたくさんあると左右への移動に手間がかかる。 GAS を使うと時短できる。

以下はマクロを記録してから改変する手順だが、直接スクリプトエディタで GAS 関数を書いてもよい。

1. ツール → マクロ → マクロを記録
2. 移動したいシートを選択
3. シート名の右の ▼ をクリック → （左 or 右）に移動 をクリック
4. マクロを保存（マクロ名は適当につける）
5. ツール → マクロ → マクロを管理 → マクロ名の右の ︙ をクリック → スクリプトを編集 をクリック
6. GAS 関数を編集（以下のコード参照）

```javascript
// シートを左端に移動する場合
function myFunction() {
  var spreadsheet = SpreadsheetApp.getActive();
  spreadsheet.moveActiveSheet(0);
};
```

```javascript
// シートを右端に移動する場合
function myFunction() {
  var spreadsheet = SpreadsheetApp.getActive();
  spreadsheet.moveActiveSheet(spreadsheet.getNumSheets());
};
```

以降は、移動したいシートを選択後、ツール → マクロ → （マクロ名） をクリック で、一発で右端・左端に移動できる。
react nativeでTask :app:processDebugGoogleServices FAILEDでるやつ(Android)

react-nativeでよくエラーになってビルドに失敗することがあったので自分なりの解決方法を書いておきます。

環境はWindows10で、react-native cliを用いてAndroidアプリの開発を行っています
エミュレータはAndroidStudioを用いて実行しています。

C:Users/user/Awesomeapp
というディレクトリの体です。
#対処法
##1. npx react-native run-androidを実行する
```terminal:C/Users/user/
cd Awesomeapp
npx react-native run-android
```
これを行って基本的にはタイトルのエラーが出ると思います。

##2. react-native run-androidを実行する
```terminal:C/Users/user/
cd Awesomeapp
react-native run-android
```

ローカルにreact-native をインストールしている場合はnpxを通してだとうまくいかないときもなぜかうまくいくときがあります。

**先にnpx startしろ！**
とか言われてるときは大体これでいけます
まあ考えてみればそりゃそうなんですけど...

##3. gradleをクリーンする
それでも治らない、てときには、androidレベルのbuild.gradleに攻撃をしかけます

```terminal:C/Users/user/
cd Awesomeapp
cd android
gradlew clean
```

まあビルドするときのキャッシュを消去してる？感じ？(たぶん...)

またここで用いているgradlew というコマンドですが、gradleをインストールしていなくても後ろにwつけると使えますよ的なやつなので決して怪しいものではありません！

##4. npmのキャッシュを消す
以上のステップでもまだ直らないってときにはnpmのキャッシュも消してみましょう
案外直ります

```terminal:C/Users/user/
cd Awesomeapp
npm cache clean
```

#これで直らなかったならコードが間違ってそう！

これでもビルドできなければビルドの問題ではなくコードで何かミスっているのでしょう。

基本このバグはライブラリ等をインストールした後で起こりやすいので、インストールしたらとりあえず
npx react-native run-android
して、バグったら上のを試してみるとよいかもです。
WSL(windows subsystem for linux)上でPython使おうとしたらJupyterで詰んだ(解決済み)

【注意】あなたがroot権限で作業をしていないならこの記事は有用でないと思います｡今回の問題はroot権限で作業しているから起こっているものなので一般ユーザーの方は読まなくても大丈夫だと思います｡

普段WSl上で開発を行っているのですが､今日久々にPythonを書こうとしたら詰まった点について解説していきます｡
*問題発生から解決まで丸一日消費してしまった...

## 動作環境

- WSL2
- Ubuntu 18.04
- pyenv 1.2.18-12-g098227f2
- python 3.8.2
- pip 20.1
- pipenv 2018.11.26

pythonのバージョン管理のためにpyenvを使っています｡更にプロジェクトディレクトリ内の仮想環境を整えるためにpipenvを使っています｡外部モジュールはpipenv経由でインストールするようにしています｡

### 環境構築

以下のコマンドで仮想環境を整えます

```bash
mkdir py_playground && cd py_playground
pipenv --python 3.8
```

### インストールした外部モジュール

- flake8
- autopep8
- mypy
- ipython(必須)
- jupyterlab(必須､notebookでもいいけど今からやるならlabだよね)
- numpy
- scipy
- matplotlib

### 初期ディレクトリ構成

```
Pipfile(Node.jsでいうところのpackage.jsonみたいなもの)
Pipfile.lock
```

## どこで詰んだのか

いつもどうりvscodeを立ち上げてJupyterNotebookでも書こうかなと思って､新規のノートブックを立ち上げたその時...

**カーネルが接続してくれない**

おかしい､pipenvで仮想環境は整えているはずなのに...
こうして私はJupyterを起動させるための長い長い旅に出た

## 問題1 デフォルトでは.venvディレクトリが生成されない

windows上で開発してたときはうまく行ったんだ...何が違うんだ...
まず発見したのはインタプリタが入っているはずの.venvディレクトリが生成されていないのである｡
これはpipenvのデフォルト設定のとき仮想環境は`~/.local/share/virtualenvs/`の下に生成されているのである｡
ひとまずこいつを変更することにした｡

[pipenv で任意の場所の仮想環境を使う](https://qiita.com/tonluqclml/items/cd0d2a2cb0197cbaee42) を参考にして以下のように.zshrcに記述した(bashの人は.bashrcに書いてください)

```~/.zshrc
export PIPENV_VENV_IN_PROJECT=1
```

これでとりあえずプロジェクトディレクトリ直下に.venvディレクトリが生成されるようになった｡だがまだ接続できていない｡

## 問題2 ターミナルからjupyterが立ち上がるようにしてみよう

```bash
jupyter lab
```

するとエラーが出た｡どうやらroot権限で実行することは非推奨らしく､その場合は`--allow-root`を追加しろとのこと

```bash
jupyter lab --allow-root
```

だが今度は何も表示られなくなった｡
いろいろ探した[結果](https://qiita.com/taka4sato/items/378782763dec3dacb1ee)､設定ファイルを作成すればうまく表示されるようになった｡

```bash
jupyter notebook --generate-config
```

生成された設定用スクリプトの先頭に以下を追加した｡

```~/.jupyter/jupyter_notebook_config.py
c = get_config()
c.NotebookApp.ip = '*'
c.NotebookApp.open_browser = False
c.NotebookApp.port = 8080
```

よしターミナルに接続状況が表示されるようになった｡

## 問題3(これが解決策です) vscodeのjupyter系の設定がデフォルトのままだとうまくいかない

どうやらvscodeでjupyterを立ち上げるとそのタイミングでjupyter serverを立ち上げるようである｡そこで問題2が邪魔をする｡
そこでvscode内で`--allow-root`を設定した｡
F1を押す->検索フィールドに｢python jupyter arg｣と入力すると先頭に`python: specify jupyter commandline argument`が表示されると思う｡それを選択して`--allow-root`と入力する｡

最終的にこれで解決した｡

めでたしめでたし
ポケモン対戦AIの論文を読む

論文メモです。ポケモン対戦の用語がわかる人向け。

# Showdown AI Competition
論文は[こちら](http://julian.togelius.com/Lee2017Showdown.pdf)から読めます。
Showdownを使ってAI同士のポケモン対戦を行わせる実験。

## ルール
第6世代（XY、ORAS）

シングルバトル6-6でチームはランダムに生成される。技構成もランダムに決まるがでんきショックやはねるなどの通常対戦で使用されない技は除かれている。

基本的にはShowdownコミュニティのローカルルールに準拠。
- 同じ種類のポケモンは1匹まで
- 複数催眠禁止
- 意図的な無限ターン禁止（交代し続ける選択の他、このルールではターンスキップが可能なため。後述）
- バトンタッチを覚えているポケモンは1匹まで。また、そのポケモンは加速と積み技を同時に持っていてはいけない。
- 影分身、小さくなる、地割れ、ハサミギロチン、つのドリル、絶対零度、いばるの使用禁止
- ゲンガナイト、ガルーラナイト、ルカリオナイト、クチートナイト、ヤミラミナイト、ボーマンダナイト、こころのしずくの使用禁止
- 対戦での使用頻度が低いポケモンの禁止
- [このサイト](https://www.smogon.com/xyhub/tiers)でBannedとなっているポケモン（ほとんど禁止級伝説だけどなぜかギルガルドが含まれている）および使用頻度が低いポケモンの禁止
- 挙動が複雑になるため？ゾロアークを禁止

コンピュータ同士での対戦ということで以下のルールを追加している。
- 各エージェントは20秒以内に行動を決定する。それができない場合ターンをスキップする（何もしないをする）
- 経過ターン数が500を超えた場合引き分けとする
- もしエージェントがエラーや例外を吐いた場合は敗北として扱う

## このゲームをAIにやらせる上で難しいところ

### 分岐する枝の数
分岐する枝の数が状態とプレイヤーの選択によって変化する。基本的には4通りの技を使うか裏のいずれかのポケモンに交代するかだが、アンコールなどによって技の選択肢が減ることもあるしバトンタッチやとんぼがえりなどによって技を出した後交代する交代先についての選択肢が生じるため枝の数が増える。

### 無限ターンが可能
人間同士での対戦ではおおよそ60ターン以内に対戦は終了するが、理論的に上限があるわけではないので適切に設計されていないエージェント同士の対戦では例えば両者共にポケモンを交代し続けるなどの行動を取ることで無限ターンが発生しうる。ルールの項でターン数の制限を設けているのはこの可能性を排除するため。

### 同時ターン制である
このゲームでは双方のプレイヤーが行動を選択した後、実際にその行動が行われるまでにタイムラグがある。例えば、プレイヤー2の選択した技によって先にプレイヤー1のポケモンが倒された場合、プレイヤー1のポケモンは選択した技を出すことはない。このように、エージェントは実際に行動するタイミングではなくその前に意思決定を行うため、実際の行動時の状態ではその選択が最善でなくなっていることがありうる。

### 状態の評価に必要な要素が多い
HPは状態を評価するための重要な指標であるため、HPが多い方が概ね有利であり相手のHPを多く減らせる技は概ね有効な行動とみなせる。しかし実際には色々な状態異常・ステータス補正・フィールド効果などがあるため、HPの大小だけでは状態の良し悪しを判断できない。

### 行動結果に確率が絡む
行動結果は以下の点で確率の影響を受ける

- 技の命中率
- ダメージ計算における乱数
- 急所
- 追加効果

また、これらの確率は持ち物・特性・天候などの影響を受けるため、戦略によって確率を増減できる。

### 不完全情報
相手のポケモンについて、以下の要素を事前に知ることはできない。
ただし、ドメイン知識により予測できる部分はある。

- 特性
- 努力値
- 技構成
- 持ち物
- 交代のタイミング

### ポケモンの偽装
ゾロアークのイリュージョンのこと。仕様上、ドメイン知識を持たないエージェントがイリュージョンを看破するのは難しいため今回の実験からはゾロアークを除いている。

### シミュレーションコスト
Showdown側の制約があるため、複雑な戦略を採っていたり状態探索を行うようなエージェントが十分な数の状態を探索すると非常に時間がかかる。

## ドメイン知識
タイプ相性、ポケモンの並び、行動時ではなくそのしばらく後に効果を発揮する行動の存在（ステルスロック、まきびしなど）など、エージェントに考慮させることで戦略が改良されるかもしれないドメイン知識について触れている。

## 実験
以下の戦略のエージェント同士で対戦。

- ランダム（Random）
- 幅優先探索（BFS）
- ミニマックス法（Minimax）
- Q学習（SLP, MLP）
- One Turn Lookahead（OTL）
- Type Selector（TS）
- 枝刈りあり幅優先探索（PBFS）

OTLとType Selectorについて説明する。OTLは「目の前の相手ポケモンに与えるダメージを自分のパーティの全ポケモンの技について計算し、それが最大である技を今場に出ているポケモンが持つならその技を選択、そうでないならその技を持つポケモンに交代する」というアルゴリズム。Type Selectorは「目の前の相手ポケモンを瀕死にできる技があるならそれを選択する、そうでない場合、タイプ相性が有利であれば居座って最大のダメージを与える技を選択、不利であれば最も有利なポケモンに交代する」というアルゴリズム。

## 結果
ランダムに配られたパーティで3回対戦→パーティを入れ替えて3回対戦で、多く勝った方の勝ち。各組み合わせで15Round （90Battle）の対戦を行い、各セルは行エージェントが列エージェントに勝利したRound数とBattle数を示す。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/134222/a0a618d5-1eb8-8344-8abb-cfb278cdcfec.png)

PBFSおよびOTLが他のアルゴリズムよりよい結果を残した。PBFSがBFSやMinimaxに優越したのは、枝刈りにより探索時間を減らすことで20秒以内に行動を決めるルールに抵触しにくかったから。
OTLの最大ダメージを狙っていく戦略はこの実験では強かったが人間相手では通用しないだろう。

## 結論と展望

- OTLはベースラインの戦略に使えるかもしれない
- ドメイン知識により枝刈りの効率がよくなれば探索ベースの手法もよいかもしれない
- Q学習は今回は奮わななかったけど今後に期待
- 今回はパーティはランダムだったがパーティ構築を含めた拡張もやりたい。

## 感想

実験条件がちゃんと書かれていないなどよくわからない部分の多い論文だけど、One Turn Lookahead戦略がそこそこ強かったという結果は面白く、ポケモン対戦AIを構築する上では少なくともこの戦略に勝てる必要があると感じた。数報この論文を引用している論文が出ているようなので、そちらも読んでおきたい。
【備忘録】特定のプロセスのCPU使用率をwhileループで確認するシェルスクリプト

# 0.はじめに
プロセス監視をtopコマンドで定期的に行うために作ったシェルスクリプトを共有します。
具体的には、topコマンドの実行結果をlogファイルにwhileループで出力し続けるという、シンプルなものです。

# 1.検証環境など
- ローカルpc
  - ubuntu20.04


# 2.topコマンドの実行結果
まず、シェルスクリプトにするtopコマンドの実行結果をサンプルとして共有します。

```
$ top -n 1
top - 00:58:08 up 55 min,  1 user,  load average: 0.67, 0.58, 0.64
Tasks: 329 total,   1 running, 328 sleeping,   0 stopped,   0 zombie
%Cpu(s):  4.6 us,  0.8 sy,  0.0 ni, 93.1 id,  0.0 wa,  0.0 hi,  1.5 si,  0.0 st
MiB Mem :  15662.8 total,   9716.0 free,   2467.8 used,   3478.9 buff/cache
MiB Swap:   2048.0 total,   2048.0 free,      0.0 used.  11582.7 avail Mem 

    PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                                                             
   9095 gkz       20   0 4616108 107196  70536 S  25.0   0.7   0:00.37 chrome                                                                                                                              
   2487 gkz       20   0 4730532 335940 156620 S   6.2   2.1   2:42.61 gnome-shell                                                                                                                         
   4102 gkz       20   0  321656  12708  11268 S   6.2   0.1   0:05.56 ibus-engine-moz                                                                                                                     
   7243 gkz       20   0  961388  52248  37448 S   6.2   0.3   0:05.53 gnome-terminal-                                                                                                                     
      1 root      20   0  168164  11936   8272 S   0.0   0.1   0:10.67 systemd    
```
topコマンドはnオプションを使うことで画面(フレーム？)の更新回数を制限することが可能です。
本記事では任意のプロセスのCPU使用率を定期的に監視するため、パイプでtopコマンドの結果を渡し、grepで特定のプロセスの出力結果のみ絞ることとします。

# 3.ソースコード

```toploop.sh
#!/bin/bash

# debug mode
# bash -x toploop.sh $process

# your monitored process, e.g. dockerd
process=$1

starttime=`date +"%Y%m%d_%H%M%S"`
filename=`echo "log/top.log.$process.$starttime"`

while true
do
  sleep 5
  output=`top -n 1| grep $process`
  val=`echo $output | awk '{print $13}'`
  if [ "$val" == "$process" ]; then
    num=`echo "$output" | grep -oP "[S|R]\s+[0-9]*[.]?[0-9]" | awk '{print $2}'`
    date +"%Y%m%d_%H%M%S" >> $filename
    echo "$process:  $num%" >> $filename
  else
    date +"%Y%m%d_%H%M%S" >> $filename
    echo "$process: notfound" >> $filename
  fi
done

```

# 4.実行方法

### 4-1.コマンドの末尾に`&`をつけてバッググラウンドでコマンドを実行
```
$  . toploop.sh chrome&
[1] 11175
```
### 4-2.シェルスクリプトを実行した後、tailコマンドでログファイルの更新を追う
※シェルスクリプトではlogファイル名のフォーマットを`top.log.${process}.${starttime}`としています。

```
$ tail -f log/top.log.chrome.20200526_011531
20200526_011602
chrome: notfound
20200526_011608
chrome:  6.2%
```

※プロセス監視が終わったら、4-1で実行したシェルスクリプトの実行プロセスを忘れずに`kill ${bashのPID}`しておきましょう。


# 5. 参考

- [top(1) - Linux manual page](http://man7.org/linux/man-pages/man1/top.1.html)

# P.S. Twitterもやってるのでフォローしていただけると泣いて喜びます:)
[@gkzvoice](https://twitter.com/gkzvoice)
増えていく電子部品の収納

紹介したケースが廃版商品となってしまったため、代替品を見つけました。

https://qiita.com/nekokurono7/items/a3a81b092ab3b0af25b8

---
こんな感じに収納しています。
![justfits.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/1ee9dbf6-c328-eb98-7bd1-39193f2794d2.jpeg)

## はじめに
マイコンや電子工作を始めると手持ちの電子部品が増えていきます(あるある)。種類が少ない時はチャック袋で十分でしたが、部品の出し入れが面倒になったり袋を重ねるとツルツル滑ってしまうなど、イライラが積もってきました。
そこで、もっときれいに収納できるものはないか探したところ、全て100均のダイソーで調達できたので記事にまとめました。

## 購入品
全てダイソーで1つ100円(税抜)で購入できます。どれも定番商品のようで、この2,3年は在庫が切れても再入荷されています。(2020年3月現在)

|項番|商品名|売り場|説明|用途|
|--:|:-:|:-:|:--|:--|
|1|ミニケース5個組|工具|プラ製の蓋付きケースが5個で1セット|同じ種類の電子部品を１つにまとめて収納します|
|2|カスタムバスケット LまたはM|収納用品、またはキッチンツール|縦にピッタリ積み重ねることができ、MサイズはちょうどLサイズの半分なのでMサイズ2個とLサイズを積むこともできます|ミニケースをまとめて収納します|
|3|おなまえシール|文房具|名前を書いて細かい場所に貼るシール|部品名を書いてミニケースに貼付します|

### 1. ミニケース
5個で1セットですが、ケース色の組み合わせが4パターンあります。

- 同色が5個1セットのパターン：青、ピンク、透明の3種類
- 青2+ピンク2+黃1で1セットのパターン

![minicase1s.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/dbad309e-1bc3-3173-e4b3-db318476230a.jpeg) ![minicase2s.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/e0ed5bfb-f06c-eda3-1da7-67295dbaf7c8.jpeg)
抵抗器もピッタリ入ります。電子部品との相性は抜群です。抵抗器、コンデンサ、トランジスタ、LEDなど、4色しかありませんがケース色で使い分けてもよいでしょう。
※ CMOS半導体など、静電気に弱い部品は導電スポンジに指したままケースに入れています。

![minicaseins.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/aa3b4c00-b850-ed47-f0b0-1fe3322f4b3d.jpeg)
![minicasein2s.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/8fc71abe-b992-fe87-fe25-e5e2c7eabc07.jpeg)

### 2. カスタムバスケット
![custumbass.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/bbff24e4-f7d7-5616-d953-f89f74f26b1a.jpeg)

Lサイズはミニケースをまとめて11個×3列+2個ぴったりハマります(Mサイズの場合は、5個×3列+1個ぴったりハマります)。
![justfits.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/1ee9dbf6-c328-eb98-7bd1-39193f2794d2.jpeg)

ピッタリ縦に重なるので崩れにくいです。
![allviews.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/1b32bb91-2dc1-a890-a3af-86040a88ae7d.jpeg)

### 3. おなまえシール
ミニケースをカスタムバスケットに詰めこんでも中身がわかるようにラベルを貼ります。
156枚もあるので失敗しても気になりません。
![nameseals.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308714/6679cfdb-4cc0-3548-84fd-b06e633fa4a1.jpeg)

# あとは
これで電子部品の整理はできました。あとは在庫の管理が課題です。特に抵抗器やコンデンサは手持ちの有無確認がいつでも外でもできるようにしたいです。
【EC2】python3の仮想環境構築と.pyファイル実行 & 対話モードに入る方法

#【EC2】python3の仮想環境構築と.pyファイル実行 & 対話モードに入る方法

###主な内容
・python3のインストール
・仮想環境用のフォルダ作成
・仮想環境の有効化
・python実行


<br>
<br>
**＞この記事は[こちらに移転しました。](https://prograshi.com/blog/ec2-python3/)**
ウィンドウのスクショ →　EXCEL貼り付け　

#目的
ウィンドウのスクショ →　EXCEL貼り付け　
借り物多数

pip install pywin32

#exe化
pyinstaller XXX.py --onefile


#RuntimeError: maximum recursion depth exceeded while calling a Python object
pip uninstall openpyxl
pip install openpyxl==2.3.5
で対処



``````python:ウィンドウのスクショ.py
import datetime
import ctypes
from ctypes import sizeof
from ctypes.wintypes import RECT

import win32gui
from PIL import ImageGrab
import keyboard
import mouse

import csv


print('撮りたいウィンドウをクリック')
handle = None
text = ''


#list to csv出力
def export_list_csv(export_list, csv_dir):
    try:
        with open(csv_dir, "w") as f:
            writer = csv.writer(f, lineterminator='\n')

            if isinstance(export_list[0], list): #多次元の場合
                writer.writerows(export_list)

            else:
                writer.writerow(export_list)
    except:
        print("エラー発生")
        pass




def mouse_callback():
    global handle
    global text
    handle = win32gui.GetForegroundWindow()
    text = win32gui.GetWindowText(handle)
mouse.on_click(mouse_callback)

while not text:
    mouse.wait(button='left', target_types=('up',))
print('このウィンドウを撮る: ' + text)
print('違うなら再起動')


rect = win32gui.GetWindowRect(handle)




memory_box = []

def key_callback():
    grabed_image = ImageGrab.grab()
    croped_image = grabed_image.crop(rect)
    name = datetime.datetime.now().strftime('%Y-%m-%d-%H%M%S')
    filename = name + '.jpg'
    memory_box.append(filename)
    croped_image.save(filename)

    
keyboard.add_hotkey('print screen', key_callback,
                    suppress=False)

print('escキーで終了')
keyboard.wait('esc')
export_list_csv(memory_box,"memory.txt")
``````


``````python:EXCEL貼り付け.py
import openpyxl
from PIL import Image
import csv


f = open("memory.txt")
data3 = f.read()
f.close()
lines3 = data3.replace('\n','').split(',')
memory_box = [x for x in lines3 if x]

print(memory_box)




wb = openpyxl.Workbook()
ws = wb.worksheets[0]

cell_number = 0
for i in range(len(memory_box)):

    im = Image.open('{}'.format(memory_box[i]))
    w = im.width
    h = im.height
    
    img = openpyxl.drawing.image.Image('{}'.format(memory_box[i]))
    if i == 0:
        ws.add_image( img, "A1") 
        cell_number = int( + h // 13.5)
    else:
        print(cell_number)
        ws.add_image( img, "A{}".format(int(cell_number)))
        cell_number = int(h // 13.5 + cell_number)
        
        
wb.save('result.xlsx')
``````
高CPU消費でバックグラウンドの動画再生が60秒でiOSにキルされていた

iOS 13 WKWebView上の動画をAVPlayerにすり替えてバックグラウンドで動画音声を再生するアプリを作って公開しているのですが、わかりにくいエラーに遭遇したのでシェアしておきます。同じエラーの検索で来た人の助けになればうれしいです。

## 現象
バックグラウンド状態になってからも動画の音声は再生され続けるのですが、約60秒でクラッシュし、Xcodeのログ上には次のように表示されます。実機でしか再現しません。

```
Message from debugger: Terminated due to signal 9
```

これだけじゃ何が原因かよくわからない。

以下のエラーはリリース済みアプリの同現象を Firebase Crashlytics が捉えたもの。

```
Fatal Exception: CALayerInvalidGeometry
CALayer position contains NaN: [nan nan]. Layer: <CALayer:0x282bad620; position = CGPoint (0 0); bounds = CGRect (0 0; 0 0); delegate = <UIView: 0x13de736c0; frame = (0 0; 0 0); transform = [0, 0, 0, 0, 0, 0]; clipsToBounds = YES; animations = { opacity=<CABasicAnimation: 0x282b33f20>; }; layer = <CALayer: 0x282bad620>>; sublayers = (<CALayer: 0x282bae000>, <AVPlayerLayer: 0x282bad4c0>); mask = <CAShapeLayer: 0x282badf00>; masksToBounds = YES; allowsGroupOpacity = YES; opacity = 1; transform = CATransform3D (0 0 0 0; 0 0 0 0; 0 0 1 0; 0 0 0 1); backgroundColor = <CGColor 0x28091fe30> [<CGColorSpace 0x280e08a20> (kCGColorSpaceICCBased; kCGColorSpaceModelMonochrome; Generic Gray Gamma 2.2 Profile; extended range)] ( 0 0.32 ); animations = [opacity=<CABasicAnimation: 0x282b33f20>]>
```

どちらのエラーからも明確な位置は特定できません。
Method Swizzlingで`CALayer`のsetterプロパティを上書きして、すべての代入処理をログにはきだしてもNaNが入る余地はなかったので悩みました。

## 原因

細部に導入したアニメーションが実は高処理で、バックグラウンドでもCPUを消費していたことが原因でした。
Instruments の Time Profiler で異常値を発見してCPU消費を100%近くから一桁台へ抑えたところバックグラウンド再生が60秒を超えても動作するようになりました。

iOS 13でバックグラウンド処理が頻繁に落とされるとの情報も聞いていたのでビビりましたが、凡ミスだったようでよかったです。スッキリしたので[アプリ](https://apps.apple.com/jp/app/ohajiki-d-web-browser/id1039646068?mt=8)を審査に出して寝ます。
【JavaScript】イベント全部ログ

取り急ぎ
HTMLの各要素の各イベント実行時に開発者ツールのコンソールにログを出力します。
ログが大量に出るのでご注意ください。
ページ解析用


```js:javascript

var logger = function(s){
  return function(){console.log(s);};
};

document.querySelectorAll("*").forEach(function(el){
  var evs = getEventListeners(el);
  for (var k in evs) {
    var name = el.tagName;
    if (el.id) name += "#"+el.id;
    if (el.classList) el.classList.forEach(function(c){
      if (c) name += "."+c;
    });
    el.addEventListener(k, logger(name+"\t"+k.toString()));
  }
});

```

2020/05/29 修正 タグ名だけじゃ特定しにくそうなのでソース改修。
Mac Laravel 7 Authを用いたユーザ登録 ログイン ログアウトなどの機能を作成する ver 2.0

# 目的

- すでにQiitaに記事として投稿してある[Mac Laravel 7 Authを用いたユーザ登録 ログイン ログアウトなどの機能を作成する](https://qiita.com/miriwo/items/5d4a94e8d2aa06b61530)よりも簡単に機能を実装できる方法を学んだのでまとめる。

# 実施環境

- ハードウェア環境

| 項目 | 情報 |
| --- | --- |
| OS | macOS Catalina(10.15.3) |
| ハードウェア | MacBook Pro (16-inch ,2019) |
| プロセッサ | 2.6 GHz 6コアIntel Core i7 |
| メモリ | 16 GB 2667 MHz DDR4 |
| グラフィックス | AMD Radeon Pro 5300M 4 GB Intel UHD Graphics 630 1536 MB |

- ソフトウェア環境

| 項目 | 情報 | 備考 |
| --- | --- | --- |
| PHP バージョン | 7.4.3 | Homwbrewを用いて導入 |
| Laravel バージョン | 7.0.8 | commposerを用いて導入 |
| MySQLバージョン | 8.0.19 for osx10.13 on x86_64 | Homwbrewを用いて導入 |

# 条件

- `$ laravel new`コマンドが実行できること。

# 概要

1. アプリの作成
1. DBの作成と設定
1. マイグレーション
1. 確認

# 詳細

1. アプリの作成
    1. Laravelアプリを作成したいディレクトリにターミナルで移動する。
    1. 下記コマンドを実行してLaravelのアプリを作成する。

        ```terminal
        $ laravel new アプリ名 --auth
        ```
1. DBの作成と設定
    1. 下記コマンドを実行してMySQLにターミナルからログインする。MySQLのルートユーザのパスワードを忘れた方はこちら→[MySQL 8.0.18 のrootパスワードを忘れた時のリセット方法](https://qiita.com/miriwo/items/1880e9d2ebcfd3c0e60d)

        ```terminal
        $ mysql -u root -p
        ```
    1. 下記コマンドを実行して
    1. `アプリ名ディレクトリ/databases`
1. マイグレーション
    1. 先のコマンドにて作成されたアプリ名ディレクトリに移動する。
    1. 下記を実行してマイグレーションを行う.

        ```terminal
        $ php artisan migrate 
        ```
1. 確認
    1. アプリ名ディレクトリで下記コマンドを実行してローカルサーバを起動する。

        ```terminal
        $ php artisan serve
        ```
    1. 下記にアクセスしてログインフォームが表示される事を確認する。
        - [http://127.0.0.1:8000/login](http://127.0.0.1:8000/login)
    
            <img width="1682" alt="スクリーンショット 2020-05-25 23.14.17.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/0ffbc894-3d1e-f01e-0c60-a8ebe1273bf8.png">
ほぼゼロから始めたdockerのお勉強の旅メモ

# 前段
dockerって超便利で今どき知らないとか自称ITエンジニアとしてもどうなの？という世界線で、dockerをよくわからずなんとなく使っていたが、ECSとかFargateとかついにDockerから逃れられなくなった青年が、広大なネットを一日さまよって得たDockerの知識をここに記す。

※つまり、ハチャメチャなことを書いている可能性があるということだ。気をつけてね。

# とりあえずこれをやればいいと思った件
https://jdlm.info/articles/2019/09/06/lessons-building-node-app-docker.html

これすごく良かったような気がします。
いろんなサイト巡ってこれにたどり着いた。
Google翻訳でもたぶん読めるから英語だけど頑張れ!

その上で、今日の気ずきをまとめていく:point_up_2:

# COPYとVolumeについて
今日の朝はVolumeでソースコードマウントして作ったイメージをFargateでデプロイしたら503エラーがでた〜とか騒いでいたんですがこれは当たりまえだのクラッカーなお話でした。

基本的にDocker開発をするときはソースコードを何回も何回も何回も何回も変更するので

```console
docker run -v /host/path:/container/path hoge
```

みたいな感じでホストのディレクトリをコンテナのディレクトリにマウントして開発をします。
こうしないと、コンテナの中でプログラムを書くか、ホストでソースコードを書き換えるたびにdocker buildしなくてはいけなくなるからです。

だかしかし、つまりこれはコンテナのなかにソースコードは入っていないということなのです。
当然イメージにソースコードは含まれていません。

そんなイメージをFargateで展開したってなんも出てこないのは当たり前です。

ということでどこかしらで公開するということになったら、これまでVolumeでマウントしていたファイルたちをイメージの中に内包することが必要になってきます。

その時に使うのがCOPYです。

``` Dockerfile
COPY . /app/src/
```
みたいにDockerfileに書いて上げればイメージにソースコードが内包されます。

開発環境はVolumeでマウントすればいいのですが、デプロイするってなったらCOPYしなくちゃいけないよ。


とここで、僕は開発と本番でDockerfile２つ書かなくちゃいけないのかよめんどくさーって思いました。
次に繋がります。

# 検証と本番でかき分けるマルチステージドサービス

検証と本番のDockerfile分けるのめんどくせーって思っていたし、どうやら2016年とかは分けるしかなかったみたいなんだけど、今は「マルチステージドサービス」というものがあって、分けなくていいんだとさ。

```Dockerfile
FROM node:10.16.3 AS development
略

FROM node:10.16.3-slim AS production
略
```
この`FROM ・　AS hoge`ってのがポイント。
この`hoge`ってところを指定することで開発用とか本番用とか分けられるんだって。

指定は`target`でやればいいらしいよ。

```docker-compose.yaml
version: '3.7'

services:
  chat:
    build:
      context: .
      target: development
    command: npx nodemon index.js
    ports:
      - '3000:3000'
    volumes:
      - .:/srv/chat
      - chat_node_modules:/srv/chat/node_modules
```
上にtargetって書いてありますが、そこをASの後ろのワードにすればOK。

で多分これの本当の良さはここではないんだが、ぶっちゃけまだ良くわかってないのでなんとなく書くんだけれど

```Dockerfile
COPY --from=development --chown=root:root /srv/chat/node_modules ./node_modules
```
こういうことができるのですよ。

つまり、別のステージのビルド結果をコピーできるってことですね。

Dockerガリガリつかってないからなんとも言えないので詳しくはこのあたりを読むといいと思う。
https://qiita.com/minamijoyo/items/711704e85b45ff5d6405


# 以上
まとめるとたいしたことないな。
java(インターフェース)

#インターフェースとしてできる条件
**抽象クラスの親玉(一番上の方)**
①すべてのメソッドは抽象メソッド
②基本的にフィールドを持たない

###抽象度の高いHumanクラス

```java:Human.java
public abstract class Human {     //上の①②を満たしている
  public abstract void run();
}
```

###インターフェースとして宣言したHumanクラス

```java:Human.java
public interface Human {
  void run();                        //public abstract　を省略可能
}
```

###インターフェースの実装

```java:Hero.java
public class Hero implements Human { 
}
```

###インターフェースによる多重継承

```java:Hero.java
public class PrincessHero 
    implements Hero, Princess {    //親のインターフェースを複数継承できる
}
```

クラスでは多重継承はできないが、インターフェースなら可能

###インターフェースの継承

```java:Hero.java
public interface Human extend Creature {
  void talk();
  void watch();
  void hear();
  //さらに、親インターフェースからrun()を継承している
}
```

###implements（実装）、extend（継承）の使い分け

- クラス同士、インターフェース同士なら`extend（継承）`
- クラスでインターフェースを使う（異種）なら`implements（実装）`


###implements（実装）、extend（継承）の両方を使ったクラスの定義

```java:Hero.java
public class Hero extends Charaater implements Human{
  // Charaaterからhpやnameなどのフィールドを継承
  // Charaaterから継承した抽象メソッドattack()実装
  public void attack(Goblin g) {
    System.out.println(this.name + "５のダメージをあたえた");
  }
  // さらにHumanから継承した4つの抽象メソッドを実装
  public void talk(){
    System.out.println("・・・");
  }
  public void watch(){
    System.out.println("・・・");
  }
  public void hear(){
    System.out.println("・・・");
  }
  public void run(){
    System.out.println("・・・");
  }
}
```
OutlookVBA（メール＞クリップボード）TEST

#Outlook VBAでメールオブジェクトでクリップボード取得
##VBA設定
①Outlookを起動

②Alt + F11でMicrosoft Visual Basic for Applications

③「フォーム」追加
　「プロジェクト」ウィンドウのプロジェクトツリーを選択し、
　「右クリック」＞「ファイルのインポート(I)...」をクリック、
　ダイアログが表示されるので対象のファイル[XXXX.frm]を選択して
　「開く(O)」をクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/642708/fa851e57-d1a4-a954-28e6-1b2e113012ac.png)

④「モジュール」追加
　「プロジェクト」ウィンドウのプロジェクトツリーを選択し、
　「右クリック」＞「ファイルのインポート(I)...」をクリック、
　ダイアログが表示されるので対象のファイル[XXXX.frm]を選択して
　「開く(O)」をクリックする。



⑤Outlookに戻り、適当なメールをクリックして
 メッセージウィンドウを表示し、
　左上の「クィックアクセスツールバーのユーザー設定」を選択して
　メニューが表示されるので「その他のコマンド(M)...」をクリック
   Outlookのオプションが開くので「コマンドの選択(C)」から
　「マクロ」を選択し、追加するマクロを選択＞「追加(A)>>」をクリックする。


##メールオブジェクト取得
```VB
 Public Sub GetMail()
    On Error Resume Next
    Dim objItem As Object
    Dim objIns As Inspector

    Set objIns = Application.ActiveInspector
    Set objItem = objIns.CurrentItem   '今開いているメールオブジェクトを取得

    GetMailForm.txt_ReciveTime = objItem.SentOn
    GetMailForm.txt_from = objItem.SenderName
    GetMailForm.txt_subject = objItem.Subject
    GetMailForm.txt_Body = """" & objItem.Body & """"
    GetMailForm.Show
    
 End Sub
```

###メールオブジェクトからクリップボードへ転送、下の関数を経由
```VB
Public Sub PutClipBoad()

    Dim buf As String
    
    buf = GetMailForm.txt_ReciveTime.Value & "," & GetMailForm.txt_from.Value & "," & GetMailForm.txt_subject.Value & "," & GetMailForm.txt_Body.Value
    
    SetCB (buf)
    
End Sub
```
###一旦フォームを経由してクリップボードへ転送
```VB
Sub SetCB(ByVal str As String)

    'クリップボードに文字列を格納
    With CreateObject("Forms.TextBox.1")
        .MultiLine = True
        .Text = str
        .SelStart = 0
        .SelLength = .TextLength
        .Copy
    End With

End Sub
```

##フォームのボタンイベント設定

```VB
Private Sub btnCancel_Click()
    
    Unload Me

End Sub

Private Sub btnOK_Click()

    PutClipBoad
    Unload Me
    
End Sub
```
railsのmigrateファイルメソッド一覧

| メソッド | 用途 |
|:--|:--|
| add_column | カラムを追加する |
| remove_column | カラムを削除する |
| remove_columns | 複数のカラムを削除する |
| rename_column | カラムの名前を変更する |
| change_column | カラムの情報を変更する |
| create_table | テーブルを作成する |
| drop_table | テーブルを削除する |
| rename_table | テーブル名を変更する |
| add_index | インデックスを追加する |
| remove_index | インデックスを削除する |
| add_reference | 外部キーを作成する |
| remove_reference | 外部キーを削除する |
| add_foreign_key | 外部キー制約を作成する |
| remove_foreign_key | 外部キー制約を削除する |
文字操作の基本(java)

# 文字操作(java)
初投稿です。
今回は文字操作についてまとめました。
基本的なものなので、わすれたときに見返そうと思います。


```java
public class Main{
    public static void main(String[] args){
        String s1 = "Javaの勉強";
        String s2 = "Java";
        String s3 = "java";
        String s4 = "Javascript";
        String s5 = "javascript";
        String s6 = "";
        String s7 = "勉強Java";
        String s8 = " j a v a ";
        String s9 = "　j　a　v　a　";
        String s10 = "jjjjjjjjjj";
        String s11 = "jjjjjaaaaavvvvvaaaaa";
        String s12 = "j";
        String s13 = "0123456789";
        String s14 = "a0b1c2d3e4f5g6h7i8j9k10";
        String s15 = "0a1b2c3d4e5f6g7h8i9j10k";
        String s16 = "a,0,b,1,c,2,d,3,e,4,f,5,g,6,h,7,i,8,j,9,k,10";

//文字の内容が等しいかを調べる
//検索したい文字.equals(検索したい文字)
if(s2.equals(s3)){
  System.out.println("s2とs3は同じ文字");
  }else{
        System.out.println("s2とs3は等しく無い");
  }

//大文字小文字区別せず文字が等しいかを調べる 検索したい文字.equalsIgnoreCase(検索したい文字)
if(s2.equalsIgnoreCase(s3)){
 System.out.println("s2とs3は同じ文字");
 }else{
  System.out.println("s2とs3は等しく無い");
 }

//文字列の長さを表示する 検索したい文字.lenght()
System.out.println(s4.length());

//空文字か調べる 検索したい文字.isEmpty()
if(s6.isEmpty()){
  System.out.println("s6は空文字");
 }else{
  System.out.println("s6は空文字では無い");
 }

//文字列sが含まれるかを調べる 検索したい文字.contains(検索したい文字)
if(s4.contains(s2)){
 System.out.println("s4にs2は含まれる");
 }else{
 System.out.println("s4にs2は含まれない");
 }

//文字列sで始まるかを調べる 検索したい文字.startsWith(検索したい文字)
if(s4.startsWith(s2)){
  System.out.println("s4はJavaから始まる");
  }else{
  System.out.println("s4はJavaから始まらない");
  }

//文字列sで終わるかを調べる 検索したい文字.endsWith(検索したい文字)
  if(s4.endsWith(s2)){
  System.out.println("s4はJavaで終わる");
  }else{
   System.out.println("s4はJavaで終わらない");
  }

//文字列sが最初に現れる場所を先頭から探す。検索したい文字.indexof(検索文字)
System.out.println(s2.indexOf(s4)); //-1なら検索文字は存在しない
System.out.println(s4.indexOf(s2)); //0以上が検索文字の発生位置

//文字列sが最初に現れる場所を後ろから探す。検索したい文字.lastIndexOf(検索文字)
System.out.println(s2.lastIndexOf(s4)); //-1なら検索文字は存在しない
System.out.println(s7.lastIndexOf(s2)); //0以上が検索文字の発生位置

//指定した位置の文字を1文字だけ切り出す 検索したい文字.charAt(切り出したい文字の場所)
System.out.println(s7.charAt(1)); //強が表示

//指定した位置から任意の長さだけ文字を切り出す 検索したい文字.substring(切り出したい文字の場所)
System.out.println(s7.substring(1)); //強Javaが表示
System.out.println(s7.substring(1,4)); //強Jaが表示

//大文字を小文字に変換 変換したい文字.toLowerCase()
System.out.println(s2.toLowerCase()); //Javaがjavaになる

//小文字を大文字に変換 変換したい文字.toUpperCase()
System.out.println(s2.toUpperCase()); //javaがJAVAになる

//文字の前後の空白を消す 変換したい文字.trim()
System.out.println(s8.trim()); // j a v a がJAVAになる

//文字列を置き換える 変換したい文字.replace(変換したい文字,変換後の文字)
System.out.println(s9.replace("j","a")); //　a　a　v　a　と表示
System.out.println(s9.replace("　","")); //javaと表示 文字内の空白を削除する

StringBuilder hoge = new StringBuilder(); //hogeにStringBuilderインスタンスをnewする
  for(int i = 0; i < 1000; i++) { //for内処理を1000回繰り返す
  hoge.append("a"); //hogeにaを追加
  hoge.append("z"); //hogeにzを追加
 }

//文字パターンのチェック(正規表現) 検索したい文字.matches(比較する文字)
//変数の文字がJavaの文字と一致しているか？
System.out.println(s7.matches("勉強Java")); //true
System.out.println(s7.matches("勉強")); //false
System.out.println(s7.matches("Java")); //false

```
gitでssh接続する際にBad configuration option: usekeychainやterminating, 1 bad configuration optionsとエラーが出たときの解決方法

# 前提
・sshの公開鍵、秘密鍵を取得済み

# 使用する秘密鍵をconfigファイルに書く

```
### vimを立ち上げて~/.ssh/configを編集する。
$ vi ~/.ssh/config
-> configファイル内に下記内容を追記する。
#-------------------
Host github
  HostName github.com
  IdentityFile ~/.ssh/id_rsa
  User git
#-------------------
-> 追加後はescキー押したあとに:wqで保存します。
```

# 接続確認
こちらのコマンドで接続できているか確認できます。
`$ ssh -T git@github.com`

# エラーの原因
私の場合は下記内容があるためにエラーになっていました。
同じ様にエラーになる場合は削除してから上記の内容を記載すると問題なく動作するかと思います。

```
Host *
    AddKeysToAgent yes
    UseKeychain yes

-> エラー
/home/vagrant/.ssh/config: line 3: Bad configuration option: usekeychain
/home/vagrant/.ssh/config: terminating, 1 bad configuration options
```

# [※補足]AddKeysToAgentとUseKeychainとは何か
私の場合は削除してしまいましたが、あっても動くこともあるようなので、何をしているのか一応調べました。

AddKeysToAgentをyesにすることで、-Kオプションをつけなくてもssh-addの時やsshの時に強制的にパスフレーズがMacOSに保存されます。
また、UseKeychainをつけることで、ssh-agentを利用していなくても、MacOSに保存されたパスフレーズで自動的に~/.ssh/id_rsaなどを複合化してくれるようです。

# 参考
・https://qiita.com/GakuNaitou/items/81dbbd3ea6211af71648
・https://qiita.com/onokatio/items/397a5899a0ec16c7e60a
【GAS】Googleフォームで取り込んだスプレッドシートに自動付番したい。

Googleフォームで取り込んだ、問い合わせ情報にそれぞれ受付番号を付番（連番）し自動返信したいです。

問題としては、
①スプレッドシートにROW関数などを盛り込んでも、フォームが更新されると空白になり反映されないこと。

②GASでの受付番号の反映方法が分かりません。
　以下、途中まで組み込んだコードを貼り付けます。

```
function autoreply() {

 var title = "問い合わせを受付しました。"; 
 var body
 = "【受付完了】　株式会社〇〇です。\n"
 +"下記のとおり問い合わせをを受付いたしました。\n\n"
 + "------------------------------------------------------------\n";
 var footer
 = "------------------------------------------------------------\n\n"
 + "問い合わせ内容と受付番号をいま一度ご確認ください。\n"
 + "万が一入力事項等に不備や追加がありましたら追ってご連絡ください。";
 

 var name = 'お名前';
 var mail = 'メールアドレス';
　　var address = "";
 var number = '受付番号';

 var sheet = SpreadsheetApp.getActiveSheet();
 var rows = sheet.getLastRow();
 var cols = sheet.getLastColumn();
 var rg = sheet.getDataRange();
 Logger.log("rows="+rows+" cols="+cols);
 
 for (var i = 1; i <= cols; i++ ) {
 var col_name = rg.getCell(1, i).getValue(); 
 var col_value = rg.getCell(rows, i).getValue(); 
 body += "■"+col_name+"\n";
 body += col_value + "\n\n";
 if ( col_name === name ) {
 body = col_value+" 様\n\n"+body;
 }
 if ( col_name === mail ) {
 address = col_value;
 }
 }
 body += footer;
 

 GmailApp.sendEmail(address,title,body);
}
```

お時間があります時にご教授いただければ幸いです。
よろしくお願いします。