OmniAICreator/Qiita-1.07M huggingface dataset:
Async Function

Async Functionとして定義した関数は必ずPromiseインスタンスを返します。
なのでAsync Functionは"Promiseインスタンスを返す関数"を定義する構文でなければなりません。

## Async Functionの構文

関数の前に`async`を付けることで、Async Functionであることを宣言します。


```javascript
async function asyncFunc() {
    return 10
}
```



##Async Functionが返すPromiseインスタンスの状態

 - **Promise以外の値をreturnした場合**

```javascript
async function asyncFunc() {
    return 10
}

asyncFunc().then((value) => {
    console.log(value) //10
})
```

上記ではただの値をreturnしてますが、この場合返り値に10を持つFulfilledなPromiseを返します。
これは、返した値がPromise.resolveでラップされているような感じです。

 - **Promiseをreturnした場合**

```javascript
async function asyncFunc() {
    return Promise.resolve(10)
}

asyncFunc().then((value) => {
    console.log(value) //10
})
```
これはそのままPromiseを返します。

 - **Async Function内で例外が発生した場合**

```javascript
async function asyncFunc() {
    throw new Error('ERROR')
}

asyncFunc().catch((err) => {
    console.log(err.message)
})
```
Async Function内で例外が発生した場合は、そのエラーをもつRejectedなPromiseを返します。

##await

awaitは指定したPromiseインスタンスの状態が変わる（FulfilledまたはRejectedになる）まで、非同期処理の完了を待ちます。
Promiseインスタンスの状態が変わって初めて次の行の処理を進めることができます。
awaitはAsync Function内でのみ利用することができます。

たとえば、
処理に数秒かかる非同期処理の後にログを出したいとすれば、以下のようになります。

```javascript
const sleep = (second) => {
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(console.log('sleep')
            )
        },second * 1000)
    })
}

(async () => {
    await sleep(3)
    console.log('sleep後に実行される');
})()
```
```:実行結果
sleep
sleep後に実行される
```

ちゃんと処理を待ってからメッセージが出力されたのが確認できます。


いろいろありましたがとりあえず覚えとくのは

**Async FunctionはPromiseインスタンスを返す！！**
**awaitはAsync Function内でのみ使える！！**
BlurHashをネイルブックに導入してみた

