OmniAICreator/Qiita-1.07M huggingface dataset:
PostgreSQL+Docker: クエリーログを出力する

[Docker公式のpostgresコンテナ]でクエリーログなどを出力する方法を紹介する。


## docker runコマンドの場合

`docker run`コマンドでpostgresコンテナを実行するとき、下記のようにロギングのオプションを指定することで、標準エラー出力にクエリーログなどが出力される。

```bash
docker run -it postgres:11.3 postgres \
  -c log_destination=stderr \
  -c log_statement=all \
  -c log_connections=on \
  -c log_disconnections=on
```

## docker-composeの場合

`docker-compose`の場合は、`docker-compose.yml`の`command`フィールドの`postgres`コマンドに下記のようなオプションを指定すると、標準エラー出力にクエリーログなどが出力される。

```docker-compose.yml
version: '3.7'
services:
  db:
    image: postgres:11.3
    # Make postgres logs. More information about logging, see official documentation: https://www.postgresql.org/docs/11/runtime-config-logging.html
    command: postgres -c log_destination=stderr -c log_statement=all -c log_connections=on -c log_disconnections=on
    logging:
      options:
        max-size: "10k"
        max-file: "5"
```

ログの表示方法は:

```
docker-compose logs -f db
```

ちなみに、`logging`については[dockerのログをローテートする - Qiita](https://qiita.com/suin/items/00f0172438f7cffe935e)を参照。

## 各コマンドオプションの補足

コマンドオプションの詳しい説明は[PostgreSQLの公式ドキュメント](https://www.postgresql.org/docs/11/runtime-config-logging.html)を参照してほしい。

### log_destination=stderr

* ログの出力先
* `stderr`, `syslog`, `csvlog`から選べるが、今回はDockerの標準エラー出力に出すために`stderr`を選択した。

### log_statement=all

* どのSQLをログに出すかの設定。
* `none`, `all`, `mod`, `ddl`から選択する。
* デフォルトでは`none`で何もクエリーログを出さない設定になっている。
* `all`にすると次のようなログが表示されるようになる:

```yaml
postgresql | 2019-06-17 07:05:01.681 UTC [32] LOG:  statement: START TRANSACTION
postgresql | 2019-06-17 07:05:01.684 UTC [32] LOG:  statement: SELECT 1 /* original connection */
postgresql | 2019-06-17 07:05:01.686 UTC [32] LOG:  statement: COMMIT
```

### log_connections=on

* コネクション接続時にログを出すかの設定。
* デフォルトでは`off`に設定されていて、何もログに出ない。
* `on`にすると次のようなログが出力される:

```yaml
postgresql | 2019-06-17 07:05:01.662 UTC [32] LOG:  connection received: host=172.19.0.3 port=37440
postgresql | 2019-06-17 07:05:01.664 UTC [32] LOG:  connection authorized: user=root database=test
```

### log_disconnections=on

* コネクション切断時にログを出すかの設定。
* デフォルトでは`off`に設定されていて、何もログに出ない。
* `on`にすると次のようなログが出力される:

```yaml
postgresql | 2019-06-17 07:05:11.683 UTC [31] LOG:  disconnection: session time: 0:00:10.046 user=root database=test host=172.19.0.3 port=37438
postgresql | 2019-06-17 07:05:11.687 UTC [32] LOG:  disconnection: session time: 0:00:10.025 user=root database=test host=172.19.0.3 port=37440
```


[Docker公式のpostgresコンテナ]: https://hub.docker.com/_/postgres
Docker で MySQL 使用時に日本語が文字化けしてプチハマりした件

# TL;DR
Dockerでlaradockを使って環境構築し、todo-appを作成。
dbコンテナに入りmysqlにログインしテーブルの確認をしたところ、日本語が文字化けしていた。ブラウザでは文字化けはしていなかった。

<img width="700" alt="mysql文字化け.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390893/b0e83a33-e7d3-c578-8763-096879714db9.png">


#対象者
* dockerを使って環境構築し、dbコンテナを使っている人。
* laradockを使って簡単に環境を作り、mysqlコンテナを使用している人

#解決方法
以下の記事を参考
[Dockerで立ち上げたMySQLにログインすると日本語が文字化け](https://qiita.com/luccafort/items/0553c589dcc6459746bc) 

記事と同様、文字コードがlatin1になっていたため、utf-8に変更する必要があるみたい。

`/etc/mysql/my.cnf`に以下を記入すれば良いらしいが...


```my.cnf
[mysqld]
character-set-server=utf8
collation-server=utf8_general_ci

[client]
default-character-set=utf8
```


コンテナ内なのでvimが使えずどうやって書き込めばいいんだ...と思い、地味にハマった(笑)

単純にコマンドで直接書き込めば良いことに気づき、以下を実行

``````dbコンテナ内で実行.
root@a2b43502b1fa:/etc/mysql# echo "[mysqld] character-set-server=utf8 collation-server=utf8_general_ci [client] default-character-set=utf8" > my.cnf 
```




**無事解決！！**
やった！文字化けなおった〜　
<img width="700" alt="mysql文字化け解決.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/390893/0b8a21ad-02d7-640c-3f95-453668bb351b.png">


#参考にした記事

* [Dockerで立ち上げたMySQLにログインすると日本語が文字化け](https://qiita.com/luccafort/items/0553c589dcc6459746bc) 
* [ターミナルのよく使うコマンド](https://qiita.com/ryo2132/items/b7e312b0eb50fc449841)
旧GitLabから新GitLab(Gitlab12)への移行

# 概要

* 会社の標準とされているGitサーバのGitLabが古すぎてかなわん
* サービス間連携とか一切できないので新しいGitLabを立てて移行してしまう
* 本当はGitHub使いたい。。エンジニア以外も使うとなるとコストバカにならない。
* でも意外と機能豊富でGitHubより実はいいんじゃね？と思っている
* CodeCommitも使っていたが、最近はAWSに依存しないようにしてるので

# 旧GitLabからコミットログなど含めてCloneしてくる

```
$ git clone --mirror http://gitlab.hoge.net/hoge/repohoge.git
Cloning into bare repository 'repohoge.git'...
remote: Counting objects: 72486, done.
remote: Compressing objects: 100% (26432/26432), done.
remote: Total 72486 (delta 50605), reused 64973 (delta 44691)
Receiving objects: 100% (72486/72486), 663.35 MiB | 39.67 MiB/s, done.
Resolving deltas: 100% (50605/50605), done.

$ cd repohoge
```

# 新GitLabへPUSHする

```
$ git push --mirror "https://gitlab.hogehoge.net/hoge/repohoge.git"
Username for 'https://gitlab.hogehoge.net': username
Password for 'https://username@gitlab.hogehoge.net': password
Counting objects: 68255, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (19677/19677), done.
Writing objects: 100% (68255/68255), 647.17 MiB | 28.85 MiB/s, done.
Total 68255 (delta 47251), reused 68255 (delta 47251)
remote: Resolving deltas: 100% (47251/47251), done.
remote:
:
:
 * [new tag]         aaaaa -> aaaaa
 * [new tag]         bbbbb -> bbbbb
```

超簡単！


# 遭遇したエラー

### "error: failed to push some refs ..."

* リモートとローカルのブランチに差異がある場合

```

 ! [remote rejected] master -> master (pre-receive hook declined)
 ! [remote rejected] develop -> develop (pre-receive hook declined)
:
:
 ! [remote rejected] aaaaa -> aaaaa (pre-receive hook declined)
error: failed to push some refs to 'https://gitlab.hogehoge.net/hoge/hoge.git'

```

### 新GitLab側でリポジトリを削除

* Gitlab上で対象のリポジトリに遷移する
* 設定→一般→展開→プロジェクトを削除で対象のリポジトリを削除

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/0d0b985e-a5c6-a4dc-e05b-be1fbdbbcdbf.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/f7801942-abd5-fb0a-4ac0-bbd77d8817ff.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/52db851a-0400-7324-7486-304d8982209e.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57350/3e76ccbb-d77f-a119-a818-729f7e3bfbbc.png)



### ローカル側で新たにPUSH

```
$ git push --mirror "https://gitlab.hogehoge.net/hoge/repohoge.git"
```

※ 上記はローカルリポジトリが正である場合に限る
Jupyter notebookのnotebook名を取得する

# TL; DR
jsを経由してnotebook名を取得する

```javascript
%%javascript
var notebook_name = document.body.attributes['data-notebook-name'].value
IPython.notebook.kernel.execute(`NOTEBOOK_NAME = '${notebook_name}'`);
```

# もう一つの方法
上の方法ではnotebook内にjsが混じってしまって統一感がないので，pythonで完結する方法も紹介する  

1\. iPythonのkernel idを取得する  

```python
import re
from IPython.lib import kernel

conn_file = kernel.get_connection_file().split('/')[-1]
kernel_id = re.findall('kernel-(.*)\.json', conn_file)[0]
```

2\. session一覧を取得する  

url: http://{jupyter_host}/api/sessions  
\* tokenやpasswordでログインしたcookieが必要  

3\. kernel idが一致するsessionを探してファイル名を取得する
mysqlで中央値(メジアン）を出す方法

mysqlには中央値を出す関数がない。

中央値のロジックを分解すると、

- データを昇順（もしくは降順）に並べて
- ちょうど真ん中のサンプルを取得

ということになる。
そのロジックを素直に実装した例をしめす。

以下サンプルデータ。

```sql
mysql> select * from users order by age ;
+---------+-----+
| name    | age |
+---------+-----+
| john    |  20 |
| ringo   |  20 |
| george  |  22 |
| paul    |  29 |
| pete    |  39 |
+---------+-----+
```

年齢の中央値を出すためのSQLがこちら。

```sql
PREPARE SET_STMT FROM 'select age from users order by age limit 1 offset ?';
SELECT FLOOR( COUNT(*) / 2 ) INTO @offset FROM users;
EXECUTE SET_STMT USING @offset;
```

実行結果

```sql

+-----+
| age |
+-----+
|  22 |
+-----+
```

##　解説

- ちょうど真ん中のレコードまでオフセットをずらして1行取得する
- そのオフセットの数とは、レコードの件数の半分の位置

5件のレコードなら、オフセットは2にして3件目を取得したい。そこで、レコードの件数を2で割ってあまりを切り捨てている。偶数のときには、前後のレコードから平均を取るというのが中央値の正しいルールだが、このロジックでは横着して件数が偶数のときには若い方だけをサンプルにしている。
「naming」タグについて (タグシノニム: 「命名規則」「ネーミング」「命名」）

### 対象
(件数は2019-06-17現在)

- https://qiita.com/tags/naming : 109件

### 説明

変数名や関数名、ソフト上のUIの名前など、命名をするときに考える事項。

### タグシノニム
(件数は2019-06-17現在)

- [https://qiita.com/tags/命名規則](https://qiita.com/tags/%E5%91%BD%E5%90%8D%E8%A6%8F%E5%89%87) : 89件
- [https://qiita.com/tags/ネーミング](https://qiita.com/tags/%E3%83%8D%E3%83%BC%E3%83%9F%E3%83%B3%E3%82%B0) : 11件
- [https://qiita.com/tags/命名](https://qiita.com/tags/%E5%91%BD%E5%90%8D) : 2件

Note: 「命名規則」タグは意味的に異なるかもしれないが、参考になると思われるのでタグシノニムとした。
[CSS]HTML内の記載方法（3種）と優先順位

# CSSの記載方法

- スタイルシートファイルを読み込む（外部ファイルリンク）

```html
<link href="style.css" rel="stylesheet" type="text/css">
```
  
- style要素でCSSを読み込む（headタグ内）  

```html
<head>
  <style>
    h1 { color: blue;}
  </style>
</head>
```
  
- style属性でCSSを記述する

```html
<h1 style="color: blue;">hoge</h1>
```

# スタイル適用の優先順位

1. style属性でCSSを記述する
2. style要素でCSSを読み込む（headタグ内）
3. スタイルシートファイルを読み込む（外部ファイルリンク）

# 実務でよく使われる順位

1. スタイルシートファイルを読み込む（外部ファイルリンク）
2. style要素でCSSを読み込む（headタグ内）
3. style属性でCSSを記述する
   ※特例でスタイルを適用させたいとき
Gitpod 2019/6リリースノート翻訳

[2019/6のリリースノート](https://www.gitpod.io/docs/release-notes/2019-06-17/june-2019/)の翻訳です、誤字、脱字、翻訳間違いがあったら申し訳ありません。

# 2019 6月
4月にGitpodが公開された後、VScodeの拡張機能をサポートなど内部アーキテクチャのスケール変更してクラウド密度を向上させるための変更に多くの時間を費やしました。この作業は完了していませんが、その途中で沢山の新機能を追加しました。

## 最大化の切り替え
タブをダブルクリックすることでそのタブを最大化することができます、シンプルですが便利な機能です。
![](https://www.gitpod.io/maximize-3a2a23b5882fa984e89ec2b45339cc40.gif)

## ターミナル内のリンク
ターミナルのリンクをクリックすることで、対応するファイルを開くことができます。
![](https://www.gitpod.io/static/6f1095ff221d805890029899cd39076f/b395d/terminal-link.png)

## 環境変数
Gitpodはユーザーが環境変数をワークスペースに注入することを可能にします。リポジトリ名に対する単純なパターンに基づいて、どの環境変数が実際に利用されるかをフィルタすることができます。また、すべての環境変数値はデータベースに格納される前に暗号化されています。

ユーザーベースの環境変数に加えて、起動時にコンテキストリンクを介して環境変数を渡すことができます。詳しくは[ドキュメント](https://www.gitpod.io/docs/47_Environment_Variables/)を参照してください。

## 双方向スクロール同期
マークダウンファイルを編集するときは、エディタの横にプレビューを表示するのが非常に便利です。エディタの右上にあるアイコンをクリックしてプレビューを開くことができます。この時、片方をスクロールするともう片側も同じ場所になるようにスクロールされます。
![](https://www.gitpod.io/scroll-sync-1c63878877c0cf0110458a2e672ecfed.gif)

[PR 5442](https://github.com/theia-ide/theia/pull/5442)によって寄付されました。

## Rustサポートの向上
Go VS Codeエクステンションに加えて、Gitpodは公式[Rust VSCode 拡張機能](https://github.com/rust-lang/rls-vscode)も利用できるようになりました。そして、より速くより信頼できるRustのサポートを期待してください。

## Emmet サポート
Gitpodは、HTML * CSSワークフローを大幅に改善することができるウェブ開発者のツールキットであるemmetをサポートしました。ショートカットを使ってhtmlボイラープレートを素早く生成することができます。
![](https://www.gitpod.io/static/6d5f7de9e31b01801ca9ef2468648047/a833b/emmet.png)
サポートの概要については[チートシート](https://docs.emmet.io/cheat-sheet/)を見てください。

## Javaのデバッグ
Javaアプリケーションのデバッグには、プロセス起動時にプロセスが誤ったJavaファイルを選択するという問題がありました。これを修正しました。

## より良いアップロード
ドラッグアンドドロップで大きなファイルをアップロードすることができます。加えてウィンドウ上部に適切な進捗情報を表示します。
![](https://www.gitpod.io/upload-7f5e0c5c892c013d9fc0e32e62780048.gif)

## 改善されたC++サポート
最新のバージョンを使用するように言語サービスをアップグレードしました。

## Git修正機能の向上
gitの修正機能のUIが改善され、複数のコミットを修正/潰したり(squash)できるだけでなく、元に戻すこともできます。
![](https://www.gitpod.io/git-amend-f3508cab6ea46499d2febd661f118db2.gif)
SCMのGUI全体もVS CodeのUXに合わせて書き直されました。

## ポート範囲の設定
あなたの.gitpod.ymlで[ポート範囲](https://www.gitpod.io/docs/43_Config_Ports/#port-ranges)を指定できるようになったので、全範囲で動作を管理してGitpodにそれらのポートの1つでサービスが開かれたときの動作を指示することができます。

## CLI (`gp await-port`)
cliは新しいことを学びました、それは`await-port`です。これは、アクションを待ってから特定のパスを開きたいときに便利です。

これは、ポート3000が利用可能になると、プレビューで特定のパスを開く例です。

```
gp await-port 3000 && gp preview $(gp url 3000)my/path/index.html
```

## 多くの小さな改良
これらのより大きな機能に加えて、我々は多くのバグを修正し、GitpodのパフォーマンスとUXを改善しました。 Gitpodの146のPRと[Theiaの220のPR](https://github.com/theia-ide/theia/pulls?utf8=%E2%9C%93&q=is%3Apr+merged%3A%3E2019-04-01+)をマージしました。

## 次は何ですか？
今回のリリースでもVS Codeの拡張機能が追加されましたね、今後のリリースでは、任意のVS Codeの拡張機能をインストールし、それを設定として.gitpod.ymlファイルに追加できるようになります。GitLabの統合と、インストールが簡単なGitpodを自分でホストするバージョンが進行中です。最後に、私たちは起動時間の改善を最適化すること、そしてもちろんバグを修正してあなたに素晴らしい開発経験を提供することを検討しています。
ラズパイにDHCP+DNSサーバを立ててみた

#はじめに
[未来電子テクノロジー](https://www.miraidenshi-tech.jp/intern-content/program/)でインターンをしています。
今回はラズパイにDHCPサーバを立てたので、その方法をご紹介します。
プログラミング初心者であるため、内容に誤りがあるかもしれません。
もし、誤りがあれば修正するのでどんどん指摘してください！

# DHCP+DNSサーバを立てていきまーす
```console
# dnsmasqをインストール
$ sudo apt install dnsmasq

# バックアップ作成
$ sudo cp /etc/dnsmasq.conf /etc/dnsmasq.conf.bak
```

```console
$ vim /etc/dnsmasq.conf
↓コメントアウトを外す
#conf-file=/etc/dnsmasq.more.conf

$ sudo vim /etc/dnsmasq.more.conf

# 以下の内容をdnsmasq.more.confに書いて保存

# ローカルホスト名を上位DNSに転送しない
domain-needed

# ローカルIPアドレスの逆引きを上位DNSに転送しない
bogus-priv

# ショートドメイン名を補完するドメイン名
local = /local/

# ローカルドメイン名
domain = local

# ショートホスト名を補完する
expand-hosts

# 192.168.0.100 ~ 192.168.0.200までのIPアドレスをDHCPで永久的に割り当てる
dhcp-range = 192.168.0.100, 192.168.0.200, infinite

# DHCPクライアントに通知するルータのIPアドレス
# dhcp-option = option:router, 192.168.0.1

# DHCPクライアントに通知するDNSサーバのIPアドレス
dhcp-option = option:dns-server, 192.168.0.2 #, 192.168.0.1

# DHCPクライアントに通知するNTPサーバ(時刻合わせ用)のIPアドレス
dhcp-option = option:ntp-server, 192.168.0.1
```

#まとめ
これからもラズパイで遊んでいきます！
Access　VBAからExcelを立ち上げる

### Excel のタスクを正常に終了できない現象
AccessのVBAからExcelを立ち上げて、インポートするときにハマりました。

ちゃんと宣言、格納、解放をしているのに、タスクマネージャを見ると複数プロセスが。。。
そのおかげでRangeオブジェクトで最終行の取得にエラーが発生

```vb
Function import_Excel(sFileName As String, sTblName As String, lStart As Long)

'**----------------------------------------------------------------------------
'** 本インポート処理の条件
'** エクセル　2010以降
'** エクセルの項目とインポート先テーブルの項目が内容及び、数が一緒であること。
'** 特に、ExcelファイルA列の項目とは名称を一致させる必要がある。
'** (テキスト・数値は後で変換するとした。)
'** ツール→参照設定→ Microsoft ActiveX Data Objects *.* Library　にチェック
'**----------------------------------------------------------------------------

Dim rs As New ADODB.Recordset
Dim oApp As Object
Dim wbTarget As Object

Dim lFieldCount As Long, lRow As Long, lCol As Long
Dim sFieldName1 As String

Debug.Print "import_Excel:" & sFileName

Set oApp = CreateObject("Excel.Application")
Set wbTarget = oApp.Workbooks.Open(FileName:=sFileName)

'Set wbTarget = oApp.ActiveWorkbook
rs.Open sTblName, CurrentProject.Connection, adOpenForwardOnly, adLockOptimistic


lFieldCount = rs.Fields.Count 'フィールド数カウント

'項目の次行からインポート
lRow = lStart

Dim lEnd As Long
lEnd = wbTarget.ActiveSheet.Cells(wbTarget.ActiveSheet.Rows.Count, 1).End(xlUp).Row
Dim i As Long
'最終行まで
For i = lRow To lEnd
    rs.AddNew
    'Debug.Print (i) & "行目処理中" & lEnd & "行中"
    '1行書き込み
    For lCol = 0 To lFieldCount - 1
        rs(rs.Fields(lCol).name) = oApp.Cells(i, (lCol + 1)).Value
    Next lCol
    
    rs.Update
    
Next i


rs.Close
wbTarget.Close False
oApp.Quit
Set wbTarget = Nothing

Set oApp = Nothing

End Function
```
正解はこう。　ついついRows.Countって書いちゃうけど
lEnd = wbTarget.ActiveSheet.Cells(Rows.Count, 1).End(xlUp).Row
↓
lEnd = wbTarget.ActiveSheet.Cells(wbTarget.ActiveSheet.Rows.Count, 1).End(xlUp).Row


###まとめ
Excelのオブジェクトを使うところは、省略せずにApplicationから書くこと（コードは長くなるけどね）

　　　
ActiveSheet→xlBook.ActiveSheet  又は xlSheet　のようにシート名を指定するようにして下さい
ActiveCell→xlSheet.Activate　or　xlApp.ActiveCell
Key1:=Range("C2")　→　Key1:=xlSheet.Range("C2")
xlSheet.Range(Cells(1,　･･･略　→　xlSheet.Range(xlSheet.Cells(1, ･･･略
Selection.ClearContents　→　xlSheet.Activate　xlApp.Selection.ClearContents
Rselenium + Rvest でログインが必要なページの向こうのデータをスクレイピングする

#ログインが必要なページとかもざくざく掘ってみよう
以前の記事で基本的なRseleniumの使い方を書いたのですが：
https://qiita.com/taiyodayo/items/def80bc3503766b24a89
ログインが必要なサイトやインタラクティブなページからデータを抜くのに苦労されてる方が多いようで、
僕がやったことをまとめてみました。
Rvest使うと、html/cssの知識とかそんなに無くてもサクサク行けますよ。

#開発は二通りのやり方がある：
・selenium-web-driverを起動したマシンでリアルタイムに要素名見ながらやる
・remDr$screenshot(display=TRUE) を見ながらチクチクやる

自分は後者が案外快適でした。
docker上で動くRStudioでちくちくインタラクティブに作っていきました。
「スクショ見る -> htmlファイルに落とす -> Chromeで開く -> xpath取ってコマンド書く」を繰り返すやり方です。


#「スクショ取る」「今のページをhtmlに落として保存する」は頻繁にやるのでこれ用に関数書いた：
docker上で動くRStudioでちくちくインタラクティブに作っていきました。

```R:devcode.R
# 開発・デバッグ用
remss <- function(){
  remDr$screenshot(display=TRUE)
}
remhtml <- function(){
  filename <- paste0("page_", today(), ".html")
  write(unlist(remDr$getPageSource()), paste0("debug_", ymd_hms(now(tz="Asia/Tokyo")), ".html")) 
}
```

中身は、殆どが下記の繰り返しです
・remDr$findElement 　で要素拾う (xpathで指定)
・webElem$sendKeysToElement 　で必要であれば要素代入
・webElem$clickElement()　　クリックイベントを送信


#実際の所を御覧下さい：ログイン作業

```R:sitefunctions.R
# 某サイトにログインする関数
sitelogin <- function(){
  # ログイン画面
  url <- "https://www.hoge.hoge/zzh/"
  remDr$navigate(url)
  
  ## Login - Page 1 
  # userid
  webElem <- remDr$findElement(using="xpath", value = '//*[@id="searchBlock"]/div/div/div/div[1]/ul/li[1]/label/input')
  webElem$sendKeysToElement(list("XXXUSERIDXXX"))
  # password
  webElem <- remDr$findElement(using="xpath", value = '//*[@id="searchBlock"]/div/div/div/div[1]/ul/li[2]/label/input')
  webElem$sendKeysToElement(list("XXXPASSWORDXXX"))
  # panel - fakepassword - 偽装パラメタを入れないとログイン蹴られる仕様
  webElem <- remDr$findElement(using="xpath", value = '//*[@id="contentBody"]/form/input[1]')
  webElem$sendKeysToElement(list("XXXX"))
  # action
  webElem <- remDr$findElement(using="xpath", value = '//*[@id="contentBody"]/form/input[2]')
  webElem$sendKeysToElement(list("login"))
  
  # Click login
  webElem <- remDr$findElement(using="xpath", value = '//*[@id="searchBlock"]/div/div/div/div[2]/div/span')
  webElem$clickElement()

  message("STATUS - Login success.")
  return(TRUE)
}
```

こんな感じです。
（実際にはエラーハンドリング等をもう少し手厚く書いています）

上記が動いたら、必要な商品IDなどを入れて狙ったデータを表示させられると思います。

#必要な情報が表示されたら、そのページのhtmlをRvestでパース
はじめとっつきが悪いかもなんですが、基本こんな感じにtidyなパイプでどんどん処理できます。
殆どはhtml_table()とhtml_text()で取得出来ると思います。
  
```R:parsesales.R
  sales <- read_html(remDr$getPageSource()[[1]]) %>%
    html_node(xpath = '//*[@id="salesTrend"]/div[2]/table') %>%
    html_table(fill = TRUE)
  colnames(sales) <- c("stockdate","v_sold","v_souhin","v_soldcum","dummy","v_henpin","v_henpinratio")
  sales %<>% select(-dummy) # remove junk col
  sales %<>% mutate_at(c("v_sold", "v_souhin", "v_soldcum"), as_integer)

  status_check <- read_html(remDr$getPageSource()[[1]]) %>% 
    html_node(xpath = '//*[@id="errorMsg"]/span') %>% 
    html_text

saveRDS(sales, "todaysdata.RDS")
```
あんがい簡単です。
取得時にfactorにしたり色々出来るので、.CSVにしてアホみたいに容量が膨らむ事も防げます。後処理に回しやすい。

# すごいぞ便利だRvest
「スクレーピングとか、データサイエンスと離れた所は誰かにやって欲しい...」と感じる方も多いかと思うんですが、
Rvest + RSeleniumだと本当に簡単に自動化出来るんで、いっそ自分で書いちゃうのもありだと思って頂けたら幸いです。
取得データを、そのままRで触りやすい形で保存できるので便利ですよ〜

(取得は適切にsys.sleep()を挟むなどして、相手サイトさんの負担が多すぎないように実行しましょうね）

##続きは本家サイトをチェックや
http://rvest.tidyverse.org
TypeORMでPostgreSQLのコネクションプールサイズを指定する

TypeORMでPostgreSQLのコネクションプールのサイズを指定するには、`ConnectionOptions`の`extra`プロパティ[^extra-property]\(`any`型)に`poolSize`もしくは`max`を指定する:

```ts
  const connection = await createConnection({
    type: 'postgres',
    host: 'db',
    username: 'root',
    password: 'root',
    database: 'test',
    extra: {
      poolSize: 10, // connection pool size
    },
  })
```

この方法でPostgreSQLのプールサイズを指定できるのは、TypeOrmの[PostgresDriver.tsの86行目あたり](https://github.com/typeorm/typeorm/blob/0.2.18/src/driver/postgres/PostgresDriver.ts#L868-L879)で`extra`を[Pool]クラスのパラメータとして渡すようになっているためである:

```ts
/**
 * Organizes communication with PostgreSQL DBMS.
 */
export class PostgresDriver implements Driver {
    // ...

    /**
     * Creates a new connection pool for a given database credentials.
     */
    protected async createPool(options: PostgresConnectionOptions, credentials: PostgresConnectionCredentialsOptions): Promise<any> {
        // ...

        // build connection options for the driver
        const connectionOptions = Object.assign({}, {
            host: credentials.host,
            user: credentials.username,
            password: credentials.password,
            database: credentials.database,
            port: credentials.port,
            ssl: credentials.ssl
        }, options.extra || {}); // Poolクラスに渡すオプションとしてextraを使っている

        // create a connection pool
        const pool = new this.postgres.Pool(connectionOptions);

        // ...
    }

    // ...
}
```

ここの`this.postgres`は[pg](https://github.com/brianc/node-postgres)モジュールのことだが、`pg`モジュールは内部で`pg-pool`モジュールに依存しており、上コードの`Pool`は[pg-poolモジュールの`Pool`クラス](https://github.com/brianc/node-pg-pool/blob/master/index.js#L82)になる。

[`Pool`クラスのコンストラクタ](https://github.com/brianc/node-pg-pool/blob/v2.0.6/index.js#L86)は次のような実装になっており、`max`もしくは`poolSize`の指定がなければ`10`がコネクション数のデフォルト値になるようになっている:

```js
class Pool extends EventEmitter {
  constructor (options, Client) {
    super()
    this.options = Object.assign({}, options)
    this.options.max = this.options.max || this.options.poolSize || 10
    // ...
```






## 参考

* [How to set poolSize for postgres driver? · Issue #3388 · typeorm/typeorm](https://github.com/typeorm/typeorm/issues/3388)

[^extra-property]: `extra`プロパティの定義は、[ConnectionOptions]→[PostgresConnectionOptions]→[BaseConnectionOptions]の順で追うと見つかる。
[ConnectionOptions]: https://github.com/typeorm/typeorm/blob/0.2.18/src/connection/ConnectionOptions.ts#L21
[PostgresConnectionOptions]: https://github.com/typeorm/typeorm/blob/0.2.18/src/driver/postgres/PostgresConnectionOptions.ts#L7
[BaseConnectionOptions]: https://github.com/typeorm/typeorm/blob/0.2.18/src/connection/BaseConnectionOptions.ts#L104
Google I/O 2019でのWebAssembly関係の講演まとめ

Google I/Oから１ヶ月ほど経ちましたが、I/Oで行われたWebAssembly周りの講演をまとめます。そんなに講演数は多くなく、WebAssemblyに直接関わるものは2つのみでした。またChromeの講演で、軽く触れられていました。

## WebAssembly for Web Developers

[!["WebAssembly for WebDevelopers"のサムネイル](http://img.youtube.com/vi/njt-Qzw0mVY/0.jpg)](https://www.youtube.com/watch?v=njt-Qzw0mVY)

WebAssemblyについて話した唯一のセッションで、Webディベロッパーに対してWebAssemblyを位置付ける内容になっています。

ざっとしたまとめ：

* WebAssemblyを利用する理由は2つ：エコシステムか高速で安定した性能のどちらか
* AssemblyScriptを使えばTypeScript利用者ならWebAssemblyを出力できる
* ChromeはWebAssemblyの新しい仕様をいくつか実装済み。またWebIDL bindingは大きな仕事

## Sonic Boom! Audio Programming on Android and Chrome 

[!["Sonic Boom! Audio Programming on Android and Chrome"のサムネイル](http://img.youtube.com/vi/-GaD0RCp-Q0/0.jpg)](https://www.youtube.com/watch?v=-GaD0RCp-Q0)

AndroidとWebで同じシンセサイザーを使って音楽アプリを作る、というライブコーディングを通じてAndroidとChromeの音声に関する新機能を紹介する内容でした。

ざっとしたまとめ：

* AndroidもChromeも、レイテンシーは20msほど
* C++で書かれたシンセサイザーをEmscriptenでコンパイルすることでWASMにする
* WebAssemblyを利用することで、WebでもAndroidアプリと同じ音色をだすことを保証できる

## What's New with Chrome and the Web

[!["Sonic Boom! Audio Programming on Android and Chrome"のサムネイル](http://img.youtube.com/vi/rUUazNIZW7I/0.jpg)](https://www.youtube.com/watch?v=-rUUazNIZW7I)

ChromeとWebの進捗についてのセッションでした。WebAssemblyと直接は関係なかったのですが、[The Web Perception Toolkit](https://web.dev/perception-toolkit)の部分で、WebAssemblyで実装されたポリフィルが提供される、という話がありました。
【R言語】美味いラーメン屋をWebスクレイピングしてみた🍜

スクレイピング記事を立て続けに2本書かせていただいたのですが、それでも飽き足らずにスクレイピングを続けております。

今回は食べログさんのサイトから美味いラーメン屋をスクレイピングにより抽出してみます。
筆者は埼玉県民なので、[埼玉のラーメン屋](https://tabelog.com/saitama/rstLst/ramen/1/?Srt=D&SrtT=rt&sort_mode=1&svd=20190617&svt=1900&svps=2)をターゲットにしています。

###抽出項目

店名:store_name
星の数:stars
レビュー件数:number_of_reviews

今回は星の数3.5以上を抽出してみます。

###実装

まずはパッケージの宣言から。
そして自作関数の読み込みを行っておきます。
ランキングページごとに大量のデータを読み込むことになるので、関数を作成しておくと後々冗長なコードを書くことを防ぐことができます。


```r:ramen.r
# ライブラリ -------------------------------------------------------------------

pacman::p_load(pipeR,textreadr,rvest,lubridate,tidyverse)


# ソース本文 -------------------------------------------------------------------

#関数
get_tabelog_review <- function(url_txt){
  url <- read_html(url_txt)
  
  #店名
  store_name <-url %>>%
    html_nodes(xpath = "//a[@class = 'list-rst__rst-name-target cpy-rst-name js-ranking-num']") %>%
    html_text(.,trim = FALSE)
  
  #星
  stars <-url %>>%
    html_nodes(xpath = "//span[@class = 'c-rating__val c-rating__val--strong list-rst__rating-val']") %>%
    html_text(.,trim = FALSE)
  
  #レビュー件数
  number_of_reviews <-url %>>%
    html_nodes(xpath = "//a[@class = 'list-rst__rvw-count-target']") %>%
    html_text(.,trim = FALSE)
  
  df <- tibble(store_name,stars, number_of_reviews)  
  
  return(df)
}

```

次に、ランキングの読み込むページ数を設定します。
1ページにつき20項目がずらっと表示されるので総件数 ÷ 20(小数点以下切り捨て)で読み込むページ数を決定できるはずです。
その後URLを定義しますが、「(URL前半) / ページ番号 / (URL後半)」で各ページが構成されている都合上、URLの前半部、後半部でそれぞれ変数を定義する必要があります。 

```r:ramen.r

url_txt <- "https://tabelog.com/saitama/rstLst/ramen/?Srt=D&SrtT=rt&sort_mode=1&svd=20190617&svt=1900&svps=2"

data <- read_html(url_txt)

#ページ番号の決定
pages_num <-data %>>%
  html_nodes(xpath = "//span[@class = 'list-condition__count']") %>%
  html_text(.,trim = FALSE) %>>%
  as.numeric()

pages_num <- round(pages_num / 20)

#URLの構成上、前半部分と後半部分に分ける
url_first_half <- "https://tabelog.com/saitama/rstLst/ramen/"
url_latter_half <- "/?Srt=D&SrtT=rt&sort_mode=1&svd=20190617&svt=1900&svps=2"

df_reviews <- data.frame()

```

準備ができたらfor文による繰り返しにより、ページ数分関数を読み込みデータフレーム結合を行っていきます。

```r:ramen.r

#for文による繰り返し
for(i in 1:pages_num){
  url <- paste0(url_first_half, i,url_latter_half)
  tmp <- get_tabelog_review(url)
  df_reviews <- rbind(df_reviews, tmp)
}
```

最後の仕上げに星3.5以上のラーメン屋のみを抽出します。

```r:ramen.r
#星3.5以上のラーメン屋に絞る
df_reviews2 <- df_reviews[df_reviews$stars >= 3.50,]

```

変数df_review2の中身はどうなっているでしょうか。見てみましょう。
![ramen_dataframe.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162354/3bdef503-e757-f702-1b23-99b6ace8fd7e.png)

…

![ramen_dataframe2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/162354/d1339940-d134-22d6-c855-996129919900.png)

できているようですね。
やりました！

###前回までのスクレイピングチャレンジ

[【R言語】楽天のレビューデータをスクレイピングしてみた](https://qiita.com/taro_6974/items/da57aabba8d926693ddc)

[【R言語】RでWebスクレイピングしてプロット表示するまでをやってみる](https://qiita.com/taro_6974/items/7f28bf071fd33809554b)
リモートサーバのPostgreSQLからpg_dumpする

## コマンド
```
$ pg_dump -d [データベース名] -h [ホスト名] -p [ポート] -F custom -U [ユーザ名] -W --data-only --inserts --verbose --file=[ファイル名]
Password: [パスワード]
```

## オプション覚え書き

### 接続オプション

|オプション|説明|
|:---:|:---:|
|-d, --dbname|データベース名|
|-h, --host|ホスト名(ドメイン、IPアドレスなど)|
|-p, --port|ポート（デフォルトは5432）|
|-U, --username|ユーザ名|
|-w, --no-password|パスワード無しで接続|
|-W, --password|パスワードを入力して接続|

### その他のオプション
|オプション|説明|
|:---:|:---:|
|-a, --data-only|データのみ（スキーマを取得しない）|
|-s, --schema-only|スキーマのみ（データを取得しない）|
|--inserts|インサート文で取得|
|-v, --verbose|冗長表示（作業中感が出てかっこいい）|
|-F, --format|出力フォーマット|
AMI作成時に直前のファイル操作が反映されていない場合の対応

# 前回
前回の[記事](https://qiita.com/YujiHamada3/items/4757acdb9e44bf860d9b)でEC2インスタンスへのリリース時に自動でAMIを取得できるようにしました。実際はCodeDeployのAfterinstallフックで行っています。

## 発生した問題
`aws ec2 create-image`コマンドの直前に行っていたファイル操作がAMIに反映されていませんでした。具体的には`mv` や`cp` とごくごく一般的なコマンドかと思います。
最初はスクリプトのバグを疑ったのですが、`aws ec2 create-image`の直前までは間違いなく正しく動作していることが確認できたため、AMIの取得についてAWSサポートに問い合わせました。AMIの仕様として直前の状態を保存する場合があるのかななど確認したかったからです。

## 結果
もろもろログを渡した結果AWSからは
>ファイルシステムへの変更がディスクに書き込まれる前に AMI の作成が開始されたことがこの度の事象の原因ではないかと推察しております。
恐れ入りますが、AMI 作成前にファイルシステムバッファをディスクに書き込むため、`aws ec2 create-image` の実行直前に sync コマンドを実行するように AfterInstall フックスクリプトを修正して、改めてデプロイをお試しいただけますでしょうか。

との指摘だったので
`aws ec2 create-image`の前にたった一行`sync`コマンドを入れるだけで解決しました。
おそらくインスタンス外部からの操作になるのでまだ書き込まれていないバッファを考慮せずAMIが取得されたのだと思います。
Order byにバインド変数は使えない

# Order byにバインド変数は使えない

## tl; dr
* ``order by ? `` というようなバインド変数の使い方は誤り
* order by句の中身を動的に切り替えたい場合は、値を検証した上で文字列結合する

## 概要
order by句でバインド変数を利用した場合、特にエラーは発生しませんが内容は無視されてしまいます。

### そもそも、バインド変数は何のために利用するのか？
一般にバインド変数のメリットは以下の二つです。

1. SQLインジェクションを防ぐ
2. パフォーマンスを高める

今回、問題になるのは2の「パフォーマンスを高める」の方です。
バインド変数は、パラメータだけ異なるSQLをDBMSに同一のSQLと認識させることで、
実行計画の再計算を抑制したり、キャッシュの共用を可能にしたりすることでパフォーマンスを高めるものです。
つまり、内部的に同じSQLではないと意味がありません。

#### カラム自体の切り替えは実行計画を激変させる
where句の中で比較する値をパラメータで切り替える場合は、同じ実行計画で処理することが可能ですし、
前回実行時の結果キャッシュを流用することが可能なケースも多くあります。
一方で、Order byのようにカラム自体の指定が異なる場合は実行計画自体(とそれにより決定される内部処理)が大きく異なってしまうためそれらの流用が出来ません。

このため、カラム自体に対してバインド変数を指定することは出来ません。

### 動的にソートを切り替えたい場合はどうすればいいか？
前述の通りバインド変数は使えないので、手動でORDER BY句を組み立てる必要があります。

ただ、バインド変数を利用しなくなったことにより、バインド変数のもう一つのメリット「SQLインジェクションを防ぐ」の部分も失われてしまっています。
こちらについても手動で保証する必要があります。渡されてくる値が正当なカラム名であることを検証した上で組み立てるようにしましょう。
Google Colaboratory Googleドライブからcsvデータの読み込み

やりたいこと
Googleドライブに一度アップロードしたデータをマウントして簡単に読み込みたい．

理由
Google Colaboratoryでデータを読み込むときに毎回アップロードするのがめんどくさいから

今回はデスクトップにある"softbank_9984.csv"を使って説明する．

まず，ローカルにあるcsvデータをGoogleドライブにアップロードする．
<img width="1371" alt="up2.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206657/86cb82ed-d95e-ab1b-a094-5fd5e760d01a.png">

次にGoogle Colaboratryを開いて以下のコードを実行する．

```ruby:colab
from google.colab import drive
drive.mount('/content/drive/')
```
コードを実行すると認証画面が出てくるのでURLをクリックし，認証IDをコピー，コピーしたものを貼り付けて認証を行う．
<img width="1027" alt="スクリーンショット 2019-06-17 14.49.22.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206657/eabf553e-a575-7f54-90c9-ccc2266bf78e.png">

次に，データの共有リンクを取得する．
Googleドライブに戻ってデータを右クリックし"共有可能なリンクを取得"からリンクを取得する．
![スクリーンショット 2019-06-17 14.51.23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206657/0c9ca165-0271-ea4f-7077-835c49c60c02.png)

<img width="245" alt="スクリーンショット 2019-06-17 14.54.16.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206657/a8595432-4f13-8753-0522-973e28e2ff0a.png">

表示されるURLの"id="以下をコピーしておく．

次に以下のコードで認証を行う．

```ruby:colab
!pip install -U -q PyDrive
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
from google.colab import auth
from oauth2client.client import GoogleCredentials

# check auth
auth.authenticate_user()
gauth = GoogleAuth()
gauth.credentials = GoogleCredentials.get_application_default()
drive = GoogleDrive(gauth)
```
先ほどコピーしたリンクを以下のコードの'id':以下に記入し，コードを実行すると,

```ruby:colab
downloaded = drive.CreateFile({'id':'1VCfUC...'})

# Download the file to a local disk as 'sample.csv'.
downloaded.GetContentFile('softbank_9984.csv')

import pandas as pd
data = pd.read_csv('softbank_9984.csv',encoding='CP932', header=-1)
data.head()
```
以下のようにcsvデータが読み込まれる．

![スクリーンショット 2019-06-17 15.02.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/206657/5f7b1fd7-67c9-bc5d-f222-d1aa56ce274a.png)

参考サイト
[公式ページ](https://colab.research.google.com/notebooks/io.ipynb#scrollTo=RWSJpsyKqHjH)
Djangoのviews.pyファイルとurls.pyファイルについて紹介！

今回は、Djangoのviews.pyファイルとurls.pyファイルについてと,ページ表示に必要な関連知識について紹介します。
しかし、プログラミング初心者であるため、内容に誤りがあるかもしれません。
誤りがあれば、どんどん指摘してください。

## views.pyとは
画面の表示に関する処理を記述しておくためのものです。

## HttpResponseとは
webアプリケーションにアクセスしてきたWebブラウザに送り返す処理内容を管理するクラスです。
例えば、

    HtttpResponse("Hello!")
とインスタンスを生成し、これをreturnすることで、Hello!がWebブラウザに送り返されます。

## pathとは
pathは

    path(アクセスするアドレス名,　任意のフォルダから実行する処理)
のように記述し、第1引数にアドレス,第2引数に実行する処理を指定することで、そのアドレスにアクセスした際に処理を実行するための値が用意されます。

## urls.pyとは
URLを管理するためのものです。ファイルの中に記述されているurlpatternsでアドレスを管理しています。
中身は例えば、
        
    import　a（フォルダ名).views　a

    urlpatterns=path('hello/',a.index),
となっていると、aというフォルダ内のviews.pyをimportし,hello/にアクセスするとa内のviews.pyのindexを実行するという意味になります。
Firebase とっても初心者コマンド 

<h1>Firebase 初心者コマンド</h1>
個人的なメモです。詳しくは<a href="https://firebase.google.com/docs/cli/?hl=ja">Firebase CLI リファレンス</a>へどうぞ。
<br>



npmでfirebaseインストール

```
xxxxxxxx $ npm i -g firebase-tools 
```

firebaseにログイン(Google Accountログイン&FirebaseのProjectは事前準備の上叩く)

```
xxxxxxxx $ firebase login
```



firebaseを初期化。index.htmlと404.htmlが自動生成される


```
xxxxxxxx $ firebase init
```
現存するプロジェクトを全てリストで出す

```
xxxxxxxx $ firebase list
```

Hosting(アップロードする)プロジェクトを指定する

```
xxxxxxxx $ firebase use [プロジェクト名]
```

Firebaseにデプロイ。2番目のコマンドはHostingのみデプロイしたい時に叩く。

```
xxxxxxxx $ firebase deploy
xxxxxxxx $ firebase deploy --only hosting
```

<br>

これだけあればHello,Worldには困らないはず。
グループ内で同じ誕生日の人のペアがいる確率を計算してみたお

「風の噂で、２０数人いれば、５０％の確率で同じ誕生日のペアが存在する」とかなんとか、、、というのを聞いたので実際に計算してみました


```python:same_birthday.py
import matplotlib.pyplot as plt
import numpy as np

print("Find the probability of existing person of same birth day in a group")
print("n: the number of people in a group")

x = np.linspace(2, 366, 364)
y = []
no_match = 1
for n in range(2, 366):
	no_match *= (366-n) / 365
	match = 1 - no_match
	y.append(match)
	print("n = %3d: %f" % (n, match))

plt.plot(x, y)
plt.show()
```

このプログラムを動かすと

```
Find the probability of existing person of same birth day in a group
n: the number of people in a group
n =   2: 0.002740
n =   3: 0.008204
n =   4: 0.016356
n =   5: 0.027136
n =   6: 0.040462
n =   7: 0.056236
n =   8: 0.074335
n =   9: 0.094624
n =  10: 0.116948
n =  11: 0.141141
n =  12: 0.167025
n =  13: 0.194410
n =  14: 0.223103
n =  15: 0.252901
n =  16: 0.283604
n =  17: 0.315008
n =  18: 0.346911
n =  19: 0.379119
n =  20: 0.411438
n =  21: 0.443688
n =  22: 0.475695
n =  23: 0.507297
n =  24: 0.538344
n =  25: 0.568700
n =  26: 0.598241
n =  27: 0.626859
n =  28: 0.654461
n =  29: 0.680969
n =  30: 0.706316
n =  31: 0.730455
n =  32: 0.753348
n =  33: 0.774972
n =  34: 0.795317
n =  35: 0.814383
n =  36: 0.832182
n =  37: 0.848734
n =  38: 0.864068
n =  39: 0.878220
n =  40: 0.891232
n =  41: 0.903152
n =  42: 0.914030
n =  43: 0.923923
n =  44: 0.932885
n =  45: 0.940976
n =  46: 0.948253
n =  47: 0.954774
n =  48: 0.960598
n =  49: 0.965780
n =  50: 0.970374
n =  51: 0.974432
n =  52: 0.978005
n =  53: 0.981138
n =  54: 0.983877
n =  55: 0.986262
n =  56: 0.988332
n =  57: 0.990122
n =  58: 0.991665
n =  59: 0.992989
n =  60: 0.994123
n =  61: 0.995089
n =  62: 0.995910
n =  63: 0.996604
n =  64: 0.997190
n =  65: 0.997683
n =  66: 0.998096
n =  67: 0.998440
n =  68: 0.998726
n =  69: 0.998964
n =  70: 0.999160
n =  71: 0.999321
n =  72: 0.999453
n =  73: 0.999561
n =  74: 0.999649
n =  75: 0.999720
n =  76: 0.999777
n =  77: 0.999824
n =  78: 0.999861
n =  79: 0.999891
n =  80: 0.999914
.
.
.
.
.

```

というようにコンソールに出力されて
このような画像が画面に出力されます。

![Figure_1.png](https://qiita-image-store.s3.amazonaws.com/0/204506/a204ac07-e9f6-9656-cabb-107d606f7935.png)

確かにこれを見ると、23人のところで、確率が５０％を超えますね。
５０人もいればほぼ100％ペアが存在する。



さて、ちょっとプログラムを解説

ざっくりやっていることというのは
・全員が違う誕生日である確率を求める
・余事象を求める
だけです

まず

```
x = np.linspace(2, 366, 364)
y = []
```

これは
「xを２から366までを364分割する」
という命令です


```
no_match = 1
for n in range(2, 366):
	no_match *= (366-n) / 365
	match = 1 - no_match
	y.append(match)
	print("n = %3d: %f" % (n, match))
```

ここではまずno_matchを１で初期化しておきます
そしてnを2~365まで回します
2人以上じゃないと、当たる確率は０だし
366人以上だと必ず１組は存在するので（うるう年は考えない）
この範囲です。


２人目が、１人目と違う誕生日である確率は
364/365
３人目が、１人目と２人目とも違う誕生日である確率は
363/365

なので、３人とも誕生日が違う確率は
1 - (364/365) * (363/365)なので
以下ループ
.
.
.


と続いていくので、その都度計算して
yに追記してコンソールに出力していくという形を取っています。


ループが終わると、xとyのデータが完成しているので
それをmatplotlibのx、yに突っ込んでグラフを出力すれば完成です
VScode > UI > Compareした後に、そのペインを閉じる > Close Editor | What is Editor?

```txt:動作環境
Windows 10 v1903
RAD Studio 10.2 Tokyo Update 3
Visual Studio Code v1.35.1
```

### Compareのペイン?を閉じる

1. コマンドパレットからcompareと入力し、ファイルを比較する
2. その比較ペインを閉じる

:thinking: 

UIが分からない。

### 閉じ方

Fileメニューから「Close Editor」にて閉じることはできた。

Editor

。。。

:thinking: 

最近のM社の製品はUIがよくわからない。自分の能力の衰退のせいなのでしょうね。


![2019-06-17_14h33_49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32870/c2e1ea96-b3f7-1a77-4274-b66a95ac2dcc.png)


### What is Editor?

https://code.visualstudio.com/docs/getstarted/userinterface

一つ一つのことをEditorというようですね。

Sublime Textでいうところの「Window」に対応してそうです。

Editorというキーワードは、秀丸エディタやSublime Text、VScodeそのもののように、ソフトを指すことが多いように思います。
そのような背景を考えると、Editorというのが編集ウィンドウを意味するというのは違和感を生じる、というのが個人的な考えです（実際に違和感を持った）。
Arduino と電磁リレーでダースベイダーのテーマ

ArduinoではTone()という関数を使って簡単に音を出す（ピンから矩形波を出す）ことが可能です。
Tone()を連ねることで曲を演奏することができるので、ダースベイダーのテーマのようなメジャーな曲は[”arduino darth vader”](https://www.google.com/search?q=arduino+darth+vader&oq=arduino+darth+vader&aqs=chrome..69i57j0l5.7550j0j8&sourceid=chrome&ie=UTF-8)　とかでググるといっぱい出てきます。
たとえば[こちら](https://gist.github.com/nicksort/4736535)。

![2019-06-17_142736.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/db9c98e6-0d22-1d16-dcdf-a58997d8867d.png)


ピンから矩形波を出しているだけなので、当然電磁リレーも駆動できるのですが、Tone()は通常ピエゾスピーカーから音を出すことを想定して使われているのでリレーには周波数が高すぎます。
そこでオクターブをさげて演奏してみます。

```
void beep(int note, int duration)
{
  //Play tone on buzzerPin
  tone(buzzerPin, note, duration);
 
  //Play different LED depending on value of 'counter'
```
のようにbeep() の中でtone()を呼んでいるので、その前に
3オクターブほど下げてみます。

```
void beep(int note, int duration)
{
  note >>= 3; // <-
  //Play tone on buzzerPin
  tone(buzzerPin, note, duration);

  //Play different LED depending on value of 'counter'
```

すると[いい感じにダースベイダーが出てきそうな音がでます。](https://youtu.be/02YovE40VpI)
![2019-06-17_143614.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/59911/e141c5c5-c716-d4f8-9653-ffc7b2f7bbc0.png)
もちろんリレーなので音に合わせてLチカもできます。

[関連](https://qiita.com/ELIXIR/items/e7be4d16dff9cbaf41a7)
BashでファイルにCRLFが含まれているかを判断してLFに置換する

Bashで、テキストファイルの行末コードがCRLFになっているかを、なるべく短くてビルトインのコマンドで判断する・置換するコードです。

# ファイルにCRLFが含まれているかを判断する

```shell
grep -U $'\r' winfile.txt
```

## `if`文で処理を分ける場合

```shell
if grep -q -U $'\r' winfile.txt; then
  # CRLFである場合の処理
else
  # そうでない場合の処理
fi
```

# 行末のCRLFをLFに統一する

```shell
sed 's/'$'\r''$//' winfile.txt
```

## 置換した結果を別ファイルに吐き出す場合

```shell
sed 's/'$'\r''$//' winfile.txt > out.txt
```

## 直接ファイルを上書きする場合

```shell
sed -i 's/'$'\r''$//' winfile.txt
```

macOSなどBSD系だと、バックアップ拡張子が必要。

```shell
sed -i.bak -e 's/'$'\r''$//' winfile.txt
```
自作のデータセットを Keras のチュートリアル用データっぽく読み込む

#やったこと
Kerasでチュートリアル用のMnistデータを呼びだす際には言わずもがな以下のコードを実行する。

```python
(X_train, y_train), (X_test, y_test) = mnist.load_data()
```

これを自作のデータでそれっぽく行う。

```python
(X_train, y_train), (X_test, y_test) = load_data("自作のデータセット名")
```
ちなみに本記事は[自作のデータセットをAugmentationを行い、train・testデータに分割](https://qiita.com/y-foi/items/230db2a0d724fa19780c)を行なった以前の記事の続き。


#[以前の記事](https://qiita.com/y-foi/items/230db2a0d724fa19780c)で行なったこと

自作の少数の画像データから
　↓
Augmentationを行い、データ数のカサ増し
　↓
Trainデータ, Testデータ, Trainラベル, Testラベルをlist形式で取得


# NumPyのバイナリファイルの活用

以前の記事の続きなので以下の変数が取得されている前提。

```python
training_images # list / Trainデータ
training_labels # list / Testデータ
test_images # list / Trainラベル
test_labels # list / Testラベル
```

NumPyのバイナリファイルについては[こちらの記事](https://note.nkmk.me/python-numpy-load-save-savez-npy-npz/)を参考にさせて頂きました。
>NumPyでは配列ndarrayをNumPy独自のバイナリファイル（npy, npz）で保存することが可能。データ型dtypeや形状shapeなどの情報を保持したまま書き込み・読み込み（出力・入力）ができる。

要はNumPyのオブジェクトを編集不可の状態で保存してくれるのがnpz形式のファイル（という理解）


以前の記事ではdog, catのデータを用いたのでデータセット名は以下を用いる。

```python
'cats_dogs'
```
list　→　np.array  →　npz形式　へ
ちなみにnp.savezを用いてnpz形式ファイルの作成。

```python
np.savez('パス文字列', array)
```
今回はカレントディレクトリに作成。

```python
np.savez('cats_dogs_training_data.npz', np.array(training_images))
np.savez('cats_dogs_training_labels.npz', np.array(training_labels))
np.savez('cats_dogs_test_data.npz', np.array(test_images))
np.savez('cats_dogs_test_labels.npz', np.array(test_labels))
```

# load_data関数の定義

まずは上記で保存したデータの読み込み、呼び出し方法の確認

>デフォルトでは上の例のように保存時に引数に指定した順番にarr_0, arr_1...という名前が自動的に付けられる。

ようなので、以下の通り。

```python
#　読み込み
train = np.load('cats_dogs_training_data.npz')

# 呼び出し
train['arr_0']
```


では早速
load_data関数の作成。

```python
def load_data(datasetname):

   """
   note : 呼び出したいデータセット名の train/test 両データ・両ラベルをnp.array形式で取得する関数
   ----------
   datasetname : str
   """

    file_train_data = np.load(datasetname + "_training_data.npz")
    train = file_train_data["arr_0"]
    
    file_train_label = np.load(datasetname + "_training_labels.npz")
    train_labels = file_train_label["arr_0"]
    
    file_test_data = np.load(datasetname + "_test_data.npz")
    test = file_test_data["arr_0"]
    
    file_test_label = np.load(datasetname + "_test_labels.npz")
    test_labels = file_test_label["arr_0"]
    
    return (train, train_labels), (test, test_labels)
```

# load_data関数の呼び出し

```python
(X_train, y_train), (X_test, y_test) = load_data("cats_dogs")
```
python の　お勉強　４日目

#　亀にグラフを描いてもらう
今回 ipadのアプリの pythonista で作成してみまました
pythonista は ipad上 で python のプログラムを実行できますが
tkinter は含まれていないので turtle に 棒グラフを描いてもらいました。
(pythonista ではNumpy,Matplotlib は使えるようです。)

プログラムの流れ
x軸、y軸を作成
棒の部分を固定値で作成
自宅のMacを使ってグラフの位置を微調整

引っ掛かったところ
亀で描く場合は　描きたい箇所で　turtleをdownさせる
亀の移動する向きを考慮する。
（座標を動かしたので　亀が無駄な動きをしています。）

次回の課題
前回作成したパネルにグラフを挿入できるか？、うまく連動してグラフが
描けるか　やや不安です...

```python

from turtle import *
screensize(300,300)
color('blue', 'yellow')
setworldcoordinates(-150, -150, 150, 150)
up()
setpos(-140,-140)
down()
def mkaxis():
   fd(45)
   rt(90)
   fd(5)
   bk(5)
   lt(90)
mkaxis()
mkaxis()
mkaxis()
mkaxis()
mkaxis()
mkaxis()
setpos(-140,-140)
lt(90)
mkaxis()
mkaxis()
mkaxis()
mkaxis()
mkaxis()
mkaxis()
up()

def mkbar(x1):
   fd(x1)
   rt(90)
   fd(30)
   rt(90)
   fd(x1)
   up()
   home()
   lt(90)


setpos(-110,-140)
down()
mkbar(80)
up()

setpos(-65,-140)
down()
mkbar(130)
up()
setpos(-20,-140)
down()
mkbar(150)
up()
setpos(70,-140)
down()
mkbar(100)
up()
setpos(-180,-140)
```
もう絶対にググらない。sliceとspliceの違いを覚えてやる。


「一度使えば覚えられるでしょ」そう思っていた。
甘かった。そいつは忘れたころにやってくる。配列操作の一卵性双生児、sliceとsplice。
どっちがどうだったっけ?
もう何度ぐぐったことか。ぐぐるごとに命が削られる。
もう二度とググらないくらい徹底的に調べてやるぞ。
決意表明の意味も込めてここに書き留めておく。

##まずはおさらい
```js
var arr1 = [0, 1, 2, 3, 4]

// .slice(開始位置, 終了位置)
console.log(arr1.slice(0, 2)) //=> [0,1]
console.log(arr1) //=> [0,1,2,3,4]

var arr2 = [0, 1, 2, 3, 4]

// .splice(開始位置[, 削除カウント[, 追加要素1[, 追加要素2, ...]]])
console.log(arr2.splice(0, 2)) //=> [0,1]
console.log(arr2) //=> [2,3,4]
```

要素を抽出したい場合、出力結果が同じなところがややこしい。
違いは元の配列から要素が削除されるかどうか。
いつもどっちが元の配列が変わらないのかがわからなくなってググらざるを得なくなってしまう。
悩ましいポイントはここにある。


##メソッド名の意味
###slice
断片
###splice
繋ぎ合わせる

。。あれ、なんだか意味の違いははっきりしてるじゃないか。
そうか、繋ぎ合わせるという意味のspliceは元来要素の抽出のためにあるわけではなく、要素を消して違う要素を入れるためにあるのか。
てことは、元の配列から要素が消えるのも納得できる。

##結論
メソッド名の意味の違いを知れば動作の予測がある程度できそう。
こんな初歩的なことだったとわ。。
これで覚えられると良いなー。

。。文字列操作の、substring, substr, sliceも同じ感じでいけるだろうか。
Basic認証の導入を分かりやすくまとめる！

###  Basic認証って？？？
HTTP通信に備え付けられているユーザー認証の仕組みです！
サーバーと通信が可能なユーザー名とパスワードをあらかじめ設定しておき、それを知っているユーザーのみがWebアプリーションを利用できるようにすることができます。

<img width="494" alt="c4956c1ad1b3ea81c25c2591c8596ae8.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/438981/820325bf-54c8-b465-0b35-ffd3f9390d91.png">


(ふむふむ、仕組みは分かったけど、どんなときに使うんじゃ？）:frowning2:

例えば...
***・公開前の見られたくないホームページを作成している場合***
***・気休め程度でセキュリティをあげたい場合（安全面という観点では、完全に信頼できる認証方式ではない）***

（なるほど、人に見られたくない時に活用するわけね）:relieved:

それでは、手を動かしながら実際に導入していきましょう！

---
### ➀Basic認証の導入

完成したコードから見ていきましょう！

```ruby:application_controller.rb
class ApplicationController < ActionController::Base
  before_action :basic_auth
  protect_from_forgery with: :exception

  private

  def basic_auth
    authenticate_or_request_with_http_basic do |username, password|
      username == ENV["BASIC_AUTH_USER"] && password == ENV["BASIC_AUTH_PASSWORD"]
    end
  end
end
```

順を追って説明していきます！
###### ・記載するファイル　######
Basic認証によるログインの要求は、全てのコントローラで行いたいですね。そこで、Basic認証の処理をapplication_controller.rbにて、private以下にメソッドとして定義し、before_actionで呼び出すように実装しましょう！

######・authenticate_or_request_with_http_basicメソッド######
Ruby on RailsでBasic認証を実装するためのメソッドです。

##### ・メソッド内に、ユーザー名とパスワードを直接記載してもいいのですが、もしもGithub上の公開リポジトリでソースコードを管理している場合、コードを読める何者かに不正にBasic認証を突破されてしまいます。
対策として、本コードではコードに直接ユーザー名とパスワードを記述するのではなく、環境変数を利用する実装に切り替えています！

---
### ➁環境変数の設定

```terminal
$ vim ~/.bash_profile

export BASIC_AUTH_USER='test'
export BASIC_AUTH_PASSWORD='1234'

$ source ~/.bash_profile
```
順を追って説明していきます！

######・vim ~/.bash_profile
ローカルサーバーで.bash_profileを開きます。
そして、「i」を押してインサートモードに移行しましょう！

######・.bash_profileの内部に記述を追加
BASIC_AUTH_USERとBASIC_AUTH_PASSWORDという名前で、それぞれユーザー名とパスワードを定義します！
記述を追加したら、escキーを押してインサートモードを抜け、「:wq」と入力して保存して終了しましょう！

######・source ~/.bash_profile
.bash_profileを再読み込みし、定義した環境変数を有効にしましょう！
こちらのコマンドを実行しないと、反映されないので注意しましょう！

---

以上で、Basic認証の導入は終了となります！

もし、本番環境のみに適応させたのであれば、application_controller.rbにて、
production?というメソッドを定義し、現在の環境が本番環境ならtrue、そうでないならfalseを返すようにメソッドを定義してあげることで設定することができます！

それでは、ご静聴ありがとうございました:relaxed:
今週の学習記録 : 少し回り道　6月第2週

#これまで
就活失敗からスキルを身につけるため職業訓練校に入るも、授業の様子や求人情報などがあまりよろしくなく、独学でポートフォリオを作っての就職を目指す。主に授業時間中に自習しています。
javascript/HTML/CSSを学ぶためいろいろなものに触れています。
twitterも始めました（@hirobanokanr）！！！！！！！！（宣伝失礼します）

#今週取り組んだもの・所感

##訓練校の授業
ネットワーク技術の単元が終わり、Linuxの実習授業に入りました。これまで全く触れたことのない技術なこともあり、なかなか自習することができず、時間を割いて取り組みました。
つぎつぎと課題が出されるので時間に追われる形になり、これまでになく良い授業でした。


##Progate

### javascriptコース Ⅳ～Ⅶ（復習）

ひととおり概要は掴めたものの自分のものになったという自信が無いため、何度も復習しています。
HTML/CSSと組み合わせて実際に使うということを経験していないため、一度実践的に制作を試みてここがこう役立つのか、と認識してから学ぼうと思っていたのですがそこまで回らず、時間が過ぎてしまいました。

### HTML/CSSコース　中級/上級

少し前まで、float:left;の仕様などにヒーヒー言いながら3時間程かけて取り組んでいた道場コースが、15分くらいでできるようになっていました！！！！！！これはとても嬉しかったです。
後述する本をひととおり済ませたことが大きな経験になったと自覚しています。

##書籍など

###HTML&CSSとWebデザインが 1冊できちんと身につく本

ひととおり一周したあと、復習としてまた1から、今度は完成形だけ見て自分で作る形でやり直しています。
レイアウトを作る際の枠組みが見えてきて、本当に為になりました。
書籍を使う学習がかなり良いと実感できたので、今後も取り組んでいきたいのですがなかなかお金が...。
試し読み本はたくさんあります！少しずつ取り組んでいければ、と思います。



###うはうは☆プログラミング 第一回～第二十回

<a href=""<a href="https://www.youtube.com/watch?v=Y8ZlFMAh9SQ">Youtube<a/>や<a href="https://www.nicovideo.jp/watch/sm31238731">ニコニコ動画<a/>に投稿されている、現役プログラマーのRevinさんが講師を務めるjavascript学習動画シリーズです。
初学者を対象にして基本ゆるい語り口でほがらかに雑談交えながらも、しっかりとした基礎知識と実践的な動くプログラミング作りに重点を置いた解説で、手を動かしながら楽しく見れるとても素敵な学習コンテンツです。変数とは？代入って？といった段階からHTML/CSSを動かすところまで、無料なのが信じられないほどたっぷりと学べました。
自分がプログラミングをやってみようかな、と思ったきっかけになった動画でもあるのですが、色々学んだ今見るとまた新たな知見が得られました。有効活用していきたいです。




##反省・来週の展望

訓練校の授業や、また辞めて完全独学体制に移ろうか、通い続けるべきか、といった判断するための調べもの等に時間を取られ先週に比べて学習量は少なかったと反省しています。
今週も訓練校のカリキュラムに取られる時間が多くなる予定なので、意識して普段よりも自己学習多めにしたいと思います（憂鬱にならない程度に）。
根がネガティブなので幾分か前向きに！！！！！！！！！！！！！やっていきたいと思います
もし読んで下さっている方がいらっしゃいましたら、御清読ありがとうございました。
アドバイス等いただけたら誠に嬉しいことこの上ないです。
乱文失礼いたしました。
Chrony で時間を強制同期

RHEL7 から `ntpd` ではなく `chronyd` が標準インストールされました。後から変えることも可能。

それで使っている環境が Vagrant であるため、 `suspend` した後、数日経ってから起動するので、日付が3日以上のズレがあるといった事があります。

`chronyd` が動いている場合、少しづつ調節してく( Drift )のですが、3日もあるといつ終わるかわかりませんので、強制的に３日飛ばしす方法として、 `chronyc makestep` を root 権限で実行すればいいです。

```
vagrant@host:~$ date
Fri Jun 14 11:41:38 UTC 2019
vagrant@host:~$ sudo chronyc makestep
^C506 Cannot talk to daemon
vagrant@host:~$ date
Mon Jun 17 04:16:39 UTC 2019
```

ただし**「rtcfile ディレクティブを使用している場合は、リアルタイムクロックを手動で調整しないでください」** とあるので、このコマンドを使うときはシステム管理者に聞くなどしてくださいな。

## see
- [第17章 CHRONY スイートを使用した NTP 設定](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/ch-configuring_ntp_using_the_chrony_suite)
- [17.3. CHRONY の使用](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/system_administrators_guide/sect-using_chrony)
[JS][Vue]非同期処理直後にリロードされてしまう問題を「e.preventDefault();」で解消させられた件

#まずは成功したコードから
<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="html,result" data-user="riotam4" data-slug-hash="Wqwdex" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="Wqwdex">
  <span>See the Pen <a href="https://codepen.io/riotam4/pen/Wqwdex/">
  Wqwdex</a> by riotam (<a href="https://codepen.io/riotam4">@riotam4</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
送信ボタンを押すと、「あああ」と表示されるだけのシステム。
### すごいざっくりコードを説明
1. 送信ボタンを押す
2. HTML側の「@submit="outPut"」により、JS側の「outPutメソッド」が発火
3. JS側でthis.stringに「あああ」を代入
4. つまり、JS側のdataの中に入っていた「string: ''」が「string: 'あああ'」に書き換えられる
5. HTML側の「{{ string }}」内に、4.が出力される(元々は空文字が出力されていた)

# 失敗したコード
<p class="codepen" data-height="265" data-theme-id="0" data-default-tab="html,result" data-user="riotam4" data-slug-hash="vqGpEw" style="height: 265px; box-sizing: border-box; display: flex; align-items: center; justify-content: center; border: 2px solid; margin: 1em 0; padding: 1em;" data-pen-title="vqGpEw">
  <span>See the Pen <a href="https://codepen.io/riotam4/pen/vqGpEw/">
  vqGpEw</a> by riotam (<a href="https://codepen.io/riotam4">@riotam4</a>)
  on <a href="https://codepen.io">CodePen</a>.</span>
</p>
<script async src="https://static.codepen.io/assets/embed/ei.js"></script>
それだけのシステムだが、このコードだと、一瞬「あああ」が現れてくれるが、すぐに消えてしまう。

cosole画面にもエラーが出ない。困った。

何度か押してみて気が付いたのが、実行したすぐ後にページがリロードされて、それで強制的に「string」が初期状態に戻されている挙動のように見える。
### 追加したコード
色々調べて「e.preventDefault();」を入れてみる。
以下に調べた内容を共有します。
# e.preventDefaultって何？
e.preventDefaultは、簡単に言うと**デフォルトのアクションを抑止する**という、JSであらかじめ決められたメソッドです。
今回の例で、具体的に説明すると…

```javascript:成功したコードの10行目付近
outPut(e){
   e.preventDefault();
   this.string = 'あああ'
}
```
今回は上記のように、outPutメソッドは最終的に、「this.string」に「あああ」を代入しているだけです。

しかし、メソッドの発火装置が、何らかの形でページ遷移（リロード）を起こさせてしまい、望んでいる挙動になってくれない。

結果論ですが、e.preventDefault();を追加したことで、実行がうまくいったので、そういうことだったのではないか、と半ば無理やり納得しています。
（もし異論があれば、教えてください。当方、半ば無理やり納得してます。）