OmniAICreator/Qiita-1.07M huggingface dataset:
【OCI】oracle cloud -仮想クラウド・ネットワーク構築編(セキュリティ・リスト)-【初心者向け】

# セキュリティ・リスト
仮想ファイアウォール
やれることは
ネットワーク・セキュリティグループとほぼ同じ
Oracleの推奨がネットワーク・セキュリティグループのため、基本セキュリティ・リストはデフォルト使用します。

ざっくりセキュリティリストとセキュリティグループの違いを説明すると

**セキュリティリストはサブネットに対して設定するファイアウォール**
**セキュリティグループはインスタンスに対して設定するファイアウォール**
セキュリティグループの方が柔軟なため私はセキュリティグループで設定するのをオススメします。

## 前回の記事でネットワーク・セキュリティグループを作成しました。

ネットワーク・セキュリティグループの作成を見たい方はこちらから
[セキュリティグループ編](https://qiita.com/manaki079/items/2a1eac62997ea41ab71e)


## セキュリティ・リストの修正
サブネットを作成したいVCNの詳細ページ
左側のリソース→セキュリティ・リストをクリック
![instance_22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/8f6abe4c-cded-db1b-bcdc-5c7dc7b7b7a4.png)

デフォルトのセキュリティ・リストをクリック
![instance_23.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/a31b6e00-39c4-ed96-55f9-a1bc0531d8a1.png)

デフォルトで22番を全開放しているため削除します。
右側の・・・をクリック→削除をクリック
![instance_24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/111276/5ad034a9-3ec3-9d5e-f131-11aa9d0dcc33.png)

セキュリティ・リストの２２番を削除してイングレスのみグループで制御するのが自分のベストプラクティスとなっています。
エグレスはセキュリティ・リストでデフォルトで全開放

セキュリティグループ周りのベストプラクティスがあれば教えてほしいです！

## 次回
NATゲートウェイの作成を行っていきます。

[NATゲートウェイ編はこちら](https://qiita.com/manaki079/items/903a5c210a2289f98ff8)
Qiitaで読みたいと思った記事がすでに削除されていた場合の2つの対処法について紹介します

# この記事でわかることについて

Qiita ですでに何らかの事情で削除されてしまった記事をどうしても読みたいときにどうすればいいのかについてまとめてみました。
この方法を使えば過去に渡ってQiita だけでなく様々なウェブページでも削除されてしまった下記のようなページでも覗き見することができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44392/03801bab-f9e5-8f93-8b8b-8e8aa1b690f3.png)


## Internet Archiveで探す

Internet Archiveは、アメリカの団体によって運営されているウェブサービスです。「wwwのスナップショット」と呼ばれる、過去に収集されたWEBページのコピーなどが多数保管されています。

[Internet Archive](https://archive.org/)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44392/6621076a-afb7-0afe-5558-481b90332869.png)

このウェブサービスを使うと私が2019年01月22日に転職活動の一貫で使った過去の記事

[iOSエンジニアがフリーランス案件の面談で良く聞かれる質問集をまとめてみた](https://qiita.com/tamappe/items/9873731cc435bc168da1)

を読むことができます。

https://web.archive.org/web/20190122180513/https://qiita.com/tamappe/items/9873731cc435bc168da1

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/44392/8ec92ba6-4835-0153-113b-59802a30b760.png)

### 使い方

[Internet Archive](https://archive.org/)に行きURL入力欄に、目的のURLを入力して「BROWSE HISTORY」ボタンを押してください。
その後カレンダーが出てきますので該当しそうな日付を選択すればその記事を読むことができます。

## Googleキャッシュで探す

Googleを開いて、キーワードを以下のようにして検索します。

```sh
// 検索窓
cache:URL
```

例えば、さきほどの

https://qiita.com/tamappe/items/9873731cc435bc168da1 

であれば


**cache:https://qiita.com/tamappe/items/9873731cc435bc168da1**

と検索窓に入力して検索してみてください。
ただこちらは有効期限があるようで1週間以上経つと確認できなくなるように感じます。

どちらもキャッシュが残っていなければ、
残念ですが本当に削除されたウェブページを読むことができません。

削除された記事が読めたときはラッキーと思うしかありませんね。
Rocky Linux 8 に WordPress 5.3 をインストール

Rocky Linux 8 にLAMP(Linux/Apache/MariaDB/PHP)環境のインストールを行う手順を以下に記します。


# タイムゾーンの変更

```
sudo su - 
timedatectl set-timezone Asia/Tokyo
```

# Apache のインストール

```
dnf -y install httpd
systemctl enable httpd
systemctl start httpd
```

# PHP のインストール

標準でインストールされる PHP 7.2 上での WordPRess 5.8 の利用は非推奨となっていますので，PHP 7.4 をインストールします。

```
dnf module list php
dnf module enable php:7.4 -y
dnf module list php
dnf -y install php php-mysqlnd php-pecl-json
systemctl restart httpd
```

# MariaDB 10.3 のインストール

CentOS 7 では MariaDB 5.5 とかなり古いバージョンのままでしたが，Rocky Linux 8 では 2018 年に GA になった 10.3 がインストールされます。

```
dnf -y install mariadb-server
systemctl enable mariadb
systemctl start mariadb
```

2019-09-26 時点では MariaDB 10.3.28 がインストールされました。

```
$ dnf list installed | grep mariadb |sort
mariadb-backup.x86_64               3:10.3.28-1.module+el8.4.0+427+adf35707 @appstream
mariadb-common.x86_64               3:10.3.28-1.module+el8.4.0+427+adf35707 @appstream
mariadb-connector-c-config.noarch   3.1.11-2.el8_3                          @appstream
mariadb-connector-c.x86_64          3.1.11-2.el8_3                          @appstream
mariadb-errmsg.x86_64               3:10.3.28-1.module+el8.4.0+427+adf35707 @appstream
mariadb-gssapi-server.x86_64        3:10.3.28-1.module+el8.4.0+427+adf35707 @appstream
mariadb-server-utils.x86_64         3:10.3.28-1.module+el8.4.0+427+adf35707 @appstream
mariadb-server.x86_64               3:10.3.28-1.module+el8.4.0+427+adf35707 @appstream
mariadb.x86_64                      3:10.3.28-1.module+el8.4.0+427+adf35707 @appstream
```


# WordPress のインストール

## WordPress ダウンロード/展開

現時点での[WordPress最新版](https://ja.wordpress.org/latest-ja.tar.gz)をダウンロードし、DocumentRoot配下に展開します。

```
dnf -y install wget
cd /var/www/html
wget https://ja.wordpress.org/latest-ja.tar.gz
tar xvf latest-ja.tar.gz
chown -R apache:apache .
```

## WordPress 用データベース作成

文字コードUTF8でデータベース wordpress を作成します。

```sql
# mysql
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MariaDB connection id is 8
Server version: 10.3.11-MariaDB MariaDB Server

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MariaDB [(none)]> CREATE DATABASE wordpress DEFAULT CHARACTER SET utf8;
Query OK, 1 row affected (0.001 sec)
```

## WordPress 用 MariaDB ユーザの作成

さきほど作成したデータベースのみ全権限を持つ wordpress ユーザを作成します(ユーザ名/パスワードは適宜変更してください)。

```sql
GRANT ALL ON wordpress.* TO wordpress@localhost IDENTIFIED BY 'password';
FLUSH PRIVILEGES;
```

## WordPress 初期設定

webブラウザで xx.xx.xx.xx/wordpress/ にアクセス、WordPress初期設定を行います。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/122952/e2a57068-9ca9-de5a-9db6-273de5a97770.png)


![image.png](https://qiita-image-store.s3.amazonaws.com/0/122952/f44caded-dc3b-7ee1-199f-b4fab2d5ba9e.png)

正常にインストールが完了すると、指定したユーザ/パスワードでダッシュボードにログインできます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122952/e80754bf-8321-306a-2a43-ea52a892cdd1.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/122952/0ffaf5d5-d97c-fbe3-f64b-19f619d08969.png)
GCP アップデート (9/20-9/26 2019)

### GKE: [Sep 20, 2019](https://cloud.google.com/kubernetes-engine/docs/release-notes#september_20_2019)
- HTTP(S)ロードバランサからGKE上のリソースへのroutingをしてくれるIngress Controller v1.6がGAになったよ。
  - v1.13-7-gke.5以上が対象。
  - マネージドSSL(ベータ)、Cloud Armor、Cloud CDN, IAP等もコントロール可能。
  - 手動で設定変更するとGKEが上書いちゃうので、必ずGKE経由で操作すること。

### Composer: [Sep 20, 2019](https://cloud.google.com/composer/docs/release-notes#September_20_2019)
- europe-west6でGAになったよ。

### VPC: [Sep 20, 2019](https://cloud.google.com/vpc/docs/release-notes#September_20_2019)
- VPCのフローログを時間単位で集計、サンプリング、メタデータの操作によってログ料を抑える機能がGAになったよ。
  - フローログ大量にでて地味にお金かかるので良さそう。

### Compute: [Sep 23, 2019](https://cloud.google.com/compute/docs/release-notes#september232019)
- N2マシンタイプがasia-east1-a, asia-east1-b、europe-west4-a、us-central1-fで使えるようになったよ。
- C2マシンタイプがasia-southeast1-b, asia-southeast1-c、europe-west4-a、us-west2-a, us-west2-c、us-central1-fで使えるようになったよ。

### Dataproc: [Sep 24, 2019](https://cloud.google.com/dataproc/docs/release-notes#september_24_2019)
- DataprocのノードにGPUをつけられるCompute Engine Accelerator SupportがGAになったよ。
  - [使えるGPU](https://cloud.google.com/dataproc/docs/concepts/compute/gpus#types_of_gpus)

### DNS: [Sep 24, 2019](https://cloud.google.com/dns/docs/release-notes#September_24_2019)
- DNSフォワーディングがGAになったよ。
  - 記憶にないと思ったらベータになったの去年でした。

### Compute: [Sep 24, 2019](https://cloud.google.com/compute/docs/release-notes#september242019)
- vCPU数に応じてPDの性能が上がったよ。
  - 16個以上は読み込み1,200MB/s、書き込み400MB/s
     - ドキュメント上は16より多ければですが、恐らく16個は含むはず。。
  - 8-15個は読み込み800MB/s、書き込み400MB/s

### Compute: [Sep 25, 2019 フィード来なかった](https://cloud.google.com/compute/docs/release-notes#september242019)
- gVNICがベータになったよ。
  - gVNICはvirtIOよりも性能良くなったNIC。
- v1beta1とv0.1メタデータサーバがシャットダウン予定。
  - metadata使っててv1に移行してない方はv1に移行しましょう。
- SSHのホストキーをインスタンスの[guest attributeに保存する機能](https://cloud.google.com/compute/docs/instances/connecting-to-instance#store-host-key)がGAになったよ。
  - ``gcloud compute ssh``使ってる場合は利用すると良さげ。

### Spanner: [Sep 25, 2019](https://cloud.google.com/spanner/docs/release-notes#September_25_2019)
- 1-nodeや2-nodeを含む全てのspannerインスタンスのアップタイムのSLAがリージョナルは99.99、マルチリージョナルは99.999%になったよ。

### Cloud Run: [Sep 25, 2019](https://cloud.google.com/run/docs/release-notes#september_25_2019)
- フルマネージド版Cloud RunがgRPCに対応したよ。

### Billing: [Sep 25, 2019](https://cloud.google.com/billing/docs/release-notes#september_25_2019)
- billingページがURLブックマークと共有をサポートし始めたよ。
  - フィルタやグルーピングの設定がURLで設定されるのでURLで一意に特定されるようになった。

### Cloud Run: [Sep 26, 2019](https://cloud.google.com/run/docs/release-notes#september_26_2019)
- サービス詳細のメトリックスのページで課金やエラー状況わかりやすくなったよ。
 
### ディスクレーマ
- アップデートの内容はあくまでも個人の理解していることを書いています。正しい内容はリリースノート等を確認下さい。
- リリース内容できるだけ拾うようにしているのですが、抜けていそうなリリースノートが追加するのでぜひ教えて下さい！(一覧[ここ](https://qiita.com/kenzkenz/items/ac18a359b803dbb6b490)で更新してます。)
NavigationBarのTitleを左に寄せたい時の手っ取り早い方法とExtension

iOSでNavigationControllerを使用した際のTitleは通常中央に表示されます。
Large Titleを選択したら、大きいTitleが左寄せで表示されます。

ただし、Androidでは通常左寄せの表示になるようです。

Androidファーストな企画の場合、Large Titleではないのにも関わらず左寄せを要求されることがあります。

その時の実装を備忘録として残しておきます。

##実装
```UIViewController+ext.swift
import UIKit

extension UIViewController {
    /// NavigationBarの左にローカライズされたタイトルを表示する
    func setLeftTitle(_ localizedStringKey: String) {
        let titleLabel = UILabel(frame: CGRect(x: 4, y: 0, width: view.frame.width, height: 28))
        titleLabel.text = localizedStringKey.localized
        titleLabel.textAlignment = .left
        titleLabel.font = .systemFont(ofSize: 17, weight: .semibold)
        titleLabel.textColor = .white
        navigationItem.titleView = titleLabel
    }
}
```

全ての画面で実装を書くのは流石にしんどかったのでエクステンションで実装しました。

```UIViewController.swift
    override func viewDidLoad() {
        super.viewDidLoad()

        setLeftTitle("左寄せで表示したいタイトル名")
    }
```

この実装でいけました！
余白もいい感じ（？）に開いてます。

また、戻るボタンをカスタマイズしている画面ても問題なく同時表示できたので良かったです。
JestでPuppeteerを動かしてCIで実行する

## 概要

- Reactで作ったアプリのE2EテストをCIで動かしたときのメモ
- 簡単なサンプルを作成してGitHub Actionsで動かすところまで紹介します

## はまったところ

- ローカルでPuppeteerを実行する際は、アプリを起動しておいて別ターミナルでテストを実行すればよいので問題なかった
- CIで動かそうとした際に、その場でアプリを起動してそれに対してE2Eテストを実行したかったがどうやればいいか分からなかった

## 解決策

- [jest-puppeteer](https://github.com/smooth-code/jest-puppeteer)を使うとテスト実行前にアプリを起動してくれるように設定できる

## コード

- アプリのセットアップ

```bash
npx create-react-app jest-puppeteer-sample
cd jest-puppeteer-sample
yarn add -D jest puppeteer jest-puppeteer
```

- テストを作る

```js:/e2e/sample.e2e.js
beforeAll(async () => {
  await page.goto('http://localhost:3000');
});

afterAll(async done => {
  done();
});

it('ページが表示されること', async () => {
  const text = await page.evaluate(
    () => document.querySelector('p').textContent,
  );
  expect(text).toBe('Edit src/App.js and save to reload.v');
});
```

- jestの設定ファイルを作る

```json:/e2e/config.json
{
  "preset": "jest-puppeteer",
  "testMatch": ["/**/*.e2e.js"]
}
```

- jest-puppeteerの設定ファイルを作る
    - このファイルが今回実現したかった内容の設定！
    - これを書いておくとテスト実行前にアプリを起動してくれる！

```js:jest-puppeteer.config.js
module.exports = {
  server: {
    command: 'BROWSER=none yarn start',
    port: 3000,
  },
};
```

- npm scriptsにE2Eテストの実行コマンドを追加する

```js:package.json
  // ...
  "scripts": {
    // ...
    "e2e": "jest -c ./e2e/config.json"
  },
  // ...
```

## ローカルで実行

- まずはローカルで実行してみる

<img width="402" alt="スクリーンショット 2019-09-26 8.00.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/db03b76b-6013-ca3f-fe8e-9ce4dd9d31f9.png">

- 事前にアプリを起動することなく、このコマンドだけで実行できた

## GitHub Actionsで実行

- CIで回してみる
    - 今回はGitHub Actionsを使ってみる
- 設定ファイルの追加
    - nodeの環境を作ってライブラリをインストールしてテストを実行している

```yml:.github/workflows/main.yml
name: Main
on: [push]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v1
      - name: Use Node.js 12
        uses: actions/setup-node@v1
        with:
          node-version: 12
      - name: install
        run: |
          yarn install
      - name: test
        run: |
          yarn e2e
```

- GutHubにPushすると実行される

<img width="836" alt="スクリーンショット 2019-09-26 8.16.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/175213/58783162-55a7-1af0-2697-e45d55e71095.png">

- CIでもJestを使ってPuppeteerを実行することができた！
plunkerでtensorflow.js その11


#概要

plunkerでtensorflow.jsやってみた。
練習問題やってみた。

#参考にしたページ

https://www.d4yvector-blog.gq/2019/07/09/nodejs-tensorflow-alphabet-order/

#練習問題


アルファベット順を予測するモデルを学習する。
例えば、「ab」と入力されれば「c」、「hi」と入力されれば「j」、「za」と入力されれば「b」が出力されるようなモデルを作る。LSTMを用いて

#成果物

https://embed.plnkr.co/cFo02RursFmTZP0bylYY/


以上。
ONNXで eliminate_nop_dropout 最適化

ONNXがサポートしている最適化 eliminate_nop_dropout を調べてみました。

対応するソースはおそらくここ。
https://github.com/onnx/onnx/blob/master/onnx/optimizer/passes/eliminate_nop_dropout.h

```C++
  bool patternMatchPredicate(Node* node) override {
    return (node->kind() == kDropout && node->hasAttribute(kratio)) &&
        node->f(kratio) == 0.0;
  }

  bool runTransform(Node* node, Graph&, NodeDestroyType& destroy_current)
      override {
    // Don't assume that theres only one output.
    for (size_t i = 0; i < node->outputs().size(); ++i) {
      node->outputs()[i]->replaceAllUsesWith(node->input());
    }
    destroy_current = NodeDestroyType::DestroyOne;
    return true;
  }

```

連続するnopとdropoutではなく、nopと同じ意味のdropout(ratio=0.0)を削除しています。なるほど。

さっそくテスト用のグラフを作って試しました。

![eliminate_nop_dropout.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/38685eed-c51c-c25f-33e2-e2a76ccea7cf.png)

左のDropoutがratio=0.0, 右のDropoutがratio=0.5に設定してあります。

最適化パスにeliminate_nop_dropoutを追加して、optimizer.optimizeを呼び出して最適化します。

```python
# 最適化パスを指定
passes = ['eliminate_nop_dropout']

optimized_model = optimizer.optimize(model_def, passes)
```

![eliminate_nop_dropout_optimized.onnx.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/327/2d62cc50-f876-762b-c3bc-d0062e4a03a3.png)


予想通り、左側のdropoutのみ削除されました。eliminate_nop_dropout は、ratioが0.0に設定されたnopと同じ（何もしない）dropoutを削除します。

全ソースです。

```python
import onnx
from onnx import helper
from onnx import TensorProto
from onnx import optimizer

X = helper.make_tensor_value_info('X', TensorProto.FLOAT, [1, 2])
Y = helper.make_tensor_value_info('Y', TensorProto.FLOAT, [1, 4])

node_def = helper.make_node(
    'Pad',
    ['X'],
    ['pad_out'],
    mode = 'constant',
    value = 1.5,
)

dropout_00 = helper.make_node(
    'Dropout',
    inputs = ['pad_out'],
    outputs = ['dropout_00_out'],
    ratio = 0.0
)

dropout_05 = helper.make_node(
    'Dropout',
    inputs = ['pad_out'],
    outputs = ['dropout_05_out'],
    ratio = 0.5
)

concat = helper.make_node(
    'Concat',
    inputs = ['dropout_00_out', 'dropout_05_out'],
    outputs = ['Y']
)


graph_def = helper.make_graph(
    [node_def, dropout_00, dropout_05, concat],
    'test-model',
    [X],
    [Y]
)

model_def = helper.make_model(
    graph_def,
    producer_name='onnx_example'
)

onnx.save(model_def, 'onnx/eliminate_nop_dropout.onnx')

# 最適化パスを指定
passes = ['eliminate_nop_dropout']

optimized_model = optimizer.optimize(model_def, passes)
onnx.save(optimized_model, 'onnx/eliminate_nop_dropout_optimized.onnx')


```
Vue.jsのプロジェクト内（Vue-Cli version2系）でpackage.jsonのバージョン番号を参照したい

Vue-CLI2で作成したVueプロジェクトでpackage.json内にあるバージョン番号を使用したかったので調べました。
Vue-CLI3はここの記事の方法だとだめなようです。その場合はこちらの[QA](https://forum.vuejs.org/t/in-cli3-how-to-get-version-from-package-json/34876/6)を参照してください。

```vue.config.js
const webpack = require('webpack');

module.exports = {
    configureWebpack: {
        plugins: [
            new webpack.DefinePlugin({
                'process.env': {
                    PROJECT_VERSION: '"' + (require('./package.json')).version + '"'
                }
            })
        ]
    },
}
```

使用する側

```js:App.vue
mounted() {
    console.log(`Version=${process.env.PROJECT_VERSION}`);
}
```
control + r 　をターミナルで実行すると、コマンドを後方検索できるんや。

`control + r`
で過去に打ったコマンドの検索ができる。

`control + r `
で検索モードに入るので、そこで検索したいコマンドを入れると候補が出てくる

その中で
`control + r `
をやると、その前に打ったコマンドが出てくる


参考
https://qiita.com/quwa/items/3a23c9dbe510e3e0f58e
iOSのショートカットでNowPlayingする

#作った

<blockquote class="twitter-tweet"><p lang="ja" dir="ltr"><a href="https://twitter.com/hashtag/NowPlaying?src=hash&amp;ref_src=twsrc%5Etfw">#NowPlaying</a> するショートカット作った<a href="https://t.co/WfCnu9q02q">https://t.co/WfCnu9q02q</a> <a href="https://t.co/vbZVwztvA9">pic.twitter.com/vbZVwztvA9</a></p>&mdash; Hiro (@hiro2do) <a href="https://twitter.com/hiro2do/status/1176960065242202113?ref_src=twsrc%5Etfw">September 25, 2019</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>

__ダウンロードは[こちら](https://t.co/WfCnu9q02q)__

#簡単でしょ？
皆さーん！ショートカット、使ってますかー？
ショートカットを使えば簡単なことなら簡単に自動化することができます。

ショートカットはiOS 13.1で大幅に強化されました！
Appの起動や位置情報に基づく自動実行も可能になりました。
POSTでWeb APIを叩いたり(制作中)[Pythonistaで任意のPythonスクリプトを走らせる](https://qiita.com/hiro2do/items/8e8998569c5c87cfce69)ことだってできちゃいます！

さあ皆さんも、れっつショートカット！
React videoでmutedが消えるバグのパワー系解決

# スマホブラウザで動画が自動再生できない

今のブラウザで動画（mp4）を自動で再生させるためには、
必ず***[muted]***プロパティをつけて上げる必要があります。

```html
<video autoplay muted playsinline src="video.mp4"></video>
```

理由はブラウザ側で、***[autoplay]***プロパティがついた動画を自動で再生しようとしたときに、
音が出てしまうとUX的にだめだよねってことらしいです。

たしかに、サイト開いて急に音が出てきたら嫌ですね。
だから***[muted]***つけて、音は出さないように設定しとかないと自動再生させてくれません。

参考：https://webliker.info/52510/#toc_8

そこでReactで実装しようと思ったときに、「mutedを書いてるのに自動再生されないぞ？」となったので、
パワー系（とりあえず動く）で解決したのでメモ。

# ISSU
結構前から上がってるのにもかかわらず、なぜに未だ解決されてないのか。。。
解決してこいよって思うかもしれませんが、一旦そこはおいといてください。。。

https://github.com/facebook/react/issues/6544

# ちょっと再現
そもそも本当に***[muted]***がつかないのか検証します。

***codesandbox***
https://codesandbox.io/s/nostalgic-currying-7q2vp

今回はvideoタグを生で書くパターンと、react-videoってライブラリ両方利用して書いてみました。

```jsx
import React from "react";
import ReactDOM from "react-dom";
import { Player } from "video-react";

import "./styles.css";

function App() {
  return (
    <div className="App">
      テスト動画
      <div>
        <video
          autoPlay
          loop
          muted
          playsInline
          width="400px"
          height="200px"
          src="test.mp4"
        />
      </div>
      <Player
        autoPlay
        loop
        muted
        playsInline
        width="400px"
        height="200px"
        src="test.mp4"
      />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

インスペクタから要素を見に行くと、やはりどちらもついてないですね。。。

***videoタグ***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/cb1c0cd9-2253-d549-d3bd-1eb3baa81586.png)

***react-video***
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/cbc38283-5d93-0b81-fbd0-cf27569640cb.png)

ライブラリの意味。。。

# パワー系解決
結論から言うと、***dangerouslySetInnerHTML***で無理やり書いていきます。
実は上のissuの中にも入っていたんですが、ライブラリを作ってくれている人がいました。

***github***
https://github.com/DylanVann/react-video-tag

私はこれを参考にラップしたのを利用していますが、
まずはこれを試してみます。

***codesandbox***
https://codesandbox.io/s/jovial-meninsky-zz782

```jsx
import React from "react";
import ReactDOM from "react-dom";
import { VideoTag } from "react-video-tag";

import "./styles.css";

function App() {
  return (
    <div className="App">
      <VideoTag src="test.mp4" muted autoPlay playsInline loop />
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
```

無理やりですが、たしかに***[muted]***がついてますね。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/160041/b76603ea-9905-b59b-e37b-22b7b18035b7.png)

# まとめ
ちょっとunsafeなやり方ではあるんですが、
どうしても「mp4を自動再生したい！」って場合はこれで解決できそうです。

ただこの解決方法自体はかなりいけてないので、
他にいい方法があったらご教授お願いします。。。

はやく直してほしいですね。
Homebridgeを簡単にデーモン化する

#大変そう
一般的に紹介されている方法だと自分の環境じゃなんかうまくいかないし大変そう
でもデーモン化しないと色々と面倒
Homebridgeもnodejsで動くのでpm2でいけるんじゃね？って思ったら普通にいけました

#やり方

```
sudo npm install pm2 -g
pm2 startup
pm2 start homebridge
pm2 save
```
終わりっ！
簡単ですね

#リンク
Homebridge公式に普通に乗ってました
https://github.com/nfarina/homebridge/wiki/Running-HomeBridge-on-a-Raspberry-Pi#running-homebridge-on-boot-using-pm2
【小ネタ】AWSの公式ドキュメントの見た目が新しくなったので試してみた

# はじめに

ここ数週間、AWS公式ドキュメントのトップに以下のような案内が表示され続けているので、ちょっと試してみました。

> The AWS Documentation website is getting a new look!
> Try it now and let us know what you think. Switch to the new look >>
> 
> You can return to the original look by selecting English in the language selector above.

# 見た目の違い
全体的なテイストは、薄い青を基調とした感じになっています。
AWS Management Consoleも随時リニューアルされていますが、あのテイストですね。

左ペインに各ページへのリンク、中央ペインに本文、右ペインに当該ページ内の見出しへのリンク、という形式は変わりません。

## リニューアル前（現行）
![2019-09-26_03h44_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137777/c8368da7-0b47-7e1b-8bad-4ed1f7b9b06f.png)

## リニューアル後
![2019-09-26_03h44_34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137777/8825d45c-5bb2-32e7-6813-938975a7444a.png)


# 機能上の違い
基本的な構成はリニューアル前後で変わりませんが、大きく以下の点が違うなと思いました。

1.ドキュメントをPDF/Kindleで参照できる
2.RSSフィードでドキュメントの更新が分かる
3.フィードバック用の機能（Did this page help you?など）がデカい、非表示にできない

## 1.ドキュメントをPDF/Kindleで参照できる
ページ上部のリンクからPDFファイルのダウンロードができます。全ページ丸ごと（このケースではAWS CloudFormationのページすべて）1ファイルに結合されて出てきます。
全部で3697ページありました。どう活用しろと…

![2019-09-26_03h23_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137777/07268175-9ff3-3722-c25d-5d6676282644.png)

「Kindle」を押すと、Amazonのサイト（米国本国）へ飛びます。
電車内等でAWSのドキュメントを調べるときは間々ありますが、スマートフォンで見るのは地味に厳しかったりするので、この機能は個人的には嬉しいです。
ただ、普段は日本のAmazonを利用しているので、Kindleアプリ側でAmazonアカウントを切り替える必要がありますが、複数のAmazonアカウントを登録／切り替えする方法が分からず…

![2019-09-26_03h25_30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137777/a344d356-5768-ce39-abca-ccb159724367.png)


## 2.RSSフィードでドキュメントの更新が分かる
こんな感じでRSSが提供されるようです。

![2019-09-26_03h35_21.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137777/82a9b867-2905-305a-1d57-5f0be4571fb9.png)

## 3.フィードバック用の機能（Did this page help you?など）がデカい、非表示にできない
この機能、これまではページ最下行にひっそりとリンクが配備されていたのですが、これが大きくなりました。
個人の感想ですが、ちょっと主張すぎな気もします。

あと、Next topic/Previous topicというリンクが追加されたようです。

![2019-09-26_03h37_28.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/137777/ccd7faf3-4325-1d50-ce20-e5f539392ca1.png)

# おわりに
まだbeta段階なので、利用者からのフィードバックを受けて改善されていくでしょう。
要望があれば早めにfeedbackを送ると、反映されるかもしれません。
【Swift】 画面遷移時に遷移先画面に値を受け渡す

####はじめに
アップデートで修正中のアプリで、似たような機能の画面を２つ追加する要件があったんですが、「これ、素直に画面を２つ作るより、遷移元を判定して画面項目の表示を切り替えた方がむしろスマートだと思う」という発想から、じゃあどうやって遷移元の情報を遷移先に渡そうか、というところをフィージビリティ検証しました。

####開発環境
端末:MacBook Pro/MacOS 10.14.5(Mojave)
Xcode:10.2.1
Swift:5

####やったこと
２つの画面を作り、遷移元画面から遷移先画面へ値が受け渡せることの確認
（受け渡れた値を元に表示切り替え、は検証するまでもないので対象外）

####実装サンプルソース
#####画面イメージ　※画面はStoryboardで作成

|遷移元|
|:-:|
|<img width="768" alt="Simulator Screen Shot - iPad Air 2 - 2019-09-26 at 02.00.42.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/8ed3258c-ad61-dd11-f516-e2389919204c.png" width="400">|

|遷移先|
|:-:|
|<img width="768" alt="Simulator Screen Shot - iPad Air 2 - 2019-09-26 at 02.00.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/c33009e9-798a-9d7e-d195-6ea9d592faf6.png" width="400">|

```swift:MotoViewController.swift(遷移元画面)
import UIKit

class MotoViewController: UIViewController {

    // 受け渡す値の入力エリア
    @IBOutlet weak var txtPassString: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    // 「遷移先画面へ」ボタン押下時
    @IBAction func transition(_ sender: Any) {
        let storyboard = self.storyboard
        // 遷移先画面
        let sakiView = storyboard!.instantiateViewController(withIdentifier: "saki") as! SakiViewController
        // 遷移先画面の項目へ受け渡す値をセット
        sakiView.passedString = txtPassString.text!
        // 画面遷移
        self.present(sakiView, animated: true, completion: nil)
    }
}
```

```swift:SakiViewController.swift(遷移先画面)
import UIKit

class SakiViewController: UIViewController {
    
    @IBOutlet weak var txtPassedString: UITextField!
    
    var passedString: String?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        if (passedString != nil) {
            txtPassedString.text = passedString
        }
    }
}
```

コードの量としては思っていたよりも少なく実装できました。
が、遷移先画面のStoryboard IDを指定するのを忘れないよう注意が必要。（下の画像を参照）

<img width="773" alt="Screen Shot 2019-09-26 at 3.22.31.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/ce780afe-2a01-bc52-54a4-b531ba2939d6.png">


####画面サンプル
GIFでの動作イメージです。
![myTransitionImage.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/126315/704490c8-7035-fc7c-2de3-6b5729b27003.gif)

青い画面(遷移元)で"test"と入力したのが、黄色い画面（遷移先）に渡されて画面中央のエリアに表示されています。

※GIF作成アプリで動作イメージ見てた時は気づかなかったけど、画面遷移時、画面がすごくチラつきますね。。
　見づらくてスミマセン。。

####参考にさせて頂いたサイトなど
カピ通信 - 【Swift/iOS】画面遷移時の値渡し
https://capibara1969.com/1060/#toc10
tableでborder-radiusを設定する方法

# 概要
CSSで`border-radius`と`border-collapse`プロパティが共存してくれなくて面倒だったのでメモ

# やり方
1. td, thに`border`を設定
2. tableの四隅で`border-radius`を設定

# 動くコード
一例です。この通りでなくてもok

```CSS
/* 表全体の設定 */
table {
  border-collapse: collapse;
}
/* セルの設定 */
td,
th {
  border-bottom: 1px solid #eaeaea;
  border-right: 1px solid #eaeaea;
  border-left: 1px solid #eaeaea;
}
/* 四隅のborderの設定 */
th:first-child {
  border-top-left-radius: 1rem;
}
th:last-child {
  border-top-right-radius: 1rem;
}
tr:last-child td:first-child {
  border-bottom-left-radius: 1rem;
}
tr:last-child td:last-child {
  border-bottom-right-radius: 1rem;
}
/* 重複するborderの消去 */
th {
  border-bottom: none;
}
tr td :not(:first-child),
tr th :not(:first-child) {
  border-left: none;
}
```
Mellanox ConnectX3,4系のモード切り替え(イーサネット、InfiniBand）

SFP+あるいはQSFP+のNIC、Mellanox ConnectXのイーサネットモードへの切り替え法。
デフォルトの設定はInfiniBandになっている。調べるのが大変だったのでメモ。



###1. Windows10
######windows10の場合、ダイレクトアタッチケーブルでPC間を直付けする場合、相手方のNICも適切に設定して接続されるまで「ケーブルが接続されていません」のエラーが出てIP等が反映されないので注意。

これのおかげで結構な時間悩んだ……。

####1.1 ドライバのインストール
WinOFがConnectX3系、WinOF2がConnectX4のドライバ  
https://www.mellanox.com/page/products_dyn?product_family=32&mtag=windows_sw_drivers  
exeファイルを実行してインストール。
####1.2 デバイスマネージャーを起動（windowsマークを右クリック等）
####1.3 ネットワークアダプタのMellanox ConnectXの項目を選択
####1.4 デバイスマネージャーのメニューで「表示」→「デバイス（接続別）」を選択
####1.5 Mellanox ConnectXが二つになるが、親を選択
####1.6 port protocolのタブを選択  
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377965/1fd9481b-27b8-fe7d-302e-9f2655fcbf24.png)
####1.7 HW defaultのチェックを外してETHを選択→OKで抜ける
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/377965/e9256bb2-8ca2-3675-feae-583508717fd4.png)
####1.8 設定→ネットワークとインターネット→アダプターのオプションを変更する、を選択
####1.9 Mellanox ConnectXを選択し、適当なIPアドレスを入力

####参考
https://community.mellanox.com/s/article/howto-install-and-configure-mellanox-driver-for-windows-environment

###2. Linux
####2.1 起動

```
# mst start
```

####2.2 設定ソフトのインストール
mstflintはConnecteX設定変更ツールのオープンソース版でWebサイトを経由せずインストールが可能。

```
Ubuntu等：apt install -y mstflint ibverbs-utils
CentOS等：yum install mstflint ibverbs-utils
```

####2.3 PCI addressの確認

```
mst status
```
例

```
Windows： mt4099_pci_cr0
Linux：　/dev/mst/mt4099_pci_cr0
```
デバイスのPCI addressとして以後適宜書き換えること。

####2.4 設定の変更と確認
下記のコマンドで設定を変更（イーサネット）

```
LINUX
# mstconfig -d /dev/mst/mt4099_pci_cr0 s LINK_TYPE_P1=ETH
windows10
> mlxconfig -d mt4099_pci_cr0 s LINK_TYPE_P1=ETH
```
LINK_TYPE_P1のパラーメーターには、下記の3モードが対応
- ETH：イーサネット
- IB：InfiniBand
- VPI：Virtual Protocol Interconnect（相互利用モード）

再起動後に変更結果を確認

```
# mstconfig -d /dev/mst/mt4099_pci_cr0 q
```

####参考
https://www.mellanox.com/pdf/prod_software/Ubuntu_18_04_Inbox_Driver_User_Manual.pdf

以上
Firebaseの匿名認証をvuexで実装してみる。

vuexでFirebaseの匿名認証を実装したので、サンプルとして投稿してみます。

最終的に、「$store.getters.uid」で、
いつでもどこでもuidを出せるようにすることが目的です。

環境・VueCLI3.0



```store.js
state: {
    login_user: null
},
mutations: {
    setLoginUser (state, user) {
      state.login_user = user
    },
    deleteLoginUser (state) {
      state.login_user = null
    },
},

actions: {
    setLoginUser ( { commit }, user) {
      commit('setLoginUser', user)
    },
    deleteLoginUser ( { commit } ){
      commit('deleteLoginUser')
    },
    logout(){
      firebase.auth().signOut()
    },
    login(){
      firebase.auth().signInAnonymously().catch(function(error) {
        // Handle Errors here.
        var errorCode = error.code;
        var errorMessage = error.message;
        // ...
      });
    },
},

getters: {
    uid: state => state.login_user ? state.login_user.uid : null
}


```

```app.vue
<template>
    <v-icon @click="login">mdi-square-edit-outline</v-icon>
</template>

<script>
import firebase from 'firebase'
import { mapActions } from 'vuex'
import { mapGetters } from 'vuex'

export default {
  created() {
    firebase.auth().onAuthStateChanged(user => {
      if (user) {
        this.setLoginUser(user)
      } else {
        this.deleteLoginUser()
      }
    })
  },
  methods: {
    ...mapActions(['login','setLoginUser','logout','deleteLoginUser']),
    ...mapGetters(['uid'])
  },
}
</script>
```

ほぼコピペで使えると思います！

あとは、Firebaseのコンソールでログイン方法の有効にすれば認証してくれます！

<img width="349" alt="スクリーンショット 2019-09-26 2.26.48.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/447711/59d8ad55-2502-dd57-c01b-4721203fe818.png">



若干解説をすると、

actionで定義したloginを着火させると、

app.vueのcreatedにある　firebase.auth().onAuthStateChanged

が発動してuserオブジェクトからデータを取得し、ミューテーション等を介して最終的にgettersでuidをどこでも取得できるようになります。


なぜ発動するのかというと、公式に「発動するよ☆」って書いてあるので発動します（体育会系の思考）

以上です！


参考・https://firebase.google.com/docs/auth/web/anonymous-auth?hl=ja
[Python] [pathlib] ファイル名を書くのが面倒な人向けの地味テク


データを読み込む際、毎回ファイル名を書くのが面倒だったのですが、
[fast.aiでlsコマンドっぽく書く方法](https://github.com/fastai/course-v3/blob/master/nbs/dl2/08_data_block.ipynb)が紹介されていたので、それをもとに作りました。

##めんどいこと
以下3～7行目の、括弧内部を書くのが地味にめんどうで、予測変換ができない。

```Python
import pandas as pd
path       = 'D:/data/ieee_fraud/'
train_tran = pd.read_csv(path + 'train_transaction.csv')
test_tran  = pd.read_csv(path + 'test_transaction.csv')
train_id   = pd.read_csv(path + 'train_identity.csv')
test_id    = pd.read_csv(path + 'test_identity.csv')
sample_sub = pd.read_csv(path + 'sample_submission.csv')
```



##こうする
はじめに以下のコードを実行すると、数字とファイル名が表示される。

```Python
from pathlib import Path
Path.ls = lambda x: list(x.iterdir())
path = Path("D:/data/ieee_fraud")      # 指定したいpathに設定する

# 方法1 (方法2と結果は同じ)
for i, p in enumerate(path.ls()): 
    print(i, str(p).split('\\')[-1])   # \ はescapeなので\\の2つ

# 方法2 (方法1と結果は同じ)
for i, p in enumerate(os.scandir(path)):
    print(i, p.name)
```

```Python
0 sample_submission.csv
1 test_identity.csv
2 test_transaction.csv 
3 train_identity.csv
4 train_transaction.csv 
```

上記の表示結果をもとに、以下のように埋める。

```Python
import pandas as pd
train_tran = pd.read_csv(path.ls()[4])
test_tran  = pd.read_csv(path.ls()[2])
train_id   = pd.read_csv(path.ls()[3])
test_id    = pd.read_csv(path.ls()[1])
sample_sub = pd.read_csv(path.ls()[0])
```

私の場合、[フリーソフトのClibor](https://yossense.com/clibor/)で上記のコードを保存し、いつでも取り出せるようにしています。
余談ですが、[pickleファイルのほうがcsvファイルより圧倒的に読み込みが速いです。](https://qiita.com/ctn15/items/501d8f838234f2308490)


[IEEEコンペ](https://www.kaggle.com/c/ieee-fraud-detection)、あと1週間切りましたね。さっぱりわかりませんが、がんばりましょい。
Gitでよく使いそうなコマンドについて

#はじめに
Gitの操作を普段作業する時、GitHub Desktopを使用していたのでターミナル操作があまり出来ませんでした。
今回はよく使いそうなコマンドを個人的にまとめようと思います。

##git add、git commit
変更したファイルをインデックスステージにあげるコマンド、編集履歴をインデックスステージに上げて`commit`する事で変更が確定されます。

```
//修正したファイルをインデックスに追加
$ git add .

//インデックスに上がっている履歴をコミットする
$ git commit -m "コミット名"
```

##git status
インデックスステージの内容を確認出来るコマンドになります。このコマンドを使用し、まめに編集履歴を確認する事が大事です。

####編集履歴がある場合

```ruby:
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   db/migrate/20190907071710_create_comments.rb

no changes added to commit (use "git add" and/or "git commit -a")
```

####編集履歴がない場合

```ruby:
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
```

##git branch、git checkout
ブランチの確認や作成で使用します。私も間違えようになったのですが、確認は`git branch`ブランチ作成や移動は`git checkout`を使用します。

```
//新規ブランチ作成し、そのブランチに変更する。
$ git checkout -b "ブランチ名"

//ブランチの変更
$ git checkout "ブランチ名"

//ブランチ確認
$ git branch
```

##git push
ローカルでの編集をリモートリポジトリに反映させるのに使用します。`git push origin HEAD`は一番新しいコミット履歴を反映させる事が出来るのでそちらの方が使用するのに便利かと思います。

```
//リモートリポジトリに反映
$ git push origin 現在のブランチ名

//一番新しいコミット履歴を反映させる
$ git push origin HEAD
```

##最後に
ターミナルでのgitの操作は`git status`、`git branch`でどこのブランチで作業してるのか確認する事が大事だと思います。
ターミナルでの操作があまり慣れてないので、今後もターミナルで操作をし慣れていきたいと思います。
自動スピーチ認識(ASR, automated speech recognition)ライブラリのメモ(2019 年 9 月 25 日時点)

## ASR とは?

automated speech recognition. 
主にはスピーチ音声から文字起こし(テキスト化. STT, speech to text)するのを想定.
(ライブラリによっては感情とかピッチとかも推定できるっぽい?)

## NeMo(Jasper, QuartzNet)

https://github.com/NVIDIA/NeMo

NVIDIA 製. 2019 年 9 月 25 日執筆時点では, できたてほやほや.

NeMo 自体はフレームワークの名前で, ASR と NLP のモジュールがある.
ASR モジュール部分は Jasper と QuartzNet(の PyTorch 実装).  

https://github.com/NVIDIA/DeepLearningExamples/tree/master/PyTorch/SpeechRecognition/Jasper

https://nvidia.github.io/NeMo/asr/intro.html

end-to-end で ASR 学習できるっぽい.
もともとは OpenSeq2seq の一部として, そこそこ前から開発されていた模様.

Jasper: An End-to-End Convolutional Neural Acoustic Model
https://arxiv.org/abs/1904.03288

Jasper 自体は使っている Neural network モジュールは比較的単純なものなので, 頑張ればモバイル推論できるものと思われる. 
ただし KenLM を使っているところがあるようなので, この部分は書き直しが必要かもしれない.
(いずれにせよ KenLM は LGPL 2.1 なので, モバイルで製品化したいときは KenLM 部分は書き直ししたほうがベター)


## Deepspeech

Mozilla 製.
pip install でインストールできて便利. Android などモバイルでもビルドできる模様(動作未確認)

Mozilla deepspeech で speech-to-text する(English). アン・ハサウェイさんのスピーチの文字起こしにもチャレンジ
https://qiita.com/syoyo/items/9e5898344403b896bf04

## Kaldi

https://kaldi-asr.org/

それなりに昔からあり, 利用されてきたらしい. Montreal forced aligner でも利用している.

## wav2letter++

https://github.com/facebookresearch/wav2letter

facebook 製.

C++ で, 音声認識向けに高速化, 効率化しているのが特徴.

C++ で書かれていて, C++ おじさんから見ると一見いい感じで食いつきたくなりますが, よくよくコードを見たりビルドしてみると, flashlight, arrayfire などいろいろと依存ライブラリが多いため(KenLM も含まれる), これをいじりたいとは思わないですね...

## まとめ

2019 年 9 月 25 時点では, NeMo からいろいろと辿っていくのがよさそう.
【paiza 演習問題】島探し (paizaランク S )（タイムアウト）

#対象
これは paizaランク S 相当の練習問題として[ここ](https://paiza.jp/works/mondai/skillcheck_sample/search-island?language_uid=python3)にあった問題の解答を記録するものであり、初心者向けです。
（上級者の方のアドバイスは頂きたいです……）

#概要
入力値ケース９にてタイムアウトを吐かれたのでリファクタリングを行いたい。（未考察、後日追記します）

#コード


```py
def out_of_area_check(width, height, x, y):
    x_in_area = 0 <= x < width
    y_in_area = 0 <= y < height
    #print(width, height, x, y)
    #print(x_in_area, y_in_area)
    return x_in_area and y_in_area


def island_seek(frontline_x, frontline_y, value_map, index, width, height):
    while len(frontline_x) > 0:
        #print('check')
        for _i, _j in zip([+1, -1, 0, 0],[0, 0, +1, -1]):
            x = frontline_x[0] + _i
            y = frontline_y[0] + _j
            if out_of_area_check(width, height, x, y):
                #print(x, y)
                if value_map[y][x] == -1:
                    value_map[y][x] = index
                    frontline_y.append(y)
                    frontline_x.append(x)

        del frontline_x[0]
        del frontline_y[0]
    else:
        return


def peninsula_seek(frontline_x, frontline_y, value_map, index, width, height):
    for _x in range(width):
        for _y in range(height):
            if value_map[_y][_x] == -1:
                value_map[_y][_x] = index
                frontline_y.append(_y)
                frontline_x.append(_x)
                return True
    else:
        return False


def solve():
    width, height = map(int, input().split())
    value_map = [list(map(int, input().split())) for _ in range(height)]
    frontline_x = []
    frontline_y = []
    index = 0
    for j in range(width):
        for i in range(height):
            if value_map[i][j] == 1:
                value_map[i][j] = -1

    peninsula = True
    while peninsula:
        index += 1
        #print('index+1')
        peninsula = peninsula_seek(frontline_x, frontline_y, value_map, index, width, height)

        #print(value_map)
        if peninsula:
            island_seek(frontline_x, frontline_y, value_map, index, width, height)
            #print(value_map)
        else:
            print(index-1)
            return


if __name__ == "__main__":
    solve()
```
WordpressからSMTP経由でSendgridを利用する際に忘れてはならぬこと

WordpressからSTMP経由でメール送りたいこと、よくあるよね。ある。そんなときに、WP Mail SMTPっていう便利なプラグインがあるんで、今回それを使ってSendgridからメールを送信してみることにした。

[How to Set Up the SendGrid Mailer in WP Mail SMTP](https://wpmailsmtp.com/docs/how-to-set-up-the-sendgrid-mailer-in-wp-mail-smtp/)

そしたら猛烈な文字化け。よく調べてないけど、多分ISO-2022-JPをUTF-8で無理矢理読んだ系の化け方。困ってヘッダーとか読んだんだけど、`Content-Type: text/plain; charset=us-ascii`とか書いてあって、「us-ascii…！？！？」と天を仰いだ。

Wordpressのメール送信系を司っておる「wp_mail()」には便利なフックがあって、

```php
apply_filters( 'wp_mail_charset', function()
{
return 'UTF-8';
})
```

とかやると、文字コードを変えてくれる。
なんだけど、それやっても駄目。おそらくSendgrid上で書き換わってる。すげえ困る。

そんな時は、このページを良く読むんだ…。よく…読むんだ…。

[SendGrid's WordPress Plugin | SendGrid Documentation](https://sendgrid.com/docs/for-developers/sending-email/wordpress-plugin/)

---

要は、**「Sendgridの[公式Wordpressプラグイン](https://wordpress.org/plugins/sendgrid-email-delivery-simplified/)を使い給え」**ってことなんですけど、もう一点、「SMTP使いたければSwift Mailerを使え、[プラグインは用意してある](https://wordpress.org/plugins/swift-mailer/)」というのも重要。このプラグインをダブルで有効にして、API Keyを登録すれば使える（API Keyは[ここ](https://app.sendgrid.com/settings/api_keys)から出力して。必要な権限は、「Mail Send」のみでOKなので、Full Permissionは不要）。

- [SendGrid – WordPress plugin | WordPress.org](https://wordpress.org/plugins/sendgrid-email-delivery-simplified/)
- [Swift Mailer – WordPress plugin | WordPress.org](https://wordpress.org/plugins/swift-mailer/)

文字化けも見事に解消しました。

---

※ ちなみに、他にも文字化けの要因はあって、まだ解消しない人は[この辺り](https://sendgrid.kke.co.jp/blog/?p=1521)を確認してみて
※ Git使ってデプロイしてる人。Sendgridの公式プラグインは、Composerパッケージを思いっきり含んでるので、`.gitignore`で`vendor`を対象にしちゃってる人は要注意ね
※ 雑な推量で文字コードとか書いてるのは、文字化けで困ってるんだけど検索ワードがよくわからなくて迷ってる子羊用なので色々察して
定期的にサーバーサイドで自動スクレイピングしたい

あるサイトのナビゲーションの内容が変わったら知りたいと思う事があったので、採用した手段と調べた事を残しておきます。

今回の要件

- サーバーサイドで実行したい
- 1日1回実行したい
- 1URLのみを対象とする
- ナビゲーションの内容と項目数を知りたい
- お金はかけたくない
- 手軽に済ませたい
- 結果を通知したい

## 結論

いくらか調べたのですが、結局

- GASを時間ベースのトリガーで実行して
- URLをFetchして取得したHTML文字列を
- 正規表現で必要な部分のみ抽出し
- Gmailで結果を送信する

ことにしました。

## 候補手段

頭に浮かんだのは下の手段でした

- スクレイピングサービス
- AWS Lambda
- GAS

### スクレイピングサービス

https://www.octoparse.jp/

はじめは、こちらのサービスの無料プランで試そうとしたのですが、14日間の無料トライアルの後、自動的に有料プランに移行されるらしく、今回の要件に合わないのでやめました。

解約もすんなりいかずに精神的に消耗したので、サービスを探すのはやめました。

### AWS Lambda

できるのはわかってますが、お手軽に済ませたいのでスキップしました。

### GAS

トリガーがあり、Gmailも簡単に送れて良さそうなので、今回はGASを使う事にしました。

## GASで特定の要素を取得する候補手段

HTMLを取得する部分と、Gmailを送信する部分はサンプル通りに1行書けば良いだけでした。
HTMLから必要な要素をいかにして取り出すかで、少し考える事になりました。

### XMLをパースして1階層ずつたどっていく

https://web.plus-idea.net/2018/04/google-apps-script-xmlservice-parse/

`rootDoc.getChild('Body', nsSoapenv).getChild('loginResponse', ...`

GASの標準機能でセオリーっぽいのですが、1階層ずつ指定していくのは嫌なので採用しない事にしました。

### IMPORTXML

https://support.google.com/docs/answer/3093342

spreadsheetのimportxml関数で必要な要素を取得した上で、GASで残りの処理をするというアイデアですが、どうせならGASだけで完結させたいので採用しない事にしました。

### querySelectorAllのような機能

ブラウザのJavaScriptなら、selectorを使えば欲しい要素が簡単に取得できるのですが、GASでそれを実現する機能は用意されていないようでした。

### querySelectorAllのPolyfillをGASにもってくる

https://gist.github.com/chrisjlee/8960575

IE7程度のdocumentオブジェクトが利用できる事が前提のようなので、GASに流用するのは無理でした。

### getElementsByClassNameのGASによる実装例

https://sites.google.com/site/scriptsexamples/learn-by-example/parsing-html

対象のXMLが壊れているらしく `XmlService.parse(html);` の行でエラーになりました。
このサイトに対してはXMLのパースが必要な手段は通用しなさそうです。

### 独自のgetElementByClassNameライブラリ

https://sites.google.com/site/scriptsexamples/learn-by-example/parsing-html

こちらもXMLのパースが必要なので、今回は利用できなさそうです。

### 独自のParserライブラリ

https://www.kotanin0.work/entry/2019/01/06/200000

場合によっては有用かもしれないのですが、今回やりたい事程度なら記述量もさほど変わらないので正規表現を使った文字列抽出でいいやという気になりました。

## 実装例

```
function myFunction() {
  var html = UrlFetchApp.fetch(url).getContentText();

  var reg = /<div class="box">([\s\S]*?)<\/div>/g;
  var text = html.match(reg);

  MailApp.sendEmail(mailAddr, mailTitle, text.join("\n"));
}
```

## まとめ

迷う事なく今回の手段を講じていれば、手軽に実現できたと言えるのではないかと思います。
ただ、必要な要素の抽出が泥臭い感じになって残念感があるので、よりスマートな手段を見つけられたらいいなと思います。
xargs コマンドの空白区切り処理

こんにちは。
xargs コマンドの空白文字区切り処理（word-splitting by spaces）について ls コマンドで試してみました[^1]。
なお ```-J``` オプションは POSIX を独自拡張したものです（GNU xargs は持っていません）。```-J``` と ```-n1``` を合わせて指定した場合は ```-I``` と同じ挙動のようです[^2]。


[^1]: xargs コマンドのデフォルトでの「空白文字」区切りは、改行、タブなども含んでいます。

[^2]: ```-J``` オプションを使わず ```xargs -J% ls %``` と同等のことを実現したい場合の方法が現在不明です。

```console
$ ls file_a  file_b
file_a  file_b
$
$ echo file_a  file_b | xargs ls
$ echo file_a  file_b | xargs -L1 ls
$ echo file_a  file_b | xargs -J% ls %
$ echo "file_a  file_b" | xargs ls
$ echo "file_a  file_b" | xargs -L1 ls
$ echo "file_a  file_b" | xargs -J% ls %
file_a  file_b
$
$ echo file_a  file_b | xargs -n1 ls
$ echo file_a  file_b | xargs -n1 -I% ls %
$ echo file_a  file_b | xargs -n1 -J% ls %
$ echo "file_a  file_b" | tr -s ' ' '\n'
$ echo "file_a  file_b" | xargs -n1 ls
$ echo "file_a  file_b" | xargs -n1 -I% ls %
$ echo "file_a  file_b" | xargs -n1 -J% ls %
file_a
file_b
$
```
Windows Update が何時までも終わらない

**滅茶苦茶だるかった。**

今回はMicrosoftが私に与えてくれた(望んでない)試練について書きます。
Windows Updateが毎日毎日失敗する現象です。

1.前置きです。

先月末、我が家のPCでCドライブが破裂しそうになってきました。容量不足です。
Cドライブには100GB SSDが積んであり、6年前に購入したものでした。
容量の大きなファイルはdドライブ(HDD)に保存していたので、Cドライブの中身は
プログラムとシステムファイルが大部分を占めていると思っています。
余談ですが、一年前にはPCが突然青画面になってしまい"SSDご臨終か"と焦ったことが
ありました。しかし翌日からは普通に起動。

そんな現状を考えてCドライブを交換することを決意しました。
新しく500GB SSDを購入して、windows 7をクリーンインストール！！
(私は常にクリーンインストール派です)

インストール終了後、早速SSDの性能をチェックすると読み書きどちらも
2倍くらい早くなっていました。windowsの起動時間も明らかに短くなって
かなりウキウキしてきましたが、この後からMicrosoftとの不毛な戦いが始まりました。

2.本題です。

クリーンインストール後のwindows updateには長時間もっていかれます。200個近かったかな。
ほぼ一日がかりで残りが2,3個までなったので作業は終わった気になってました。
ところが何日経ってもシャットダウンする度にwindows updateが動きます。
犯人はこいつです。

**セキュリティマンスリー品質ロールアップ**

![Img01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/502728/b375bb42-5e99-679e-4fc3-06d8410f2d67.png)


早速googleさんに聞いてみると同じようにお悩みの方々を発見し、対処法を教えてもらえました。
原因についても下記参照↓

https://qiita.com/kokawa2003/items/67efbccedde5911859fb
https://7mc.org/2019/04/10/windows_update_fails_with_monthly_rollup.html

ところがこの対処法では私のPCはダメでした。

システム更新準備ツールを使ってC:\Windows\logs\cbs\checksur.logファイルを確認すると
"No errors detected"と無情な宣告。

したがって最後に成功したマンスリーロールアップを特定することができません。
その後もgoogleさんを頼りに一週間程色々やりましたがギブアップ！！

半月ほど見ないことにしましたが、奇跡が起きました。

3.私の見つけた対処法です。

　①windows updateを起動する。
　②更新プログラムの確認を実行。
　③中身を確認して、表示された全ファイルを右クリックで”**非表示にする**”

するとあら不思議、もう一度②実行すれば"セキュリティマンスリー品質ロールアップKB0000000"の
番号が変化しています。これをwindows update カタログで確認すれば問題となっていた
更新プログラムのひとつ前にリリースされたものでした。

つまり後は、ひたすら②～③を繰り返して更新プログラムが見つからなくなるまでやります。
私は2～3時間ほどで終わりました。

　④非表示の更新プログラムの再表示で"セキュリティマンスリー品質ロールアップ”
　　の中で一番数字の若いファイルのチェックを入れて再表示ボタンを押します。(通常は一番上のやつ)
　⑤windows updateを実行。そして再起動がかかります。

あと④～⑤を繰り返します。補足ですが④でチェックを入れるとき最初はビクビクしながら
一個ずつ入れましたが、後半は３つほどまとめてインストールしましたが問題ありませんでした。
一方で、他のオプションファイルも同時にインストールしようとすると失敗しました。
あと⑤の再起動は横着せずに毎回実行しておいたほうがいいと思います。というか
そんな度胸ありませんでした。

この方法で私はMicrosoftとの戦いを終わらせることができました。
疲れました。達成感はありません。Microsoftへの不信感が募っただけです。

windows 10にしたくねー
マルコフ連鎖botをGoで作った話（後編）

#はじめに
- [マルコフ連鎖botをGoで作った話（前編）](https://qiita.com/cotton392/items/6e8288616a19669d0e4c)
- マルコフ連鎖botをGoで作った話（後編）

今回は前編で作ったコードをCircleCIを用いて定期実行する際の設定や、その時に用いるDockerコンテナの設定などを説明していきたいと思います。

#やること
- Go言語を使ってマルコフ連鎖をするロジックを作る (前編)
- マルコフ連鎖に使うデータは自分のTwitterアカウントのツイートにする (前編)
- 1時間おきにツイートできるように定期実行する機構を作る （この記事）

#定期実行を行う機構について
今回は定期実行を行うためにCircleCIを用いました。
理由としては、

- カスタムDockerイメージが使える(Mecabなどを用いる関係で実行環境を事前に作成しておきたかったため)
- workflowによって実行された結果が管理しやすい

といったものが挙げられます。

#Dockerfileの作成〜DockerHubへのPush
まずCircleCIで用いるDockerコンテナを生成するDockerfileを作成します。
使う用途はこのBotを運用することだけなので、コンテナ生成時に依存パッケージのダウンロードを行って環境変数を設定し、実行ファイルをgitからcloneしてくるところまで行っています。
このDockerfileが以下になります。

```dockerfile:Dockerfile
FROM golang:latest

RUN apt update
RUN apt -y install sudo
RUN sudo apt install -y mecab libmecab-dev mecab-ipadic-utf8 git

ENV GO111MODULE on
ENV CGO_LDFLAGS -L/usr/lib/x86_64-linux-gnu -lmecab -lstdc++
ENV CGO_CFLAGS -I/usr/include

RUN git clone https://github.com/cotton392/ctn_ai.git
```

このDockerfileを使ってDockerコンテナを作成した後、コンテナをDockerHubへPushして準備完了です。

#CircleCI側の設定
次は前項で作成したDockerコンテナを用いて、前回作ったプログラムをCircleCIで1時間ごとに定期実行するように設定していきたいと思います。
CircleCIで定期実行を行うために今回はCircle-CI 2.0のcron triggerを利用しました。
また、push時に`git pull`した後`go build`するようにも設定します。
これらを行うようにするための`config.yml`は以下のようになります。

```yaml:config.yml
version: 2
jobs:
  tweet:
    docker:
      - image: hystyl243/ctn_ai-container:1.0.0

    working_directory: /go/ctn_ai
    steps:
      - checkout
      - run: go run main.go


workflows:
  version: 2
  tweet_workflow:
    triggers:
      - schedule:
          cron: "0 * * * *"
          filters:
            branches:
              only:
                - master
    jobs:
      - tweet

  push_workflow:
    jobs:
      - tweet
```
また、Twitter APIで使用するトークンはCircleCIのプロジェクト内で環境変数を定義してそれを利用しています。

これでマルコフ連鎖Botの完成です！

#最後に
今回の一連の記事では、Go言語でマルコフ連鎖Botを作成する手順を紹介しました。
この記事がマルコフ連鎖のロジックの理解や、Go言語で作られたプログラムをCircleCIで定期実行する方法の理解などに役立てれば幸いです。
また、今回紹介したコードは全て[このGitHubリポジトリ](https://github.com/cotton392/ctn_ai)に置いてありますので良ければ参考にしていただけると幸いです。

それでは、ここまで読んでいただきありがとうございました。
Java基礎学習内容5（修飾子）

# static修飾子
変数・メソッドに付けることのできる修飾子。
インスタンス化せずとも呼び出すことが出来る。また、元のクラスをインスタンス化した場合でも、static変数およびstaticメソッドは一か所に管理される。(=各インスタンスがそれぞれstatic変数を持つというわけではない。)
staticメソッドからはstatic変数またはstaticメソッドのみ呼び出すことが出来る。

また、クラスにはクラスファイルがロードされた際の処理を定義する **staticイニシャライザ** を定義できる。

```java:staticイニシャライザ
class A {
  static {
  // 処理
  }
}
```

#アクセス修飾子
private:同一クラスからアクセス可能
(デフォルト):同一パッケージ内のクラスからアクセス可能
protected:同一パッケージまたはサブクラスからアクセス可能
public:どのクラスからでもアクセス可能

※publicなクラスはクラスファイルにつき一つのみ、かつファイル名と同名のクラスのみ定義可能
Python+SeleniumWebDriverではwebdriver_managerを使うといちいちdriverのexeを置き換えなくて済む

SeleniumWebDriverを使ってブラウザ操作の自動化を行う際には、各ブラウザに対応するdriverを用意する必要があります。

しかし、ブラウザのバージョンが上がるとdriverのバージョンも上がり、その都度driver.exeを置き換えたりするのは面倒です。

チームで自動化しているときに管理担当が居て、都度git管理しているChromedriver.exeなどを更新して・・・という経験もありますがやっぱり面倒です。

そういうときには、webdriver_managerを使いましょう。

## webdriver_manager

詳細はこちらから確認できます。

[SergeyPirogov/webdriver_manager](https://github.com/SergeyPirogov/webdriver_manager)

### インストール

`$ pip install webdriver_manager`

### 使い方

操作したいブラウザのDriverManagerをimportします。

``` Python
from webdriver_manager.chrome import ChromeDriverManager
```

webdriver_managerを使わない場合は直接exeのパスを指定するか、環境変数PATHの通った場所にdriverをおいた状態でカッコの中を空にします。

webdriver_managerを使う場合は以下の例のような書き方になります。

``` Python
def setup_class(cls):
    cls.driver = webdriver.Chrome(ChromeDriverManager().install())
```

これで、あとは実行するたびにブラウザのバージョンに対応したdriverを取得して使ってくれます。

## 注意＆参考

今回のは`webdriver_manager`でしたが、類似のものに

- [webdriver-manager · PyPI](https://pypi.org/project/webdriver-manager/)
- [webdrivermanager · PyPI](https://pypi.org/project/webdrivermanager/)

があります。

基本的にはwebdriver_managerと一緒で、いちいちdriverを自分で用意しなくて済むようになるのですが、細かい使い方など異なるので気をつけてください。

私がwebdriver_managerを選んだのは、ドキュメントが一番充実しているように見えたから、です。
ハンダごてを使うときには綿手をつけよう

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/253945/8ffd9b25-7209-451e-ea59-f887cf6ac066.png" width=50%>

## ハンダ付け熱すぎ問題
近年の電子工作の盛り上がりによってハンダごてを使ってハードウェアを作る人が増えてきました。

老舗の秋月電子通商さんだけではなく、通販で購入できるたくさんの半製品キットがあり、一式そろった材料をハンダ付けするだけでほしい機能が作れるようになっています。こんな素晴らしい環境を利用しない手はありません。

ただ、ハンダ付けにしようするこてはめちゃくちゃに熱くなります。半導体のロウ付けには、ハンダを使うのが一般的ですが、だいたい200度から300度ぐらいになります。普通に使う分には何ら問題のない作業なのですがホビーユースで行うときにはかなり無理な作業を行うことがあります。

熱容量の違うものをハンダ付けする場合、温度が均一にならないことからハンダが玉になり、それが指に落ちたりすると｢あっっっっっつ｣と一人悶えることになります。

電子部品は小さいものが多いので大体の人は素手でハンダ付けをするかと思いますが、こういった作業を行う際に便利な道具が｢綿手｣です。


## 🧤効果は絶大🧤
木綿でできた軍手を付けるだけで、ハンダごてをかなり指に近づけても熱くならず、指でパーツを抑えながらハンダ付けを行うことができます。やったことがある人ならわかると思いますが、手袋をつけないと熱くてとてもできません。間違ってこてが指に触れた場合でも何とか我慢できるレベルになります。

綿や麻はこすっても静電気が発生せず電子部品向きの素材で、綿手は柔軟性があり薄くて軽く、道具としても消えてなくなるものでもないためコスパ最高です。100円均一にも保湿用手袋などの名前で売っており、ツールボックスなどに入れておくと強い味方になります。

サイズ選びのコツとしては、手のサイズより小さいものを用意すると綿手袋が伸びて密着するので操作性が下がりずらいです。

**ただ、綿であるため燃えやすいので火気には気をつけてください。ハンダ付けで発火点を超えることはありませんが火があると燃え広がります。また、過剰に信頼していると痛い目をみるので適切に使いましょう。**


## ご安全に
コワーキングスペースでハンダ付けをしているところに遭遇し、電子工作の広がりを感じるとともに、いい感じのTipsが共有されていないことがもったいないなと思いこのエントリを記載しました。
YouTubeでハンダ付けの動画をみてもやっている人は見当たらなかったので、ぜひとも皆さんやってみてください。安全にハンダ付けができる方法が広まることで、男性のみならず女性にも電子工作が広がっていくとうれしいです🧤

Twitterを始めましたので、もし宜しければフォローしてみてください。[@noolbar](https://twitter.com/noolbar)