久々の投稿です。
[note](https://note.com/kouda)の方に書いた記事をQiitaにも！


# BlurHashとは？

最近、ギークなエンジニアの間で話題になっているBlurHashってご存知ですか？

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr">BlurHash。これはおもしろいなあ。画像を30文字程度のテキストにエンコードする。レスポンスに含めて返せるからクライアント側で復元してプレースホルダとして使える。画像は元画像にブラーをかけたように圧縮されるから各画像の違いもなんとなくわかるし美しい。<a href="https://t.co/SxhzdHOZJB">https://t.co/SxhzdHOZJB</a></p>&mdash; kishikawa katsumi (@k_katsumi) <a href="https://twitter.com/k_katsumi/status/1230686603422707713?ref_src=twsrc%5Etfw">February 21, 2020</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


BlurHashはブラー（ぼかし）加工した画像をテキストで表現する技術です。

[BlurHash公式サイト](https://blurha.sh)

下記は公式サイトにあるサンプルです。

<img width="250" alt="picture_pc_648e4193a7bc3005c9de126c65e93f38.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32789/c82e6821-98f8-e152-40bc-66930fdc1c19.jpeg">


おいしそうな料理の写真をなんとなくイメージさせるぼかし画像を28文字のテキスト（画像真ん中の文字列）で表現しています。ぼかしの強さはパラメーターで調整することが可能です。

こちらはドーナツの例です。

<img width="250" alt="２.jpg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32789/b78bbb2d-29ce-0f06-f4e6-2c73d34e14ed.jpeg">


BlurHashは下記の２点が特に素晴らしいと感じました。

- ぼかし画像を別途生成する必要がない
- ごく短い文字列で画像を表現することができる


# BlurHashの使いみち


大きめな画像を扱うサービスでは表示が遅くならないようにプレースホルダー画像やファイルサイズの小さいサムネイル画像を用意しているところが多いと思います。

![3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32789/b2718048-7841-f4be-e7d5-b0248e761912.png)


こういった単色のプレースホルダー画像では味気ないですよね。かといって、このためにサムネイル画像を用意するのも大変です。

こんなときにBlurHashを使いましょう！ネイルブックでの実装例をご紹介します。

![4.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32789/afc598d0-7811-14ff-2f90-8376912d714b.png)


クールですよね〜。

単なるプレースホルダー画像を表示するのではなく、オリジナル画像を想起させるブラー画像を表示させておくことは、オリジナル画像読み込みまでの待ち時間のUX改善につながります。


ぼかし画像取得による通信も発生しませんので、レスポンス向上やパケット節約にもなります。


# BlurHashの導入方法

ソースコードがgithubで公開されていますので、あなたのサイトにも導入してみたらいかがでしょうか？
SwiftやKotlinのライブラリも公開されてますので、アプリへの組み込みも容易です。


[github](https://github.com/woltapp/blurhash)
CentOS7のネットワーク初期設定

#はじめに


CentOS7.7をインストールした後に、
どのようにネットワーク設定をすべきか
悩む部分があると思われるので手順を明記します。

##条件

条件：CentOS7.7を既にインストール済みであること
　　　インストール時のソフトウェアはインフラストラクチャーサーバを選択
　　　

##手順

###ログイン
まずは管理者権限を持つアカウントでログインします。

```CentOS7.7
localhost login:
```
###管理者権限の確認
プロンプトが「#」になっていることを確認します。
「$」であれば管理者権限を持っていないユーザでログイン
しているのでrootでログインし直します。

```CentOS7.7
[root@localhost ~]#
```
###NICの確認
設定するNICの情報を確認します。
※私の環境では設定できるNICはeth0でした。

```CentOS7.7
[root@localhost ~]#nmcli d
```
###ネットワーク情報の確認
設定するCネットワーク情報を確認します。

```CentOS7.7
[root@localhost ~]#nmcli c show 
```
###ネットワーク設定
ネットワーク設定コマンドの入力をします。

ここではネットワーク設定は以下とします。
IPアドレス: 192.168.0.1
サブネット: 255.255.255.0
ゲートウェイ: 192.168.0.254
DNS: 8.8.8.8
NIC: eth0


```CentOS7.7
[root@localhost ~]#nmcli c mod eth0 ipv4.method manual ipv4.addresses 192.168.0.1/24 ipv4.gateway 192.168.0.254 ipv4.dns 8.8.8.8 connection.autoconnect yes
```
もちろんバラバラに設定してもOKです。

```CentOS7.7

#eth0というインターフェースの有効化(無効化されている場合IPアドレスを設定しても通信できない)
[root@localhost ~]#nmcli c modify eth0 connection.autoconnect yes

#eth0のIPアドレスとサブネットの設定
[root@localhost ~]#nmcli c modify eth0 ipv4.addresses 192.168.0.1/24 

#eth0のデフォルトゲートウェイの設定
[root@localhost ~]#nmcli c modify eth0 ipv4.gateway 192.168.0.254

#eth0のDHCPの無効化
[root@localhost ~]#nmcli c modify eth0 ipv4.method manual

#eth0のDNSの設定
[root@localhost ~]#nmcli c modify eth0 ipv4.dns 8.8.8.8
```
###ネットワークマネージャサービスの再起動
ネットワークマネージャサービスの再起動のため以下のコマンドを入力します。
※ネットワーク設定反映のため

```CentOS7.7
[root@localhost ~]#systemctl restart NetworkManager
```
###ネットワークサービスの再起動
ネットワークサービスの再起動のため以下のコマンドを入力します
※ネットワーク設定反映のため

```CentOS7.7
[root@localhost ~]#systemctl restart NetworkManager
```
###ネットワーク設定の更新確認
ネットワークの設定が正しく設定できているか確認します。

以下の設定が反映されていればOKです。
BOOTPROTO=no (DHCP無効化)
IPADDR=192.168.0.1 (IPアドレス)
PREFIX=24 (サブネット)
ONBOOT=yes (NICの有効化：再起動後に有効になる)
GATEWAY=192.168.0.254 (ゲートウェイ)
DNS1=8.8.8.8 (Google Public DNS)

```CentOS7.7
[root@localhost ~]#cat /etc/sysconfig/network-script/ifcfg-eth0
```
###NICの有効化確認
（念の為）NICが有効化されているか以下のコマンドで確認します。

```CentOS7.7
#eth0がconnectedになっていればOKです。
[root@localhost ~]#nmcli d 
```
###PINGによる疎通確認
CentOSの画面に戻り、Pingを8.8.8.8(Google Public DNS)へ打ちます。

```CentOS7.7
#Pingが成功したら、正常に外部ネットワークへ接続ができたことになります。
#失敗する場合は、先にselinuxの設定およびFirewalldのサービスを無効にする必要があります。
[root@localhost ~]#ping 8.8.8.8
```


#終わりに
ハイパーバイザーでCentOS7.7を作成されている方は、
NICの値が違うかもしれませんので確認してください。

また、NICを有効化にしても通信できない場合は、
ハイパーバイザ側のNICの設定が無効化されている場合や、
そもそもNICを仮想マシン上に割り当てていなかったりする場合も
あるので確認してください。

ネットワーク設定後の基本設定については以下となります。
[インストール後のCentOS7のネットワーク初期設定](https://qiita.com/x5dwimpejx/items/546387c5ebea7183b6aa)
また、以下サイトを参考としました。
[NetworkManager_CLI_(nmcli)_でネットワークを設定する方法](http://www.maruko2.com/mw/NetworkManager_CLI_(nmcli)_でネットワークを設定する方法)

以上となります。
gitにhttpsのパスワードを覚えさせる

# 汎用


- git標準のgit-credential-storeやgit-credential-cacheはどこでも使える
- 参考： https://qiita.com/usamik26/items/c655abcaeee02ea59695

# Linux

- Fedoraの場合は git-credential-libsecret パッケージをインストールする
- .gitconfigに以下を記入

```
[credential]
        helper = libsecret
```
- 保存状況の確認と削除はseahorseでできる
- git-credential-gnomekeringはgnomekeyring自体がobsoleteのようです。

# cygwinのgit

- Git-Credential-Manager-for-Windowsのreleaseから最新版をダウンロード
  - https://github.com/microsoft/Git-Credential-Manager-for-Windows/releases
- 展開して出てくる.exeと.dllを C:\cygwin64\usr\libexec\git-core にコピー
- .gitconfigに以下を記入

```
[credential]
        helper = manager
```

- パスワードの保存状況と削除は、コントロールパネル>資格情報マネージャー でできる
- 参考： https://github.com/Microsoft/Git-Credential-Manager-for-Windows/issues/146
SpringBoot+Maven+PostgreSQLでFlywayの導入

Ruby on Railsは、デフォルトでDBのマイグレーション機能が搭載されていますが、SpringBootでは自分で導入するしか有りません。マイグレーションツールであるFlywayを導入するのに手こずったため、纏めて行こうかと思います。

#準備
```xml:pom.xml
<dependency>
	<groupId>org.flywaydb</groupId>
	<artifactId>flyway-core</artifactId>
</dependency>

```

依存関係の階層に、このように書いてあげます。
合わせてmvnのコマンドを使用したいので、プラグインにも下記の通り指定しています。

```xml:pom.xml
<build>
         <plugins>
           <plugin>
               <groupId>org.flywaydb</groupId>
               <artifactId>flyway-maven-plugin</artifactId>
               <version>6.0.8</version>
               <configuration>
                   <url>DBのURLを指定して下さい?currentSchema=DB側でスキーマを指定している場合は指定して下さい。</url>
                 <user>DBのUSERを指定して下さい。</user>
                 <password></password>
                 <schemas>
                     <schema>ssp_engine</schema>
                 </schemas>
                 <baselineOnMigrate>true</baselineOnMigrate>
                 <baselineVersion>1.0</baselineVersion>
                     <baselineDescription>Initial</baselineDescription>
                 <locations>classpath:/db/migration</locations>
             </configuration>
           </plugin>
         </plugins>
</build>
```

あとは、Mavenでプロジェクトを更新してあげて、jarファイルをインポートします。

#DBの命令ファイル作成

ファイル名は厳密に決まっているので、こちらを参考下さい。
・[Flyway使い方メモ](https://qiita.com/opengl-8080/items/6368c19a06521b65a655)

僕の場合、こんな感じになりました。
階層は、

```
-src/
  -main/
    |-java/
    |  -com/
    |    -example/
    |      -main.java
    -resources/
      -db/
        -migration/
          -V1_0__create_sequence.sql
          -V1_1__create_table.sql
          -V1_2__create_data.sql
```
ファイルの中身は、シーケンスオブジェクトを生成したり、テーブルを作って、中身を書いたりしてます。

#コマンド実行
ご自身のお使いのターミナルで、対象となるファイルがある階層まで行き、下記のコマンドを実行すると実行出来ます。

####マイグレーションを実行する
```
mvn flyway:migrate
```
####データベース上の全てのオブジェクトを削除する
```
mvn flyway:clean
```
####マイグレーションがどのバージョンまで実行されているかの情報を表示する
```
mvn flyway:info
```
####データベースと用意されているSQLファイルのバージョンに差異が無いかを確認する
```
mvn flyway:validate
```
####データベースのバージョン１にする
```
mvn flyway:init
```
####状態がFailedになっているバージョンのメタデータを削除する
```
mvn flyway:repair
```

#導入した感想
localで開発中に、フォーム等でCRUDの確認後、``mvn flyway:clean``して、``mvn flyway:migrate``してリセット目的でしか活用出来ていません。
もっと、有効活用の仕方があれば、聞きたいです。。
Rails Tutorialのファイルサイズのチェックに使ったjQueryのコードを読み解く

こんばんは。Shota(@Mii4a2501)です。
突然ですがRails Tutorial経験者の方、こんなコードを目にしたことはありませんか？

```
$('#micropost_picture').bind('change', function(){
  var size_in_megabytes = this.file[0].size/1024/1024;
  if (size_in_megabytes > 5) {
    alert('Maximum file size is 5MB. Please choose a smaller file');
});
```
これはCarrierWaveで画像をアップロードできるようにした後、ファイルサイズの検証のために作られたjQuery文です。
ふとこのコードの意味を知りたいと思ったので一行ごとに内容を書いていこうと思います。

<h2>1行目</h2>

```
$('#micropost_picture').bind('change', function(){
```

**$('#micropost_picture')**は簡単ですね。
$はjQueryのインディケーターでid="micropost_picture"を指し示しています。

さて次の**bind**メソッドです。
このメソッドは第一引数に**イベント**（'click'や'submit'など)に対し、第二引数には**コールバック関数**を紐づけます。

第一引数の'change'イベントですが、意外とそのままの意味のようで、テキストボックスやチェックボックスなどのvalue値が変更される際のことを指し示すようです。

第二引数のコールバックは、通常通り上から順に処理するのではなく、紐づけられたインスタンスやイベントが呼び出されたときに参照する処理方法のことです。非同期処理で散々お世話になること間違いなしですね。例えると、関数くんAに関数くんBを呼び出してもらう感じです（間違ってたらすいません！！）

Railsを勉強している方だと、Rspecのletをイメージするとわかりやすのではないかと思います。

<h2>2行目</h2>

```
var size_in_megabytes = this.files[0].size/1024/1024;
```

**var size_in_megabytes**
ここも最初同様、簡単です。
**var**はvariable(変数)の略でそのまま変数宣言です。

jQueryの**this**ですが直前の$で指し示した要素を指すので、この文中では**this = $('#micropost_picture')**となります。
（ここも間違えてたらすいません。。。）

その後、**files[0]**で**input type="file"**に入れられた画像を取得。**size**メソッドで容量を確認して**1/1024^2**することでbyteをMBに変換しています。

<h2>3行目</h2>

```
if (size_in_megabytes > 5)
```

条件文でおなじみifですね。
写真の容量が5MB以上の時に条件文内での処理を行います。

<h2>4行目</h2>

```
alert('Maximum file size is 5MB. Please choose a smaller file.');
```

alertはダイアログを表示する際用いるメソッドです。これも避けては通れないものの一つではないでしょうか。

<h2>最後に</h2>
ここまで読んでくださった方、お付き合いいただきありがとうございました！
細かく解説しすぎて冗長感が出てしまいましたが、誰かの助けになったら幸いです！
UnityIAP、お前は許さん（インストール方法）

課金システムをUnityに導入するにあたって必要不可欠なUnityIAPですが、わりとインポートするときにバグります(というか開発途中のやつにimportすると確定演出)。今回は僕の環境でうまくいった例を挙げます。

他にもいろいろ手段があるみたいです
http://sassembla.github.io/Public/2018:04:19%2011-08-42/2018:04:19%2011-08-42.html

## 環境

win10 1909
Unity 3.0f3

1. 親の顔より見たこの画面に到達します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106327/b18f622f-275a-ae81-9d30-ebbb81af9dcb.png)
1. 右側でアカウントを紐づけてservicesを立ち上げます
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106327/b9713832-e8b7-d741-806e-1dac6e5dc71b.png)
1. In-App Purchasingを選んで、Enableします
13歳以下むけとかテキトーなダイアログは進めてください
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106327/46ba3dec-3de2-7483-377a-a87b322d131a.png)
4. importをクリック
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106327/886022fe-6b73-0470-2678-0d739c8ab4a6.png)
5. IAP Installerが起動します。たぶんここで選ぼうが選ぶまいがあまり変わりませんがとりあえずインストールしてみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106327/eb39b0c1-3fe0-f80e-29bf-2ff23c759317.png)
6. No Thanks(Go Aheadしてぶっ壊れたことがある)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106327/e4d71293-6a70-3e24-c8c6-d54da7715106.png)
1. Customパッケージインストールを選択します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/106327/c76e1ff8-2159-d581-92ea-b582874713cf.png)
1. Assets→plugins→UnityPurchasingあたりにunityパッケージがあるのでそれを選んでimportします
GitHubの特徴とは

##GitHubのアカウントを作成
[GitHubのアカウントを作成](https://github.com/)
まずはアカウントを作成しましょう。
##GitHubの特徴とは
主に
世界中のあらゆるプロダクトが保存、公開されています
グラフィカルな画面からGitを扱うことができます
チーム開発に便利な機能が用意されています
という特徴があります。
##世界中のあらゆるプロダクトが保存、公開されている
GitHubでは世界中の人々が自分のプロダクト(ソースコードやデザインデータなど)を保存、公開をすることができます。そのため自分以外のプロダクトを読んだり、その他大勢の人が一つのプロジェクトやソースコードの変更に関わることができます。
##グラフィカルな画面からGitを扱うことができる
通常Gitはコマンドで扱いますが、GitHubならWebサービス上の画面からグラフィカルにGitの操作を行うことができます。
##チーム開発に便利な様々な機能がある
コードレビューを行う仕組みやソースコード単位でコメントのやり取りをする機能、他の開発者のリモートリポジトリをコピーしてくる機能などの機能があります。
Azure Container Registry への docker login ワンライナー (PowerShell版)

ネット上にあるのがBash版ばかりなのでPowerShell版を参考に投下します。テスト的に使ってください。

# 環境
- Windows PowerShell 5.1
- Azure PowerShell Module 3.6.1
- Docker version 19.03.5
- Azure Container Registryの認証オプションの管理者アカウントが有効になっていること
    - https://docs.microsoft.com/ja-jp/azure/container-registry/container-registry-authentication#admin-account
    - (補足) 上記ドキュメントにある通り、管理者アカウントはテスト的に使うのがベター

# コマンド
```powershell:AzureContainerRegistry_DockerLoginOneLiner_PowerShell
PS C:\> Get-AzContainerRegistryCredential -ResourceGroupName myresourcegroup -Name myregistry | Select-Object -ExpandProperty Password | docker login myregistry.azurecr.io --username myregistry --password-stdin 
```

`Login Succeeded` と表示されればログイン成功。
コマンド中の `myresourcegroup` `myregistry` は自身の環境に合わせること。

# コマンド解説
- `Get-AzContainerRegistryCredential` でAzure Container Registryのクレデンシャル情報を取得
- 取得したクレデンシャル情報のうち `Password` の値のみを `Select-Object -ExpandProperty` で取得
- `Password` の値を標準入力で `docker login` の `--password-stdin` に引き渡し

# 参考リンク
- https://docs.microsoft.com/en-us/powershell/module/az.containerregistry/get-azcontainerregistrycredential
- https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/select-object
- https://docs.microsoft.com/ja-jp/powershell/azure/queries-azureps
プログラムはなぜ動くのか？を読んでみてまとめることで知識の定着を図る投稿#5

[プログラムはなぜ動くのか第２版](amazon.co.jp/プログラムはなぜ動くのか-第２版-知っておきたいプログラムの基礎知識-矢沢久雄/dp/4822283151/ref=sr_1_1?adgrpid=53631245656&gclid=Cj0KCQjw0pfzBRCOARIsANi0g0tajATNcn3H7Ogokqrdst5O2JctSzMRb6A0XyW5GegcPbJwaEvZO84aAlK8EALw_wcB&hvadid=338517958683&hvdev=c&hvlocphy=2392&hvnetw=g&hvqmt=e&hvrand=9776556383623440456&hvtargid=kwd-334563073858&hydadcr=27265_11561134&jp-ad-ap=0&keywords=プログラムはなぜ動くのか&qid=1583760691&sr=8-1)

を僕が師匠と読んでいる方に進めていただき、読んでみようと思いました。
そこで、僕的にはかなり難しいこともあり、この本をまとめながら読み進めていくことによって理解度を高めようと思いました。

こちらはあくまでも推奨する記事ではなく、僕がこうした方が定着しやすいかもと思い、記録に残すことにしました。

##関数呼び出しの仕組み

プログラムの流れの説明を続けると、高水準言語で記述されたプログラムで関数を呼び出す処理も、プログラム・カウンタの値を、関数が格納されたアドレスに設定することで実現されます。

*ただし、条件分岐や繰り返しとは仕組みが異なりジャンプ命令では関数の呼び出しは実現できません

##コール命令・リターン命令

関数の呼び出しはコール命令によって行われます。

コール命令は、関数の入り口のアドレスをプログラム・カウンタに設定する前に、関数呼び出しの次に実行すべき命令のアドレスをスタックと呼ばれるメイン・メモリー上の領域に保存します。

関数の処理が終了したら、関数の最後（出口）でリターン命令を実行します

リターン命令は、スタックに保存されたアドレスをプログラム・カウンタに設定する機能を持っています。

##まとめ

高水準言語のプログラムをコンパイルすると、関数呼び出しがコール命令に変換されて、関数を終了する処理がリターン命令に変換されるのです。

なるほど
関数の始まりが「コール命令」

関数の終わりが「リターン命令」

特に感想はないので感謝の正拳突きでも

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253981/c321fa20-2a31-7942-0ceb-ac53a2550442.png)
Railsチュートリアルメモ - 第10章

[メモの目次記事はこちら](https://qiita.com/yokohama4580/items/dedfd5510080273dc2a0)

[公式Railsチュートリアル第10章へのリンク](https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.1#cha-updating_showing_and_deleting_users)

## サマリ
- ユーザーの更新・表示・削除を行えるようにする
    - 認可モデル (Authorization Model)
        - 認証 (authentication) :サイトのユーザーを識別すること
        - 認可 (authorization) :そのユーザーが実行可能な操作を管理すること 
    - beforeフィルター (before_action) 
    - フレンドリーフォワーディング
    - seeds.rbを使ったデータ作成
    - ページネーション
    - Strong Parameters

## ポイント
- Active Recordのnew_record?を使うと、既存レコードか新規レコードかを判定できる
- モデル内で`has_secure_password`を設定した項目は更新時にnilだった場合、更新されない
- モデルは`reload`メソッドでDBの最新データを再読み込みできる e.g. `@user.reload`
- `request.original_url`でリクエスト先が取得できる
- `redirect`の後に書かれている処理も実行される
    - 明示的にreturn文やメソッド内の最終行が呼び出されない限り、リダイレクトは発生しない

e.g.

```ruby
def redirect_back_or(default)
  redirect_to(session[:forwarding_url] || default)
  session.delete(:forwarding_url)
end
```
- Faker gemを使うとダミーの名前を作成できる
e.g. 

```ruby
name  = Faker::Name.name
```
- `rails db:migrate:reset`でDBデータがリセットできる
    - サーバーが起動しているとエラーになることがあるらしい
- will_pagenate gemを使うとページネーションを作成できる。具体的には以下が利用できるようになる。
    1. ビューに`<%= will_paginate %>`タグを埋め込むとページリンクを作成してくれる
    2. `paginate`メソッドを使うと指定したページに合わせてoffset-limitしてデータを取得してくれる
        - e.g. `User.paginate(page: 1)`
    3. `params[:page]`にページ番号を設定してくれる
- `render`メソッドは以下の動きをする
    - ファイル名 => パーシャルを探す
    - `user`などのモデルから生成したオブジェクト => `_user.html.erb`を探す
    - `@users`などのモデルから生成したオブジェクトのリスト => 自動でコレクションを生成してパーシャルを呼び出す
- `rails generate migration add_xxx_to_yyy column:type`で生成したmigrationファイル内の追加カラムはdefauｌｔ値は`nil`になる。
- default値を変えたい場合は`, default: false`のように指定する。
- boolean型のカラムを追加した場合はカラム名?型の真偽値判定メソッドが使用できるようになる e.g. `user.admin?`
- `toggle!(シンボル)`でboolean値を反転させられる。e.g. `user.toggle!(:admin)`
- `assert_no_difference {数値} {ブロック}`でブロック内の処理を実行しても数値が変化しないことをテストできる
- `assert_difference {数値}, {変化値} {ブロック}`でブロック内の処理を実行したときに数値が変化値だけ変化することをテストできる
- `heroku pg:reset DATABASE`でherokuのDBデータをリセットできる

## 感想
- 7章でのユーザー作成の後、8~9章にかけてのログイン周りのパートが（重要な部分ではあるものの）セキュリティに関する内容などを含みテンポが悪くあまり楽しい内容ではなかったので、10章は純粋にRailsでのコードの書き方に戻ってきた感じがして楽しめた。
OutSystemsのPersonal Environmentでサポート依頼を出してみた

今週の月曜日から火曜日にかけて、私のPersonal Environmentで何らかの障害が起き、アクセスできなくなりました。無償のPersonal Environmentですが、サポートチケットを起こすことで対応してもらい解決したので、手順を共有しておきます。

# 現象
ある日の朝、Service Studioを立ち上げでPersonal Environmentに接続すると、こんなエラーが表示されました。

> Server was unable to process request. Invalid username or password.

アクセスには、Service Studioに保存しておいたEnvironment/Username/Passwordを使っており、前日の夜にはPublishもできていたので、接続情報が間違っているということはない。

また、同時にService CenterやLifetimeへのアクセスも

> リダイレクトが繰り返し行われました

というエラーになりました。

まあ、無料環境だし様子を見ることにしましたが、夜になっても解決しなかったのでサポートに問い合わせることにしました。

# サポートに伝えるために調査
サポートに問い合わせるときに、正確に何が起きているか伝えた方がいいでしょうから、ちょっとだけ発生している問題を調査してみました。

## Service Center/Lifetimeの「リダイレクトが……」エラーの詳細を調査
エラーの内容から判断すると、HTTP Status Codeの302がOutSystemsから返されて、返された先でも再び同じページへの302が返される……ということが繰り返されたようです。

こういうときは、Fiddlerやブラウザの開発者向けツールを使ってHTTP通信を確認してみます。
以下は、Lifetimeにアクセスしたときのレスポンスです。

``` 
HTTP/1.1 302 Found
Content-Type: text/html; charset=utf-8
Location: https://<Personal Environment環境のホスト名>/lifetime/CustomHandlers/internalerror.aspx?
```
というHTTPのレスポンスが繰り返し発行されていることが確認できました。

## 環境の状態を確認
Personal Environmentについては、OutSystemsのサイトで状態が確認できます。
https://www.outsystems.com/home/
にアクセスしてみます。

Personal Environmentの環境のパスの隣に緑色の「●」が表示されていて問題なさそうです。

## Service Studioのエラー原因を探る
問題ないはずのアカウントに対して、「Invalid Username or Password」が出るというのは不思議なので、Fiddlerを起動しておいて、Service Studioからの通信をキャプチャしてみました。

```
HTTP/1.1 500 Internal Server Error
... (省略)

<?xml version="1.0" encoding="utf-8"?><soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema"><soap:Body><soap:Fault><faultcode>soap:Server</faultcode><faultstring>Server was unable to process request. ---&gt; Invalid username or password.</faultstring><detail /></soap:Fault></soap:Body></soap:Envelope>
```
あまり追加の情報はありませんでしたが、サーバから直接返されたエラーが原因調査の役に立つこともあるので、問い合わせに載せておくことにしました。

# チケット起票
Service StudioのHelp > Open a Support Case...でチケットを起票するページが開きます。
![qPEerror1.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/332987/d7e1062e-403b-a4a1-592b-76d3edfd432a.png)

Platform：Personal Environment
Lifetime Version：選択しない（アクセスできなくてわからなかったので）
Development Environment Version：Service StudioのHelp > Aboutで確認して設定

Request Detailsに英語で簡単に状況と上の調査結果をまとめて送信。
（質問：I noticed this morning ( around JST 7:00) that my Personal Environment is not working.
The problem continues at the time. Is there any way to solve this problem?）

なんと、翌日には回答が来て、アクセスできるようになっていました。
（残念ながら実際に何が起きていたかは不明）
バージョンアップが発生したときにもPersonal Environmentのトラブルはありました。そういうときのために、問い合わせ方法を把握しておくのもいいのではないかと思います。
Gitの基本的なこと

##Gitをインストール
ターミナル

```
$ brew install git
```
##リポジトリ
リポジトリとは、Gitの管理下にあるファイルやディレクトリの変更履歴を保管しておくことです。
リポジトリにはローカルリポジトリとリモートリポジトリがあります。
##ローカルリポジトリ
自分のPC上（ローカル環境）に置くリポジトリのことです。自分のPC上にあるファイルやディレクトリのバージョン管理をする場合に用います。
##リモートリポジトリ
外部のサーバなどのネットワーク上に置くリポジトリのことです。ネットワーク上に置くことで複数人で管理下のファイルやディレクトリを共有することが出来ます。複数人でサービスを開発するときにはリモートリポジトリが必須です。
##git init
新たにGitで管理したいディレクトリにおいて実行すると、隠しディレクトリである.gitが作成され、Gitで管理できるようになります。
【例】sampleで新規アプリケーションを作成したあととします。
ターミナル

```
$ cd ~/sample  #sampleディレクトリに移動
```
```
$ git init  #当該ディレクトリをGitの管理下に置きます
```
```
$ ls .git  #隠しディレクトリである.gitがあるかどうか確認できます
```
##インデックス
バージョンを記録するためにファイルを一時的に登録する場所です。インデックスに登録されているファイル群の変更が記録されます。同じバージョンとして記録したい編集についてはインデックスに追加し、まだ記録したくない編集についてはインデックスに追加しません。
##git status
ターミナルでインデックスに追加されている変更修正、されていない変更修正を確認することができます。
##git add
ターミナルでインデックスに追加して、変更修正記録の対象とすることができます。

```
$ git add XXXX #XXXディレクトリをインデックスに追加する部分です
```
##コミット
コミットとはインデックスに追加された変更修正をバージョン記録する操作のことです。
##git commit
インデックスに追加されている変更修正を、コミットするためのコマンドです。
-mのオプションはどのような変更を行ったのかメモを残せます。どのような修正をしたかがわかりやすくなります。
##git log
コミットの履歴が確認できます。
COVID-19Hokkaidoデータ編②オープンデータ化＋自動更新へ向けて

## もくじ
[COVID-19Hokkaidoデータ編①スクレイピングなどによる初期データ作成](https://qiita.com/Kanahiro/items/b47984fbf77f4e632663)
[COVID-19Hokkaidoデータ編②オープンデータ化＋自動更新へ向けて](https://qiita.com/Kanahiro/items/8f0768708d2c47ae3206)←この記事だよ！
[COVID-19Hokkaidoデータ編③完全自動化](https://qiita.com/Kanahiro/items/782cb6d5497d3c3704ec)

![スクリーンショット 2020-03-10 17.37.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73197/cfee968c-cffb-cc29-67c0-76b076fa30cd.png)

①では上図V0についてまとめましたが、今回の記事はそれ以降、オープンデータポータルなど外部API活用までをまとめます。

## V0での課題
V0ではデータの取得は①道ウェブサイトからのスクレイピング、②札幌市提供の静的なCSVファイルに依存していました。
これには以下のような問題があります。

- スクレイピングしたデータではなく、ちゃんとオープンデータとして公開されているデータを使いたい
- スクレイピングは、ウェブサイトのtable構造の変化に対し脆弱
- CSVファイルが更新されるたびに毎回プッシュする運用の手間

ではどうなったらラクなのかというと、上図のV1以降？となっている左下のフローが実現すればとてもラクです。

現在は（おそらく）エクセルでこさえた表形式のデータを、利用者がみやすいようにPDFなどに変換して公開していたり、HTMLに直でデータが掲載されていたり、いわゆる機械判読が困難なデータに仕上がっている状況にあります（誰でもすぐ読み取れる資料を、という意図はわかります）。今回のウェブサイトも、たとえば陽性患者データすらPDFで提供されていたらデータの収集が困難だったと思います（最低限HTMLのテーブルだったから無理やり読めた）。様々な情報を生データ（CSVなど）で、オープンデータとして配布すれば、こんな良い事があるよ、と、今回の事案で多くの方に認識されればなぁ。

という私のお気持ちが実現すれば左下のカタチになるわけです。近い将来そうなったら良いなぁ。

とか余裕ぶっこいてたらなんと2日くらいしたら実現しました。

## オープンデータへの移行
#### 北海道
北海道のデータがウェブサイトだけではなく[北海道オープンデータポータル](https://www.harp.lg.jp/opendata/)にも随時更新される事となりました。北海道の担当者がこのポータルに最新のCSVファイルを随時アップロードする仕組みです。名前のとおり、ここで公開されるデータはオープンデータで、誰でも無料でCSVデータにアクセス出来ます。

#### 札幌市
また札幌市も同様にオープンデータのポータルサイト[札幌市ICT活用プラットフォーム DATA SMART CITY SAPPORO](https://data.pf-sapporo.jp/)を運営しており、窓口相談件数データなどがオープンデータとして公開されました。データの作成は北海道と同じく担当者の作業。ありがたい限りです。

ものすごいスピード感でした（こういったポータルという土壌があったからこそスムーズに移行出来たんだなぁ）。行政のイメージが覆るようなスピード感に負けじと、前回のスクリプトをオープンデータポータルに対応させる修正を行いました。

https://github.com/codeforsapporo/covid19hokkaido_scraping/tree/f3923df7f6a3781e94ef5b514c9d9ec7fe5aa4b1
※本記事執筆時点のコミットまでさかのぼっています

main.pyを実行すると、settings.pyのREMOTE_SOURCESに入力されたデータを巡回してjsonなどを吐き出すようになっています。
今回公開されたCSVデータはAPIを通してファイルにアクセス出来ますが、結局CSVデータを読み出す必要があったため、API経由のアクセスではなくリソースへの直リンクです。読み込んだCSVをdictに変換し、jsonにdumpします。

本リポジトリ上で、main.pyの実行は15分おきにスケジューリングされており、gh-pagesブランチにjson類を吐き出します。
なので、各ポータルのデータが更新されれば15分以内にはjson類にも反映されます。これらjson類には外部からCORS制限なくアクセス可能（のよう）です。つまり<b>擬似的なAPIサーバー</b>として機能する訳です。
フロント側で非同期通信でそれらjson類を読み出すようになれば、データ更新の完全自動化が実現します。
※現状、json生成時にバリデーションなどがないため、完全自動化にはまだリスクが高く実装はしていません

## 終わりに
前回まではウェブサイトのスクレイピングと静的CSVファイルでデータをこさえていましたが、北海道、札幌市それぞれの常識が覆るスピードでのオープンデータ公開により、トップの図で示された理想的なカタチが実現しました。確かに新型コロナウイルスをきっかけとした変化ですが、そもそもポータルサイトがなければこれほどスムーズな動きにはならず、そういったサイトが作られるには地道な活動があったはずです。先人の活動に感謝しつつ、より前に進められればと思う限りです。
Sequel ProでEC2のデータベースと接続する/ログインする方法


## 接続方法
AWSのデータペースを確認するために、Seaquel Proで確認したいと思って調べて接続できたので、方法をまとめました

### Seaquel Proを開きます
[![Image from Gyazo](https://i.gyazo.com/a33369241dc3be511bb20f7cb1343500.gif)](https://gyazo.com/a33369241dc3be511bb20f7cb1343500)


名前：なんでも可能
MySQL ホスト：127.0.0.1
ユーザ名：root
パスワード：ご自身で作成したMySQLのrootユーザのパスワード
データベース：未記入
ポート：未記入
SSHホスト：EC2で設定した'Elastic IP'
SSHユーザ：ec2-user
SSH鍵：ご自身が保持しているEC2インスタンスの秘密鍵（○○.pem）を選択
SSHポート：未記入
SSLを使用して接続：チェック入れない

### EC2インスタンスの秘密鍵（○○.pem）を選択する方法
まずは場所の確認

```:ターミナル
    $ cd ~/.ssh
.ssh$ pwd
/Users/owner/.ssh
```
しかし、 .sshフォルダはありません。

[![Image from Gyazo](https://i.gyazo.com/3ab912f2be183460abec6d93331114e7.png)](https://gyazo.com/3ab912f2be183460abec6d93331114e7)

「不可視ファイルを表示」に☑️をつけます
[![Image from Gyazo](https://i.gyazo.com/ed08a7a898ce973a8e6420e5bd150ada.png)](https://gyazo.com/ed08a7a898ce973a8e6420e5bd150ada)
すると.sshフォルダが存在しますので、そこでpemを選択します

## 参考記事
[EC2上のmysqlにSequelProから接続](https://qiita.com/pieroplus/items/c0651030d9b12ad2aa65)
macでstsにlombokをインストールする

単純な事で苦戦したのでメモ。

1.ダウンロードしてlombok.jarを開く
2.自動でIDE検索が行われなかったので、Specify locationを押下
3.ネットで手順を検索するとlocationに.exeや.appを選んでいた為、
それに倣ってみたところインストール出来ず、、、
4.なんとなく.iniをlocationに選択したらインストール成功。何故。
Git コマンド

Gitコマンドについて

普段はEclipseを介して、操作しているのでコマンドを打つ機会がないので勉強ついでに記載する

環境
 Windows10 Home
 Git Bash
 2.17.0

# ■git log
### gitにコミットした履歴

```
git log
```

### コミットしたファイル名のみを取得

```
git log -p --name-only
```

### コミットしたファイル名から、特定の文字列が消えていることを確認
例はpythonファイルから、@をgrepする

```
git log -p --name-only | grep .py | xargs grep @
```

### N個前まで取得する

```
git log -p -2
```

# ■git branch
### ブランチの情報を取得
何も指定しない場合は、ローカルのブランチが表示される
リモートのブランチを表示する場合は、-r
両方取得したい場合は-aを付ける

```
git branch # ローカル
git branch -r # リモート
git branch -a # 両方
```

### パターンに一致したブランチ名を取得
ワイルドカードは使用可能

```
git branch --list *feature*
```

### ブランチの削除

```
git branch -d branchName
```

### ブランチの作成

```
git branch branchName
```

### ブランチをソート
=の後に、ソートキーを指定する

```
git branch --sort=authordate
```

# ■ブランチの切替

### ブランチの切替

```
git checkout branchName
```

### パターンに一致するブランチ名に切替
ブランチを切り替えるとき名前が長い場合やコピペするのが面倒な場合があるので

```
git branch --list *branchName* | xargs git checkout
```
重み付き確率分布を用いた乱数生成

# やりたいこと
確率質量関数(PMF: Probability Mass Function)を与えて、
一様でなく不均一な分布を用いて乱数を生成したい。
ちなみに`Python`で書くと`numpy`を使って下記の通りに簡単に書ける。

```python
import numpy as np

pmf = [0.22, 0.5, 0.28]
# 22%の確率で0, 50%の確率で1, 28%の確率で2
np.random.choice(3, p = pmf)

```

# 実装
## 1. naiveな実装

筆者が`C`を使っていた頃に用いてた方法。

```rust
use rand::Rng;
use rand::rngs::ThreadRng;
use rand::thread_rng;

fn naive_impl(rng: &mut ThreadRng, pmf: &[f64]) -> usize {
  let mut rep = 0;
  let mut sum = 0.0;
  let v: f64 = rng.gen();
  for p in pmf.iter() {
    sum += p;
    if v < sum {
      break;
    }
    rep += 1;
  }
  rep
}

fn main() {
  let mut rng = rand::thread_rng();
  let pmf = [0.22, 0.5, 0.28]; // 任意
  
  let num = naive_impl(&mut rng, &pmf);
}
```

## 2. `WeightedIndex`を使う方法

```rust
use rand::rngs::ThreadRng;
use rand::distributions::{Distributions, WeightedIndex};

fn main() {
  let mut rng = rand::thread_rng();
  let pmf = [0.22, 0.5, 0.28]; // 任意
  
  let dist = WeightedIndex::new(&pmf).unwrap();
  let num = dist.sample(&mut rng);
}
```

# 実測

1億回実行して速度を測ってみる。
実際に望む通りに乱数が生成されているかもチェックする。

```rust
use rand::Rng;
use rand::rngs::ThreadRng;
use rand::distributions::Distribution;
use rand::distributions::WeightedIndex;
use std::time::Instant;

fn naive_impl(rng: &mut ThreadRng, pmf: &[f64]) -> usize {
    let v: f64 = rng.gen();
    let mut sum = 0.0;
    let mut rep = 0;
    for c in pmf.iter() {
        sum += c;
        if v < sum {
            break;
        }
        rep += 1;
    }
    rep
}

fn main() {
    let mut rng = rand::thread_rng();
    let pmf = [0.22, 0.5, 0.28];
    let trial = 100_000_000;

    println!(“\n# Naive”);
    let start = Instant::now();
    for _ in 0..trial {
        naive_impl(&mut rng, &pmf);
    }
    println!(“w/o insertion -> {:?}“, start.elapsed());
    let start = Instant::now();
    let mut c = [0; 3];
    for _ in 0..trial {
        c[naive_impl(&mut rng, &pmf)] += 1;
    }
    println!(“w/  insertion -> {:?} {:?}“, start.elapsed(), c);

    println!(“\n# WeightedIndex”);
    let start = Instant::now();
    let dist = WeightedIndex::new(&pmf).unwrap();
    for _ in 0..trial {
        dist.sample(&mut rng);
    }
    println!(“w/o insertion -> {:?}“, start.elapsed());
    let mut c = [0; 3];
    let start = Instant::now();
    let dist = WeightedIndex::new(&pmf).unwrap();
    for _ in 0..trial {
        c[dist.sample(&mut rng)] += 1;
    }
    println!(“w/  insertion -> {:?} {:?}“, start.elapsed(), c);
}
```

結果。

```bash
# Naive
w/o insertion -> 869.118501ms
w/  insertion -> 1.619900124s [21997730, 49998808, 28003462]

# WeightedIndex
w/o insertion -> 1.000642238s
w/  insertion -> 1.586865294s [21993674, 50010827, 27995499]
```

なぜ優位が逆転しているのかわからないが、
`WeightedIndex`の方が簡潔なので推奨されると思う。
開発環境と本番環境での、db:resetとdb:migrate

railsで、作成したwebアプリをherokuへデプロイする際にdbがうまく反映されず、詰まったので簡単に備忘録(自戒)として残しておく。


# 経緯

開発環境でdbにカラムを追加する際に、一度作ったカラムと同じ名前のものを作成しようとしたことで、migrationが途中で中断され、中途半端なmigraionファイルが作成された。`db:rollback`して`db:migrate`するもエラーが出現して解決方法がわからず、ググると、`db:reset`して、`dn:migrate`する方法や`rails db:migrate:reset`などの方法が書かれていたが、resetコマンドに恐怖を感じたこと、開発環境では問題なく動作していたことで、「ま、いっか」と開発を続けてしまった。

そのことを忘れて、herokuへデプロイしてしまい、createアクション時にエラーが出現して、そのことを思い出して、解決方法をググった。

# 開発環境での解決

初めは、`db:reset`して、`db:migrate`したが、同じカラムが存在しているというエラーが出現したため、半ば諦めつつも、`rails db:migrate:reset`コマンドを行うと、すんなり通った。

これもググった結果だが、migrationする順番の違いで、初めの操作はうまくいかなかったのかな？恐らく

# 本番環境での解決

[heroku上のDBをリセットする](https://qiita.com/G-awa/items/792b7cd60205823f7ac0)を参考にして、

```shell

heroku pg:reset DATABASE_URL

heroku run rails db:reset

heroku run rails db:migrate
```

としたが、ここで何故かheroku上で同じエラーが出現。
原因がわからず、heroku上でadminに入り、カラムを確認すると、以前と同じ状態。

もう一度慎重に、上記を繰り返したが、それでもだめ...

途方にくれ、さらにググると、以下の記事を発見。

[Herokuでデータベーススキーマを変更したとき→db:migrateしてheroku restartする](https://seinzumtode.hatenadiary.jp/entry/20120527/1338102726)

上記を参考に、`heroku restart`すると、正常に動作した^^

# 最後に

初学者の私は、db関連のエラーに拒否反応が出てしまい、問題を先送りにしてしまっていた。
そんな私への自戒として、この記事を残しておく。

間違っている箇所や、もっと簡単な方法などございましたら、ご教示くだされば幸いです。
【ColdFusion】多次元配列の初期化方法

多次元配列を、`arraySet`関数を使って初期化する方法です。

```cfscript:cfscript
Dat1 = arrayNew(3);
d1 = 2;
d2 = 10;
d3 = 3;
for(i = 1; i <= d1; i++){
    for(j = 1; j <= d2; j++){
        arraySet(Dat1[i][j], 1, d3, "");//空文字で初期化
    }
}
writeDump(Dat1[2][10][3]);//参照してもエラーにならない
```

[動作するサンプルはこちら](https://cffiddle.org/app/file?filepath=316378c9-db5f-42f9-af09-7b72d62b9a32/b832ad97-10ab-4911-ad1f-f112d8469e10/6f8a8faf-c64a-4e21-91e2-8ae8a461669f.cfm)
docker-machineでLaravel+laradock

# はじめに
自分の備忘録として作りました。

### Laradockの準備
まずプロジェクトのディレクトリを用意します。

```
$ mkdir MyProject
$ cd MyProject
```

laradockのインストールと`.env`ファイルを用意します。

```
$ git clone https://github.com/LaraDock/laradock.git
$ ls
laradock # これがクローンされていると思います
$ cd laradock
$ cp env-example .env
```

そして、以下の３行をファイルに書き込みます。

```
$ vim .env
DB_HOST=mysql
REDIS_HOST=redis
QUEUE_HOST=beanstalkd

# MySQLの設定もします
MYSQL_VERSION=5.7

# 自分の場合、phpmyadminでポート被りが発生するので以下のようにしてます
PMA_PORT=8880

# 場合によってはコンテナ内の.envで見つかります
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=default
DB_USERNAME=default
DB_PASSWORD=secret
```

これで`laradock`の準備は完了です。

### Dockerの準備

先ほどの`laradock`フォルダ内で行います。

```
$ docker-compose up -d nginx mysql workspace phpmyadmin
```

dockerの準備はOKです。

### Laravelプロジェクトの作成

```
$ docker-compose exec --user=laradock workspace bash
laradock@84df08e29420:/var/www# apt-get update
laradock@84df08e29420:/var/www# composer create-project --prefer-dist laravel/laravel MyApp "6.*"
laradock@84df08e29420:/var/www# ls
laradock MyApp
laradock@84df08e29420:/var/www# exit
```

### PATHと権限の設定
コンテナを止めてから、`.env`へ修正しにいきます。

```
$ docker-compose stop
$ vim .env
# Point to the path of your applications code on your host
APP_CODE_PATH_HOST=../MyApp
```

```
$ docker-compose up -d nginx mysql workspace phpmyadmin
$ docker-compose exec --user=laradock workspace bash
laradock@84df08e29420:/var/www/MyProject# chmod 777 storage -R
laradock@84df08e29420:/var/www/MyProject# chmod 777 bootstrap/cache
```

もしポートでエラーを吐いたら、`phpmyadmin`のポートを`8880`にでもしておきましょう。任意のポートでおっけーです。

### 注意点
`php`コマンドが使えない！！ってなったら、コンテナ内にいきましょう。使えるようになると思います。

```
$ docker-compose exec --user=laradock workspace bash
# 出たくなったら
$ exit
```

あとphpmysqoadminのログインは以下のようになります。

```
server:MySQL
user:default
password:root
# おそらくこれは変更できます
```

MySQLのコンテナでのログインは以下です。

```
$ docker-compose exec mysql bash
# passwordは.envのroot_passwordです

# mysql -u root -p
```

### 参考
[Laravel 5.8 インストール](https://readouble.com/laravel/5.8/ja/installation.html)
[laradockのworkspaceコンテナからmysqlコンテナに接続する方法](https://qiita.com/dmrt/items/330ba9b5049bba9cf92c)
deviseのTwitter認証での「Unauthorized 403 Forbidden」の対処法

ローカルでのRailsの開発中に下記のエラーが出ました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403521/72293ecd-4e3d-bec2-8728-130a16b9cc54.png)

原因は[Twitter Developer](https://developer.twitter.com/)のcallbacksにローカルのURLを登録していないことが原因でした。

該当アプリケーションのコールバックの設定で下記の様にローカルのURLを設定して下さい。また、本番環境でこの現象が起きたら本番のURLを設定して下さい。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/403521/7eef1552-a5f2-9fb2-bbee-8fd93e8039f0.png)
[Spark] DataFrameで "" と null と [ ] のトラップにハマった話

Spark2の本当は怖い？DataFrameの話。

# 開発環境
ちょっと前に書いていた記事なのでバージョン古めです。

- Python 2.7.15
- Spark 2.1.2

# CSV読み込みでハマる例

```input.csv
x,y,z
1,,2
```

```python:pyspark
>>> df = spark.read.csv("input.csv", header=True)
>>> df
DataFrame[x: string, y: string, z: string]
>>> df.show()
+---+----+---+
|  x|   y|  z|
+---+----+---+
|  1|null|  2|
+---+----+---+
```

こういうファイルを読み込むと空のフィールドには "" ではなくnullが入ります。
言い換えると、CSVで保存すると "" とnullは区別できなくなります。ご注意を。
もっとも、別のSparkアプリで読み込むようなデータなら、CSVなんか使わずにParquetとかAvroで保存するなど、やりようはあるでしょうけど。

# 文字列関数がらみでハマる例

先ほどの ``df`` を使いまして。

```python:pyspark
>>> df.select(pyspark.sql.functions.length("y")).show()
+---------+
|length(y)|
+---------+
|     null|
+---------+
# わかる。

>>> df.select(pyspark.sql.functions.split("y", " ")).show()
+-----------+
|split(y,  )|
+-----------+
|       null|
+-----------+
# まあわかる。

>>> df.select(pyspark.sql.functions.size(pyspark.sql.functions.split("y", " "))).show()
+-----------------+
|size(split(y,  ))|
+-----------------+
|               -1|
+-----------------+
# -1なの? まあいいけど...

>>> df.fillna("").show()
+---+---+---+
|  x|  y|  z|
+---+---+---+
|  1|   |  2|
+---+---+---+
# nullを "" に置き換えました。

>>> df.fillna("").select(pyspark.sql.functions.length("y")).show()
+---------+
|length(y)|
+---------+
|        0|
+---------+
# "" だもんね。

>>> df.fillna("").select(pyspark.sql.functions.split("y", " ")).show()
+-----------+
|split(y,  )|
+-----------+
|         []|
+-----------+
# せやな。

>>> df.fillna("").select(pyspark.sql.functions.size(pyspark.sql.functions.split("y", " "))).show()
+-----------------+
|size(split(y,  ))|
+-----------------+
|                1|
+-----------------+
# えっ0じゃないの??

>>> df2 = spark.createDataFrame([[[]]], "arr: array<string>")
>>> df2
DataFrame[arr: array<string>]
>>> df2.show()
+---+
|arr|
+---+
| []|
+---+

>>> df2.select(pyspark.sql.functions.size("arr")).show()
+---------+
|size(arr)|
+---------+
|        0|
+---------+
# なんであっちが1でこっちが0なんだ...

>>> df.fillna("").select(pyspark.sql.functions.split("y", " ")).collect()
[Row(split(y,  )=[u''])]
# Oh... 確かにPythonでも len("".split(" ")) == 1
# ということは勝手に引っ掛かっただけか...orz
```

``show()``の出力では、空の配列 ``[]`` と空文字列が1個入った配列 ``[""]`` は区別できないのですね…
意外とこういう仕様は[ドキュメント](https://spark.apache.org/docs/latest/api/python/pyspark.sql.html#module-pyspark.sql.functions)にちゃんと書かれていないのです。焦った。
lgtm.in 復活してるってよ Looks Good To Me! 

## LGTM 画像

チームメンバーのコードに「いいじゃん!」をつける画像のことですね。

[![LGTM](https://www.lgtm.in/p/EoyHeNanq)](https://www.lgtm.in/i/EoyHeNanq)

[![LGTM](https://www.lgtm.in/p/IuWAh93oq)](https://www.lgtm.in/i/IuWAh93oq)

## lgtm.in

たくさんの LGTM 画像が集められているサイトでしたが、多くの人に惜しまれながらずっと昔に閉鎖。管理者さんいわく「これにかかずらっている時間がない!」とのことでした。でも復活しておられるようですね。

- [https://www.lgtm.in/](https://www.lgtm.in/)

[![LGTM](https://www.lgtm.in/p/WR8H3hY8q)](https://www.lgtm.in/i/WR8H3hY8q)

最近はどこでも Markdown なので、 Markdown テキストが各画像にあらかじめ用意されているのが嬉しいです。気に入った画像を開いて、「Markdown」欄のテキストをコピペして使いましょう。

[![LGTM](https://www.lgtm.in/p/6phSCxsaq)](https://www.lgtm.in/i/6phSCxsaq)

みんなでレビュー欄を賑やかに! 明日からレッツ LGTM!

## (2020-03-13)追記

あっ……

![issue.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/270842/fb61eed4-e76b-75ee-8cb3-3130ed7eb9e8.png)
FinderでFolderの容量を表示する (Mac)

# FinderでFolderの容量を表示する (Mac)

↓ こうする方法

<img width="1051" alt="finderFolderSizeDisplayed.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472945/7df2eff2-92a6-dc51-2965-4c3e39b587c1.png">

# やり方

Finderで容量を表示させたいFolderを開く。（上の画像の例ではCodeフォルダ内の容量を表示させている）

Finder > View > Show View Options (cmd + j)

![showViewOptions-min.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472945/27955a0a-c520-52d4-b1ab-6689a16cc413.png)

calculate all sizes を選択

<img width="282" alt="calclateAllSize.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/472945/de587ff7-8479-1ae3-b932-25e25095761c.png">

以上
Dockerについて参考になったWebサイトURL

## 概要
Dockerについて調べたので、参考になったURLをまとめます。
「Dockerってなんなの？」から、実際にDockerをインストールして仮想Webサーバを立てるところまでが対象です。

## Dockerの概要
・[Dockerイメージの理解とコンテナのライフサイクル](https://www.slideshare.net/zembutsu/docker-images-containers-and-lifecycle)
・[Docker導入のための、コンテナの利点を解説した説得資料](https://qiita.com/niisan-tokyo/items/88a53a1b4aa7ad60723e)

## Docker導入手順
・[DockerをMacにインストールする](https://qiita.com/kurkuru/items/127fa99ef5b2f0288b81)
・[Docker 入門ハンズオン資料](https://qiita.com/zembutsu/items/891c7ffd2c36097400b1)

## Dockerのネットワーク周り
・[Dockerのネットワークを理解するために覚えたことまとめ](https://christina04.hatenablog.com/entry/2016/07/22/193000)
・[Dockerのネットワークの基礎](https://deeeet.com/writing/2014/05/11/docker-network/)
dhcpd.lease を PHP で解析、CSV出力してみたりする！

いままでDHCPサーバは、ルータに付属している機能を使用していたのですが、折角Linuxサーバが起動しているのに使ってなかったのでそのネタです。しかもDHCPサーバの立ち上げ方でなくログ(dhcpd.leases)の解析であります。

# dhcpd.leases を解析してみる
dhcpd サーバが起動しているときDHCPクライアントに払い出された情報（貸し出しデータベース、って言うらしい）が `/var/lib/dhcp/dhcpd.lease` に出力されます。ただ接続機器が多いと出力結果をパッと見でわかりづらい（わからん）のです。なのでいい解析ツールがあればということで探してみました。

ちなみに dhcpd.lease は下記のフォーマットで出力されます。
[dhcpd.leases Format](https://linuxjm.osdn.jp/html/dhcp2/man5/dhcpd.leases.5.html)

# とりあえず Git で探してみる
Git で [dhcpd.leases](https://github.com/search?q=dhcpd.leases) 探してみると結構あります。とりあえず PHP でよさげなのを探してみました。

[jpereira/php-dhcpdleases](https://github.com/jpereira/php-dhcpdleases)

JSON形式にも出力できるし使い勝手がよさそう。

# 時間がUTCなんだが…
出力結果の時間をみるとなんだか +9時間ずれている、と思ったら、タイゾーンが UTC でした。
なので解析時に UTC ⇒ JST 変換するロジックを追加してみる。

```class.DhcpdLeases.php
$m[2] = trim($m[2], '"');
if ($this->filter_field && $this->filter_value) {

    if ($this->filter_value != $m[1]) {
        //echo "TESTANDO: (".$this->filter_value." == ".$m[2].")<br>";
        //continue;
    }
}

// UTC->JST ここから追加
if ($m[1] == 'starts' or $m[1] == 'ends' or $m[1] == 'tstp' or $m[1] == 'cltt' ) {
    if (preg_match("/^.* (.*) (.*)/", $m[2], $dt)) {
        $date = new DateTime($dt[1] . " " . $dt[2], new DateTimeZone('GMT')); 
        $date->setTimeZone(new DateTimeZone('Asia/Tokyo'));
        $m[2] = $date->format('Y/m/d H:i:s') ;
    }
}
```

# CSV出力が欲しい
JSON形式でもいいのですが、自分はExcelでちゃちゃっとみたいって思う時の方が多いので処理を追加してみる。

```class.DhcpdLeases.php
function PutArrayCSV($putCSV_file = null)
{
    $p = $this->row_array;
    $outputFile = new SplFileObject($putCSV_file, 'w');

    $outputFile->fputcsv(array("ip", "starts", "ends", "binding", "hardware-ethernet", "tvendor-class-identifier", "client-hostnamen"));
    foreach($p as $key => $value) {
        if (!isset($p[$key]['client-hostname'])) { $p[$key]['client-hostname'] = ""; }
        if (!isset($p[$key]['vendor-class-identifier'])) { $p[$key]['vendor-class-identifier'] = ""; }
       
        $outputFile->fputcsv(array($key, $p[$key]['starts'], $p[$key]['ends'], $p[$key]['binding'], $p[$key]['hardware-ethernet'], $p[$key]['vendor-class-identifier'], $p[$key]['client-hostname']));
    }
}
```

呼び出してみる

```test.php
<?php
require_once("class.DhcpdLeases.php");

// main()
$dl = new DhcpdLeases("/var/lib/dhcp/dhcpd.lease");

if ($dl->process() > 0) {
    $p = $dl->GetResultArray();
    $dl->PutArrayCSV("test.csv");
}
?>
```

思いとおりの出力！満足ｗ
スマフォ、タブレットなど以外と接続していることが判る（無駄遣いしているという説もある）、面白いですね。

# 自宅で運用する？？
とりあえず勢いで作ってみたが、これ年に数回使うかどうかなのかなって感じ？？なのかな。
会社で運用するとしたら「不正な機器が接続された？」とか監視するに役立つのかもしれませんね。

[いますぐ実践! Linux システム管理 / Vol.251](http://www.usupi.org/sysad/251.html)
Debian(Linux)インストール時の「grub-install dummy failed」に関する情報

#はじめに
新しいPCを組んで、Debianを入れたりUbuntuを入れたり、Debianで最新のカーネルをビルドして適用したりして遊んでいました。
そして、また新しくDebianをインストールし直そうとしたら、「grub-instal dummy faild」というエラーが出ました。
あれ？と思い、Ubuntuのインストールも試したところ、同じくgrubのインストールで失敗しました。
それ以降、どちらのOSもインストールできなくなってしまいました。
いろいろ試して何とか直せたので、なぜ直ったのかわかりませんが、やったことを書いておきます。

#環境
CPU: AMD Athlon 200GE
GPU: Raedon Vega 3(CPU内蔵)
マザーボード: ASUS PRIME B450M-A
SSD: SanDisk SDSSDH3 250G
OS1: Debian-10.3
OS2: Ubuntu-ja-18.04.3

#作業
- SSDのSecure Eraseを行う。
  - Ubuntu Live USBからブートし、端末(ターミナル)を起動してスーパーユーザに切り替える。
  - `$ sudo -i`
  - [こちら](https://qiita.com/nvsofts/items/f46c8a1b3541894ad382)の記事の通りにSecure Eraseを実行する。
- CMOSクリアを行う。
  - マザーボードの説明にある手順通りにCMOSクリアを行う。
- CSMを無効にする。
  - UEFI BIOSの設定を起動しブートの項目からCSMを無効にする。
- OSをインストールする。
  - 通常の手順でインストールする。
  - 途中で、「BIOS互換モードのOSがあります。UEFIを強行しますか。」的なメッセージが出ますが、強行します。

#おわり
不要な作業も含まれているかもしれませんが、私の場合は以上の手順でインストールに成功しました。
不思議なのはSSDをSecure Eraseしたはずなのに、インストール時に他のOSがあると判断されることです。
実際はSecure Eraseできずに、内容が消えていないのかもしれませんが私にはわかりません。
推測しかできませんが、いろいろやっているうちにBIOS互換モードに設定されて、その情報がずっと残っていたせいで失敗していたのかもしれません。
CSMを無効にし、UEFIを強制することでインストールできるようになったのではないかと考えています。

同じエラーが発生している方の助けになれば幸いでございます。

#参考文献
[SSDをSecure Erase機能で安全に消去する](https://qiita.com/nvsofts/items/f46c8a1b3541894ad382)
GoogleDriveにある大量のデータをダウンロードするときの注意

GoogleDriveの容量を空ける，という話題になると必ず出てくるのは

「共有後にオーナーを変更」

新しいアカウントを作り，そのアカウントとデータを共有後，データのオーナーを新アカウントに設定することでデータの引っ越しが可能です．

「一旦PCにダウンロード▶新規アカウントにアップロード」なんてしなくても，新しいアカウントにデータを引っ越せば空き容量が確保できるといううまい話なのですが，

オーナーの変更が可能なのは一部のファイル（Google DocsやSpreadsheets）で，普通のファイルは無理．

オーナーを変更しなくても，新アカウントにデータを共有後，そのデータを元アカウントから削除すると，一見移動できているように見えます．

しかしこれは落とし穴でして，全てのファイルはオーナーアカウントの容量を食っているため，オーナー権限の委譲を行わないと「マイドライブには残ってないのに容量は食う」という事態が発生します．


そんなわけで，僕の様にGoogleDriveに大量の非GoogleDocsファイルを保存している人間は，ひとまずPC上に全部ダウンロードしたくなることもあるでしょう．

さてダウンロードするとき，当然zipに圧縮された状態でダウンロードされます．

そしてダウンロードするデータが大きすぎると，複数のzip（例えばFirst.zip, Second.zip ..）に分けてダウンロードされます．

各zip内の階層構造は，元のドライブの階層構造と同じですが，なにぶん分割されてダウンロードされている訳なので，
例えばもともと
\A\B\file1,file2,file3
という構造だった場合，各zipの解凍後には

file1はSecond\A\B\にあるのに
file2はThird\A\B\にある．

という大分面倒な状態になっています．

僕の場合はファイル数もフォルダ数も多すぎて手作業で元に戻すのは不可能でした．ですので次の方法をとりました．

①https://www.himadara.info/entry/expand_all を参考にunZipAll.batを作成し，First.zip, Second.zip...をまとめて解凍
②次のようなmerge.batを作成し，元に戻す

```merge.bat
for /d %%a in (*) do ( if not %%a==mgd ( xcopy /s %%a mgd\ ) )
```
FlutterでgRPCを使うためのPC環境構築手順

# はじめに

Flutterアプリで`gRPC`を使うために必要な`ホストPC`のセットアップについてまとめています。

Flutterアプリで`gRPC`の使い方自体は[DartでgRPCを使う](https://qiita.com/kabochapo/items/6848457ea7a966baf957)を参考にすれば良いですが、`protoc`コマンドの実行のところで躓いたため、別途ここにまとめることにしました。

`gRPC`、めちゃ便利ですね。WebソケットやRESTより便利です。

# 1. Dart (Dart VM) インストール

`pub`コマンドが必要なため (`proto`コマンドのdart変換プラグイン内部で必要) 、Dart環境をインストールします。

### macOS

```shell:
$ brew tap dart-lang/dart
$ brew install dart
$ dart --version
Dart VM version: 2.7.1 (Thu Jan 23 13:02:26 2020 +0100) on "macos_x64"
```

### Linux (Ubuntu)

```shell:
$ sudo sh -c 'wget -qO- https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
$ sudo sh -c 'wget -qO- https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
$ sudo apt-get update
$ sudo apt-get install dart
```

Linux環境の場合、`pub`コマンドのパスが通ってないため、以下のようにパスを通します。

```shell:
$ export PATH="$PATH:/usr/lib/dart/bin"
```

# 2. ProtocolBuffers

`.proto`ファイルをDartファイルに変換するためのツールをインストールします。
ちなみに、gRPCの通信プロトコルが`ProtocolBuffers`で、シリアライズ＆圧縮されたデータを送受信します。

### macOS

```shell:
$ brew install protobuf
$ protoc --version
libprotoc 3.11.4
```

### Linux (Ubuntu)

```shell:
$ sudo apt install libprotobuf-dev libprotoc-dev protobuf-compiler
```

## 2-1. protocプラグイン for Dartのインストール

```shell:
$ pub global activate protoc_plugin
$ export PATH=$PATH:~/.pub-cache/bin
```

# 3. protoファイル → Dartファイル変換

```shell:
$ protoc --dart_out=grpc:${Dartファイルの出力先パス} -Iprotos ${.protoファイルのパス}/${ファイル名}.proto
```

# 参考文献

* [Dart Quick Start](https://grpc.io/docs/quickstart/dart/)
損保数理　日本アクチュアリー会

```{r}

#複合ポアソン分布　2-15

library(dplyr)

n=10

x=sample(1:100,n,replace=T)

p=x/sum(x);lam=sum(x)

t=sample(1:100,n,replace=T)

(lam*p*(exp(t)-1))

lam_i=t*lam*p

V_S=lam*sum(p*t^2);E_S=sum(t*p);

under=E_S+qnorm(0.05/2)*sqrt(V_S)

upper=E_S+qnorm(1-0.05/2)*sqrt(V_S)

#Jung method 4-13

I=5;J=3

nij=array(sample(1:10,I*J,replace=T),dim=c(I,J))

rij=array(sample(1:10,I*J,replace=T),dim=c(I,J))

#Broyden Quasi-Newton Algorithm p.213

f=function(s){

x=s[1:I];y=s[-c(1:I)]

f1=apply(-nij*c(y)+t(t(nij*rij)/c(x)),1,sum)

f2=apply(-t(t(nij)*c(x))+((nij*rij)/c(y)),2,sum)

return(c(f1,f2))

}

X=rep(1,I+J)

ite=1000

H=diag(f(X))

eta=0.001

for(l in 1:ite){

if(sum(abs(f(X)))>10^(-9)){  

X_pre=X  

X=X-eta*H%*%f(X)  

s=X-X_pre

y=f(X)-f(X_pre)

H=H+((s-H%*%y)/as.numeric(t(s)%*%H%*%y))%*%t(s)%*%H

print(sum(abs(f(X))))

}

}  






```
LGTMを戻す

# 概要
いいねに戻します。


LGTMの趣旨は、[こちらをご覧ください](https://blog.qiita.com/like-to-lgtm/)。
趣旨に対して異論はないです。

もっと良いChrome拡張機能がありましたので、こっちを使うことをおすすめします。
https://qiita.com/HirosuguTakeshita/items/f015fee48f42a41045ef

# やり方
ディレクトリーを掘る。`mkdir qiita`
２つファイルを作る。

```javascript:qiita/content.js
window.onload = function() {
  var button = document.querySelector('div.it-Actions_item-like button');
  button.innerHTML = '<i class="fa fa-fw fa-thumbs-up"></i>';
};
```

```json:qiita/manifest.json
{
  "name": "LGTM",
  "version": "1.0.0",
  "manifest_version": 2,
  "description": "LGTM Chrome Extension",
  "content_scripts": [{
    "matches": ["https://qiita.com/**/items/*"],
    "js": [
      "content.js"
    ]
  }]
}
```

Chromeの拡張機能を選んでデベロッパーモードを有効にします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77441/369c10a9-5b70-d0a1-d169-e46851794992.png)

パッケージ化されていない拡張機能を読み込むをクリックして作ったファイルのディレクトリーを選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77441/e1f25f80-bed4-d2e3-762b-0caa209fa829.png)

読み込まれると、こうなります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77441/19ccfc3f-d6af-267d-ec02-c2941b17a190.png)

記事を見ると戻ります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77441/dcc34bb0-efe2-51cb-1e6b-4af0097ba692.png)

# 差分
2020年3月12日 22時17分
自己の記事に対応してなかったのを修正しました。


# 下対応版
暫定版です。
こちらのバージョンはいいねするとLikeアイコンとLikeの文字が見えなくなります。

```javascript:qiita/content.js
window.onload = function() {
  var button = document.querySelector('div.it-Actions_item-like button');
  button.innerHTML = '<i class="fa fa-fw fa-thumbs-up"></i>';
  var button2 = document.querySelector('div.it-Footer_like button');
  if (button2) {
    button2.removeAttribute('style');
    button2.innerHTML = '<span class="fa fa-fw fa-thumbs-up"></span><span>Like</span>';
  }
  var svg = document.querySelector('div.it-Footer_like svg');
  if (svg) {
    svg.parentNode.removeChild(svg);
    var like = document.querySelector('div.it-Footer_like');
    like.insertAdjacentHTML('afterbegin', '<button><span class="fa fa-fw fa-thumbs-up"></span><span>Like</span></button>');
    like.className = "it-Footer_like";
  }
};
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/77441/1a09cf5d-3f6a-b1b7-795c-be4760d4d722.png)

# 勇者たち
[QiitaのLGTMボタンをLGTAにする](https://wand-ta.hatenablog.com/entry/2020/03/12/203553)
[QiitaのLGTMをSushiにするユーザースクリプト](https://qiita.com/m_fukuchan/items/0842637ae34d7e5aa004)
[[ネタ]強制的にLGTMをいいねに戻す方法[Chromeエクステンション不要]](https://qiita.com/Andhy/items/de9d7430ffc5b30670f5)
[LGTMはいやだ](https://qiita.com/HirosuguTakeshita/items/f015fee48f42a41045ef)
[Qiita Nonsense LGTM Button Killer](https://gist.github.com/mpyw/240b40a9003cdc689f04941225033faa)


# わたしの気持ち
この記事を書いた気持ちをブログに書きました。
[なぜ #Qiita の「LGTMを戻す」を作ったのか](https://kawahara-ci.hatenablog.com/entry/2020/03/14/LGTM)
Anaconda Navigatorでの仮想環境作成時の覚え書き

#この記事の目的
Anaconda Navigatorを用いて仮想環境を構築する際の, 自分用のメモです.

## STEP1
左側の「Environments」を選択して, 中央下の「Create」で新しい環境を構築
設定は, 適当に「Python 3.7」などの選択を行って完了.


## STEP2
右側上のプルダウンから, 「All」(もしくは「Notinstalled」)を選択して, 未インストールのライブラリが表示されるようにする.
右上の検索バーを使って, 以下のライブラリをインストールしていく.

```
#必須
notebook 
numpy
pandas
matplotlib


#機械学習用
scikit-learn
keras (tensorflowも併せてインストールしてくれる)


#自然言語処理用
gensim


#画像用
pillow
opencv
```

上が完了したら, 中央にある環境の実行ボタンを押して, 「Open with Jupyter Notebook」を選択.
この際, 上でnotebookをインストールしていないと, with Jupyter Notebookは選択できないので注意.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/540956/d2ffd76d-4a13-93ef-f58f-a1ab152788ef.png)

## STEP3
STEP2のGUI画面からでは追加できないライブラリをターミナルから追加する.


```
#matplotlibの日本語表示のため
pip install japanize-matplotlib

#拡張機能で便利にコーディングするため(特にHinterlandが便利)
pip install jupyter-contrib-nbextensions

```