OmniAICreator/Qiita-1.07M huggingface dataset:
Scrapyでスクレイピング（その1 準備編）

**関連記事**
[その2 事前調査編](https://qiita.com/ezotaka/items/4840a7ca2f70c653a9c8)

Gitリポジトリを作成してから空プロジェクトのコミットを行うまでの手順を簡単にまとめます。

# 開発環境
* Ubuntu 18.04.5 LTS (Bionic Beaver)
* bash
* Python 3.8.1
* PyCharm 2020.3.2 (Professional Edition)

# プロジェクトの準備
1. GitHubでリポジトリを新規作成します。
1. リポジトリをcloneします。
1. Pythonの仮想環境を作ります。
仮想環境名は任意ですが今回はvenvにしました。

    ```
$ cd <リポジトリ(=プロジェクト)のルートディレクトリ>
$ python -m venv venv
```

1. 仮想環境に入って必要なライブラリをインストールします。

    ```
$ . venv/bin/activate
(venv) $ pip install --upgrade pip
(venv) $ pip install scrapy
```

1. 現在のディレクトリをルートにしてScrapyプロジェクトを作成します。

    ```
(venv) $ scrapy startproject <プロジェクト名> . 
(venv) $ tree -L 3
.
├── <プロジェクト名>
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       └── __init__.py
├── scrapy.cfg
└── venv
(略)         
```

1. PyCharmを起動してプロジェクトのルートディレクトリを開きます。
このタイミングでPyCharmの管理用ファイルが.ideaディレクトリ以下に作られます。
（.idea以下のいくつかのファイルをGit管理外にするための設定が正しく行われるかをあとで確認します。
1. ルートディレクトリに.gitignoreファイルを作成してGit管理外ファイルを定義します。
[JetBrains.gitignore](https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore)の末尾に`/venv/`のエントリーを追加します。
(PyCharmの.ignoreプラグインを使用すればマウス操作のみでも設定可能です。)
1. 別の実行環境を構築するときのことも考えてpipのrequirements.txtを作成しておきます。
これで作業はほぼ終わりですので、仮想環境から抜けておきます。

    ```
(venv) $ pip freeze > requirements.txt
(venv) $ deactivate
$
```

1. コミットしてプッシュします。
コミット時に.gitignoreで定義したファイル[^1]が含まれていないことを確認しておきます。

    ```
$ git add .
$ git commit
$ git push
```

#書籍紹介
この書籍が非常にわかりやすく、クローリング・スクレイピングを行うのに必要な知識がひととおり学べます。
[Pythonクローリング&スクレイピング[増補改訂版]](https://www.amazon.co.jp/gp/product/4297107384/ref=as_li_tl?ie=UTF8&camp=247&creative=1211&creativeASIN=4297107384&linkCode=as2&tag=ezotaka-22&linkId=ac36b579de9951ba628a826875d9d424)
![Pythonクローリング&スクレイピング[増補改訂版]](https://ws-fe.amazon-adsystem.com/widgets/q?_encoding=UTF8&MarketPlace=JP&ASIN=4297107384&ServiceVersion=20070822&ID=AsinImage&WS=1&Format=_SL250_&tag=ezotaka-22)

[^1]: 具体的には`.idea/workspace.xml`と`venv`ディレクトリ以下のすべてのファイル
Qiitaのコード編集で、タブ入力出来るようにする

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/457922/e1fbbbff-ab61-c41f-7c6a-ad785cdd6335.png" width=60%>


ブラウザ内ではタブ文字は挿入されず、代わりにコントロールが次のフォーム要素（ボタンやチェックボックスなど）に移動してしまいます。コードの編集でタブは良く使うので不便過ぎます。それを出来るようにします。

Windows限定ですが、AutoHotkeyを利用してTabをコピペする事で結果的にタブ入力をしたのと同じ事にします。


###1. AutoHotkey をインストールします。
[AutoHotkey](https://www.autohotkey.com/)

				


###2. AutoHotKeyスクリプトを作成して、以下を記述します。


Chromeの画面がアクティブになっている時だけ動作するようにしました。
もしChrome以外のブラウザを利用している場合は、以下の部分を目的のブラウザに変えてください。
`#IfWinActive,ahk_exe chrome.exe`

```
;Chrome内で、Tabを入力
#IfWinActive,ahk_exe chrome.exe
tab::
clip:=clipboard
clipboard:= "`t"
clipWait
sendInput,^v
clipWait
Sleep,50
clipboard:=clip
return
#IfWinActive
```


###3. スタートアップフォルダに先程のスクリプトのショートカットを入れて、OS起動時に有効にします。

C:\Users\ユーザー名\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup\

***※もしタブを押してもタブが入力されない場合***
最近のWindows10の更新で、新しいマルチクリップボード機能が原因でコード順が無視されて実行されてしまうようになりました。もしタブではなくクリップボードの内容がペーストされるようなら、Sleep,50の数値をSleep,100とかに上げてください。数値を上げると確実にタブが入力されますが連続でタブを入力する時に少しですがタイムラグが生じます。それぞれの環境に応じて調整してください。
【rails】Gem「bullet」の具体的な効果

<br>今回は、オリジナルアプリを作成する中で、N+1問題を検出する「bullet」というGemを使ってみました。
実際にどうやって使うのか、どんなふうに活用できるのか紹介します。

# 目次
[1.bulletとは？](#1-bulletとは？)
[2.具体的な使い方](#2-具体的な使い方)
[3.参考](#3-参考)


#1. bulletとは？

そもそもbulletというGemはどんなライブラリなのか、公式の説明を抜粋しました。

> The Bullet gem is designed to help you increase your application's performance by reducing the number of queries it makes. It will watch your queries while you develop your application and notify you when you should add eager loading (N+1 queries), when you're using eager loading that isn't necessary and when you should use counter cache.

僕なりの理解ですと、bulletはアプリケーションのパフォーマンスを向上させるように考えており、実行するクエリの回数を減らすことを目的としています。
開発中のアプリケーションのクエリを監視して、不要な読み込みをしている場合に通知します。
（他にも読み込みを追加で必要な場合やカウンターキャッシュを使用する場合も通知するらしいですが、今回はN+1問題をへらすことのみに着目します）

Google翻訳がわかりやすい、、！！


ということでアプリケーションを開発しているときに、無駄なクエリの読み込みしている場合に通知してくれるとか。
めっちゃ便利なので、積極的に使っていきましょう。

#2. 具体的な使い方

まずGemfileに記述します

```ruby:gemfile
   group :development do
     gem 'bullet'
   end
```
このとき、本番環境で通知させないように必ず「group :development do」に入れるのが大事です。

そして、ターミナルで以下を実行します

```
$ bundle install
```
インストールが完了したら、以下のコマンドでbulletが使用できるようになります。


```
$ bundle exec rails g bullet:install
```


これで自動的にN+1問題が発生している箇所を特定し通知してくれるようになりました。
具体的には、N+1問題が発生しているページに遷移するとアラートが表示されます。


![Qiita2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/759659/7c413713-8cf4-fdfb-70f1-a8015ba08b41.png)

これでN+1問題によるサーバーの負荷をへらすことができます！

#3. 参考
下記の記事を参考にさせていただきました。
https://techtechmedia.com/nplusone_query-bullet-rails/
DAPLink を gcc でビルドする

# これは何？

[DAPLink](https://github.com/ARMmbed/DAPLink) を [ARMGCC](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm) でビルド確認した話です。

2020年末頃から gcc 対応の [experimental branch](https://github.com/ARMmbed/DAPLink/tree/experimental_compilers) が作成されました。この branch を windows で ARMGCC + cmake + [ninja](https://ninja-build.org/) で `lpc11u35_if` 向けにビルドできることを確認しました。

# 準備

- [GNU Arm Embedded Toolchain](https://developer.arm.com/tools-and-software/open-source-software/developer-tools/gnu-toolchain/gnu-rm/downloads) のインストール
- [python](https://www.python.org/) のインストール
- [git](https://gitforwindows.org/) のインストール
- [chocolatey](https://chocolatey.org/) を使うと楽なので、まずこれをインストール。

    [install](https://chocolatey.org/install)に書かれているとおり、管理者権限の powershell で次のコマンドを実行します。

    ```powershell
    Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
    ```

- cmake と ninja の install

    管理者権限の powershell か command prompt から次のコマンドを実行します。

    ```batch
    choco install cmake ninja
    ```

# ビルド

[experimental branch](https://github.com/ARMmbed/DAPLink/tree/experimental_compilers) に書かれているとおりです。

git clone した場所で、以下のことを実行します。

1. 仮想環境を作成
2. 仮想環境を起動
3. そこに依存するモジュールをインストール
4. ビルドの実行

```batch
> virtualenv venv
> venv\Scripts\activate.bat
(venv) pip install -r requirements.txt
(venv) progen generate -t cmake_gcc_arm -o generator=ninja -p lpc11u35_if -b
```

`projectfiles\cmake_gcc_arm\lpc11u35_if\build\lpc11u35_if_crc.bin` が生成されるので、それをターゲットボードに焼き込みます。

# 雑談

いままでは、ビルドに商用の ARMCC5 が必要でした。このブランチが安定した後は gcc を default にするようなことが管理者のコメントでありました。より一層ホビー目的に DAPLink が使われていくでしょう。
anyenvとnodenvを使ったNode.jsの環境構築


本記事では、`anyenv`と`nodenv`を使って**Mac**にNode環境を構築する。

## nodenvとは

プロジェクト(ディレクトリ)ごとに、Node.jsのバージョンを管理することができる**バージョン管理ツール**のこと。

### なぜnodenvを使用するのか？
仮に、`nodenv`を使用せずに、あるプロジェクトAのためにNodeの**v7系を固定**でインストールすると、別のプロジェクトBにおいて**v8系**を使用する必要があった際にはNodeのアップデートが必要となってしまう。

`nodenv`を使用したバージョン管理をしていると、上記のようなプロジェクトごとに異なるバージョンを使用する際の手間をなくすことができる。

---
今回は`noodenv`を包括する`anyenv`を使ってNodeのバージョン管理を行える環境を構築していく。`nodenv`の他にもRubyやPythonのバージョン管理を行う〇〇envも存在し、`anyenv`はこれらのバージョン管理ツールを包括的に管理するツールである。

## anyenvのインストール
以下のコマンドを実行し`anyenv`をインストールする

```zsh
% brew install anyenv
```

nodenvをインストールする前に`anyenvの初期化`が必要なため初期化を行う。

```zsh
% anyenv install --init

... Do you want to checkout ? [y/N]: y <- yと答える

remote: Total 62 (delta 1), reused 1 (delta 0), pack-reused 57
Unpacking objects: 100% (62/62), done.

Completed!
```

`anyenv`のインストールに成功したので、次に`nodenv`のインストールを行う。

## nodenvのインストール
以下のコマンドを実行し`nodenv`をインストールする

```zsh
% anyenv install nodenv

...
Resolving deltas: 100% (76/76), done.
~

Install nodenv succeeded!
Please reload your profile (exec $SHELL -l) or open a new session.
```

プロファイルの更新のため、以下のコマンドも続けて実行する。

```zsh
% exec $SHELL -l
```

インストール可能なバージョンを以下コマンドの実行結果から確認することができればインストールに成功。

```bash
% nodenv install -l
0.1.14
0.1.15
...
...
```
---
※ `nodenv`コマンドの実行に失敗した時の対処方

.zshrc ファイルが未作成のため、`nodenv`のパスが設定されていなく失敗する場合は、以下の対処を行うことを勧める

- `vi ~/.zshrc`を実行
- `eval "$(anyenv init -)"`を書き込み保存する
- 再度、`anyenv install nodenv`を実行する

---

## Node.jsのインストール

以下のコマンドを実行しNode.jsをインストールする。今回は`12.20.0`をインストールする。

```bash
% nodenv install 12.20.0
```

インストール済みのバージョンは以下のコマンドから確認できる。`12.20.0`が表示されれば無事に`Node.js`のインストールに成功している。

```bash
% nodenv whence npm
12.20.0
```

### グローバルのNode.jsのバージョンを指定
以下のコマンドで、インストール済の`12.20.0`をグローバルなバージョンとして指定する。

```bash
% nodenv global 12.20.0
```

### 動作確認
`node`コマンドを実行し、`12.20.0`が表示されれば無事にNode環境の構築ができている。

```bash
% node -v
v12.20.0
```

### ディレクト毎にバージョンを切り替えたい場合
今回は`12.20.0`のNodeバージョンを使用できるようにしたが、特定のディレクトリでは`8.0.0`を使用したくなったときの手順を最後に紹介する。


-  Node.js`8.0.0`をインストール

```bash
% nodenv install 8.0.0
```

-  `8.0.0`を使用したディレクトに移動する。(今回は`node-8`)

```bash
% cd node-8
```

- localオプションで`8.0.0`を指定

```bash
% nodenv local 8.0.0
```

- 対象ディレクトリ配下で`node -v`を実行し`8.0.0`が表示されれば成功

```
% node -v
8.0.0
```

> `nodenv local 8.0.0`実行時には、指定したバージョンが記載された`.node-version`ファイルが生成される。このファイルに指定された値を変更することで使用するバージョンも変更することができる。


## 参考記事

https://qiita.com/kyosuke5_20/items/eece817eb283fc9d214f

https://www.to-r.net/media/anyenv/
react-hook-formで確認用パスワードの入力チェックを実装してみる

## 概要
Formである項目を入力した時に、別の項目の入力内容と比較してチェックをしたい時があると思います。例えば[こちら](https://www.atmarkit.co.jp/ait/articles/1104/25/news137_3.html)で紹介されているような、確認用パスワードの入力です。
今回はreact-hook-formでこの確認用パスワードの入力チェックを実装してみたので、どのようになったのかというのを紹介してみます。

## 実装方針
・親コンポーネント、パスワードの入力用コンポーネント、確認用パスワードの入力用コンポーネントの3つでコンポーネント分けします。
・入力された値は親コンポーネントのformStateで管理します。formStateからは[getValues](https://react-hook-form.com/jp/api#getValues)を使用して、入力した値を取得します。
・確認用パスワードの入力欄では、getValuesで取得したパスワードの値と[こちら](https://www.carlrippon.com/custom-validation-rules-in-react-hook-form/)の記事で紹介されているvalidateメソッドを使って比較します。

## 実装
**【親コンポーネント】**

```javascript:ParentComponent.js
export default function ParentComponent() {
  const { register, handleSubmit, errors, formState, getValues } = useForm({
    mode: "onChange",
  });

  function onSubmit(data) {
    // submit処理は割愛・・
  }

  return (
    <div>
      <Form onSubmit={handleSubmit(onSubmit)}>
        <PasswordInputComponent register={register} errors={errors} />
        <br />
        <PasswordReInputComponent
          register={register}
          errors={errors}
          password={getValues("password")}
        />
        <br />
        <Button variant={"primary"} type="submit" disabled={!formState.isValid}>
          送信
        </Button>
      </Form>
    </div>
  );
}

```

**【パスワードの入力用コンポーネント】**

```javascript:PasswordInputComponent.js
export default function PasswordInputComponent(prop) {
  return (
    <>
      <Form.Label>パスワード</Form.Label>
      <Form.Control
        id="password"
        type="password"
        name="password"
        placeholder="パスワード"
        isInvalid={prop.errors.password}
        style={{ width: "300px" }}
        ref={prop.register({
          required: "パスワードは必須項目です",
          minLength: {
            value: 6,
            message: "パスワードは6文字以上で入力してください",
          },
        })}
      />
      {prop.errors.password && (
        <Form.Control.Feedback type="invalid">
          {prop.errors.password.message}
        </Form.Control.Feedback>
      )}
    </>
  );
}

```

**【確認用パスワードの入力用コンポーネント】**

```javascript:PasswordReInputComponent.js
export default function PasswordInputComponent(prop) {
  return (
    <>
      <Form.Label>パスワード（確認用）</Form.Label>
      <Form.Control
        id="passwordReInput"
        type="password"
        name="passwordReInput"
        placeholder="パスワード"
        isInvalid={prop.errors.passwordReInput}
        style={{ width: "300px" }}
        ref={prop.register({
          validate: (input) => input === prop.password,
        })}
      />
      {prop.errors.passwordReInput && (
        <Form.Control.Feedback type="invalid">
          <span>入力したパスワードと一致していません</span>
        </Form.Control.Feedback>
      )}
    </>
  );
}
```
DS-CO2-20とRaspberryPIで二酸化炭素測定

#### 二酸化炭素を測りたい

　例のウィルスのせいで自宅にこもりっぱなしとなっていますが、CO2が多いとどうにも眠い気がします。

　隔離施設(ホテルや病棟)では1,000ppm以下になるよう換気しているそうです。
　できれば1,500ppmくらいになったらでアラートを出して欲しい。

　Qiitaにもいくつか同様の先輩方から似たような記事が投稿されていますが、どうにもドリフトが多すぎてアラートとして使うには誤差が大きすぎます。

　ずぼらで放置しっぱなしの仕組みが欲しいなと思い、この記事を書きました

---
#### 理想のセンサーを求めて

　二酸化炭素を測定するセンサーは個人でもいくつか手に入ります
　以下は個人的に譲れない条件を羅列してみました

- I2C対応している事
	同じ線に温度計とか湿度計もぶらさげて配線少なくしたい
	UARTだとノイズにも弱い

- 2波長NDIRな事
	普通のNDIRだと毎週部屋を2時間程度窓全開にしないといけません
	この時期寒すぎる

- 1個単位で手に入る事
	日本のセンサーだとロット単位で買わないと相手にすらしてもらえません

- ラズパイに繋ぐので消費電力はあまり考えないでいいが少ないに越した事はない



#### DS-CO2-20 が良さそう

　という事でAliExpressからDS-CO2-20というセンサーを購入してみました
　[データシートはこちら](https://www.icbanq.com/icdownload/data/ICBShop/Board/DS-CO2-20%20series%20data%20manual_English_V2.9.pdf)

　このセンサーはいくつかバージョンがあるようで、v2.9はI2Cが使えるようです
　センサー自体にはどこにもバージョンは書いておらず、ファームのアップデートもできなさそうです
　最新版は2019年ごろアップデートされているのでまず大丈夫でしょう
　この記事を書いている頃にディスコンになってDC-CO2-21なるものが出たようですが、市場には十分なストックはあるようです

#### 配線

さてデータシートの通りにラズパイに配線します

|センサー端子|機能名|ラズパイのPIN|備考|
|---|---|----|----|----|
|1|VCC|4|(5V)|
|2|GND|6|(GND)|
|3|SDA |  3  | (GPIO2) SDA|
|4|SCL |  5   |(GPIO5) SCL|
|5|RESET|  開放(リセット用に使うかも)|
|6|I2Cmode=L  |  9 |   (GND)|
|7|PWM  |  開放(使わない)||


　間欠的に200mAも流れますので、突入電流対策の為にセンサーの5V電源の近くには100〜470μF程度のコンデンサーを入れたほうがよさそうです。


#### あっさり動作

![スクリーンショット 2021-01-25 21.27.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/76552/a7830682-0ebf-2adf-8f77-d9685893453e.png)


　校正も何もせずあっさり動作しました
　窓を開けると430ppmという値です

　ラズパイのI2Cの設定などは[こちら](https://nasuplant.blogspot.com/2021/01/diy_24.html)もご覧ください
全国市区町村界データを Tippecanoe で Mapbox Vector tile に変換して、ArcGIS API for JavaScript で表示


Mapbox 社がオープンソースとして提供しているツール ”Tippecanoe” (発音は ”ティピカヌー”) を使用して、全国市区町村界データのシェープファイルを MVT 化して、Esri 社の ArcGIS API for JavaScript で表示してみましたので、その手順について紹介したいと思います。

今回以下のステップでそれぞれ構築しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/102251/dadb7258-0051-747c-5d40-53aa307a0744.png)
Tippecanoe を使用して、mapbox vector tile に変換する場合に、シェープファイルを GeoJSON に変換する必要があります。そして、変換した GeoJSON を使用して、ベクタータイルを作成します。

ArcGIS API for JavaScript で作成したアプリは以下で確認することができます。
https://valuecreation.github.io/arcgis-js-api-samples/20210127/index.html

本記事の詳細は以下のブログで公開しています。
https://freedom-tech.hatenablog.com/entry/2021/01/28/001931
独自ドメインのメールをPCのGmailで確認・送信する方法

先日xserverでドメインを取得して、メールアドレスも作成しました。
そのメールをpcのgmailから見ようとしたのですが、設定に躓いたのでメモを残します。
（手間かけて作る時間がなかったので超絶メモで残します。）

スマホからだとすんなりと、アカウントも作成せずに設定できたのですが、pcのgmailから自分のメールを確認するには、設定が必要です。

A．Google アカウントを作成する。
B．GSuite に登録する。（初月は無料。以後、月額でお金がかかる。）

Gsuiteにお金を払ってもよかったですが、すでに別アカウント（別ドメイン）でGSuite1は購入していたので、今回は「A．Google アカウントを作成する。」でやりました。

#手順
１．Google アカウントを作成する。
２．[Gmail](https://mail.google.com/mail/u/2/?pli=1#inbox) を開く
３．設定 > すべての設定を表示する
４．アカウントとインポート（もしくは、アカウント）
５．Check mail from other accounts: の設定を行う。
　　ユーザー名：（XSERVERで設定した内容）
　　パスワード：（XSERVERで設定した内容）
　　POPサーバー：svXXXXX.server.jp
　　ポート：995
　　☑ SSLを使用するにチェックを入れる
　　→「アカウントを追加」ボタンクリック
６．Send mail as: の設定を行う。
　　入力はほぼ、５．と一緒。
　　※ポートは465にする。
　　→設定が終わるとメールが飛んでくる。
　　　確認コードを画面に入力する。
以上！
Mapbox GL JS v2 を使用して Esri の地形図を表示

昨年にリリースされた Mapbox の Mapbox GL JS v2 についてようやく触ることができましたので、簡単ではありますが紹介したいと思います。

Mapbox GL JS はウェブブラウザでベクトル地図を表示するための JavaScript ライブラリで、v2 によるバージョンアップによってレンダリングがより高速になっています。また、新規機能として、空の色をコントロールできる Sky API やCamera API の機能強化によりさまざまな視点から 3Dマップを見ることができたりなど機能が追加されています。その他、リアルな 3Dマップが作成可能になったりしています。

詳細は以下のブログで公開しています。
https://freedom-tech.hatenablog.com/entry/2021/01/17/215348
Webアプリ開発に必要なドキュメント10選【備忘録】

<br/>
この記事は[こちら](https://tekuzo.org/2021/06/16/web%e3%82%a2%e3%83%97%e3%83%aa%e9%96%8b%e7%99%ba%e3%81%ab%e5%bf%85%e8%a6%81%e3%81%aa%e3%83%89%e3%82%ad%e3%83%a5%e3%83%a1%e3%83%b3%e3%83%8810%e9%81%b8%e3%80%90%e5%82%99%e5%bf%98%e9%8c%b2%e3%80%91/)へ移動しました。
<br/>
<br/>
Mapbox、deck.gl、ArcGIS、Cesium について


本エントリーは [FOSS4G Advent Calendar 2020 21日目](https://qiita.com/advent-calendar/2020/foss4g)のエントリーです。

本ブログでは、これまで Mapbox GL JS や deck.gl、Cesium.js、ArcGIS API for JavaScript について幾つか紹介してきました。 紹介してきたのは、いずれも JavaScript のクライアントライブラリーでリリース頻度も高く、高機能な機能を提供しています。対応しているプラットフォームも異なるので、できることや得意な領域などは異なりますが、同じような方向性に向かっているような気もしています。今回はこれまでの振り返りとして個人的な見解を述べたいと思います。

記事の内容は以下に公開しています。
https://freedom-tech.hatenablog.com/entry/2020/12/24/203615
【初心者】RubyとPHPの基本的な書き方を比較してみた

# この記事は…
プログラミング初心者学習向きのスクリプト言語として人気のある**Ruby**と**PHP**。
Ruby基礎の復習も兼ねて、PHPではどのように書くか比較したアウトプットです。

# ファイルの拡張子
Rubyのファイルは「.rb」。PHPのファイルは「.php」

# 記述方法
Rubyには「拝啓〜敬具」みたいなプログラムの書き出しと締めの言葉はないけれど、PHPでは開始と終了に<?php 〜 ?>とタグを記述する必要があります。

```php:hoge.php
<?php
  // ここ（タグの間）にプログラムを書く
?>
```

コメントアウトはRubyの場合は#を付与。

```ruby:hoge.rb
# Rubyの1行コメントアウト 

=begin
  Rubyの
  複数行コメントアウト
  ですよ
=end
```

PHPでは1行コメントアウトの場合//(ダブルスラッシュ2個)、複数行は/* 〜 */のようにコメントアウトします。

```php:hoge.php
<?php
  // 1行コメントアウト

  /* PHPの
     複数行コメントアウト
     ですよ
  */
?>
```

PHPはHTMLの中に埋め込むことができます。
たとえば以下のように強調の\<b>タグを記述してブラウザ（HTML出力）すると、Hello worldを太文字で出力することができます。

```php:helloworld.php
<b>
<?php
  echo "Hello world";
?>
</b>
```

そうそう、Rubyでは語尾に何もつかないけれど、PHPでは**;(セミコロン)**が無いとエラーになっちゃう。
語尾に;が必要なのは、CSSに似てる親近感。

# 変数
PHPでは変数名の頭に$(ドルマーク)をつけると変数名になります。
Rubyでは標準出力は**putsコマンド**で行います。

```ruby:hoge.rb
hoge1 = "Hello"
hoge2 = "World!"

puts hoge1 + hoge2         # HelloWorld! 
puts "#{hoge1} #{hoge2}"   # Hello World! 
```

PHPでは**echo**で出力できます。
PHPで文字列を繋げる場合は、変数の前後に**.(ドット)**を記述。
変数に代入する場合はRubyと同様に**=(イコール)**で代入。

```php:hoge.php
<?php
  $hoge1 = "Hello";
  $hoge2 = "World!";

  echo $hoge1.$hoge2;      // HelloWorld! 
  echo $hoge1." ".$hoge2;  // Hello World! 
?>
```

標準入力はRubyでは**gets**で値を取得し、**chomp**で改行コードを削除。


```ruby:hoge.rb
  hoge = gets.chomp
```

PHPでは**fgets(STDIN)**で値を取得。
改行を削って変数に代入したい場合、PHPでは**trim**を使います。

```php:hoge.php
<?php
  $hoge = trim(fgets(STDIN));
?>
```

# 条件式(if文)

条件分岐のif文、Rubyで書くとこんな感じ。

```ruby:hoge.rb
# 1〜3までランダムな数を選び、変数hogeに代入
# ランダム数値の生成はrandを使用。数の範囲は(From..To)のように表現
hoge = rand(1..3)

# 1ならコンニチワ、2ならサヨナラ、3ならマタネ
if hoge == 1
	puts "Hello"
elsif hoge == 2
	puts "Bye"
else
	puts "See you again"
end
```

同じ内容をPHPで書くとこんな感じ。
条件文は**(カッコ)**で囲みます。
ほか**{カギカッコ}**や**;(セミコロン)**を書き忘れそうになります(苦笑)
何回か条件を書く時、Rubyでは**elsif**、PHPではしっかり**e**もつけて**elseif**と書きます。

```php:hoge.php
<?php
  // 1〜3までランダムな数を選び、変数hogeに代入
  // ランダム数値の生成はrandを使用。数の範囲は(From,To)のように表現
  $hoge = rand(1,3);

  // 1ならコンニチワ、2ならサヨナラ、3ならマタネ
  if($hoge == 1){
    echo "Hello";
  }elseif($hoge == 2){
    echo "Bye";
  }else{
    echo "See you again";
  }
?>
```

# まとめ
異なる言語だから当然異なる部分はあるけれど、RubyとPHPの基本的な構文は似ている書き方もあることを知りました。

同時に学ぶことで頭の中で書き方が混ざっちゃう可能性には注意しつつ、Rubyの復習・振り返りも兼ねて、PHPも学習していこうと思います。

PHPの基礎もやったら、Ruby on Railsの復習兼ねてPHPの主要フレームワークであるLaravelの学習も進めたいです。
Javaの時分(hhmm)をバリデーションする方法

# 経緯
Javaの日付フォーマットの確認方法はぐぐるといくつか出てくるのだが、「1900」や「11:00」など時分形式のバリデーションはいろいろ調べてもあまり出てこなかった。
ちなみに日付のフォーマット確認はSimpleDateFormatなどを利用すればできる。
https://www.sejuku.net/blog/20994

正規表現で調べる方法はいくつか見つかったが、できれば同じようにフォーマッターなどを使用して確認をしたい。
https://www.saka-en.com/java/java-time-check/

# 方法
DateTimeFormatterを使ってExceptionに入るかどうかで判定すれば時分(hhmm)形式でもできそうだった。
以下のような形で実装する。

```java
import java.time.format.DateTimeParseException;
import java.time.format.DateTimeFormatter;
import java.time.LocalTime;

public boolean checkDateTimeFormat(final String format, final String value) {
  try {
    LocalTime.parse(value, DateTimeFormatter.ofPattern(format));
  } catch (DateTimeParseException e) {
    return false;
  }
  return true;
}
checkDateTimeFormat("HHmm", "1900");
```

誤りなどあればご指摘もらえますと幸いです。
双方向通信と単方向通信の違いをまとめてみた

TCP/UDPで双方向通信と単方向通信ができることを最近知った。

ちなみに私のTCPとUDPに対する認識は以下の通りである。

+ TCP・・・トランスポート層のプロトコル。リアルタイム性がないかわりに証明書が発行されてるのでセキュリティは担保されている。
+ UDP・・・こちらもトランスポート層のプロトコル。証明書が発行されてないのでセキュリティはちょっと怪しいけどリアルタイム性があるのでTCPよりも早く通信できる。

で。
「双方向通信は、クライアントから要求を送り、それに対してサーバが帰ってきたら成り立つ。単方向通信はただただ要求投げっぱなしのやつじゃないの？」と思っていたがどうも違うらしい。

双方向通信とは、クライアントが要求を送った__ポート__にサーバが応答を返すものであり、要求を送ってきたポートと違うポートに応答を返せばそれはもう双方向通信じゃないのだ。

---------------------------------------
超短いけど備忘録として書いておきました。

読んで頂いた方、ありがとうございます。
ではまた次の記事で。
Railsのアセットパイプライン完全に理解した

Railsのアセットパイプラインとやらは長年私を苦しめてきました。なぜアセットをpublicに置かずにapp/assetsなどというディレクトリに置かなければならないのか。webpackじゃだめなんですか？(webpackerについてはよく知りません)
私がいかに完全に理解したかをできるだけシンプルに共有したいと思います。

* アセットとは次のものである
    * 画像ファイル(gif, jpg, png)
    * スクリプトファイル(js, coffee, es6)
    * スタイルシート(css, scss, sass)
* アセットは次のディレクトリ以下に置く。サブフォルダを作って入れてもよい
    * app/assets/*/
    * vendor/assets/*/
* **実際に利用するためには、適当なアセットファイルに利用したいファイルをリンクするディレクティブを書く必要がある！**

言いたかったのは最後のやつだけです。このルールに気づくのにだいぶ時間がかかった。

```
//= link foo.js
//= link_directory ../stylesheets .css
//= link_tree ../images
```

こういう指定をアセットとして読み込ませたい単位で適当なアセットファイルに記述します。マニフェストファイルと呼ばれたりしますが、あくまでアセットファイルの一つにすぎません。上から、

* どこかのアセットディレクトリにあるfoo.jsまたはfoo.jsになりうるファイル
* マニフェストファイルからの相対パス指定によるディレクトリ以下のcssファイルすべて
* マニフェストファイルからの相対パス指定によるディレクトリ以下のアセットファイルすべて(サブディレクトリ以下も再帰的に含む)

という指定になります。
マニュアルをみると、読み込みたいファイルをいちいちRails.application.config.assets.pathsに追加しなければいけないように見えますし、実際そのようにしてきましたが、この仕組みを理解していればその必要がないことがわかると思います。泣く泣くapplication.jsやapplication.cssにすべてを記述していた人も多いのではないのでしょうか。
他にも依存関係指定やトランスパイルなど便利な機能が揃っていますが、このことを知らないと話にならない。

今はwebpackerとやらが主流なんでしょうが、まだ触れる機会はあると思います。
Railsで複数カラム追加のalter文を1つにまとめる

- `bulk: true` をつければOK
- 以下は https://github.com/rubocop-hq/rubocop/pull/5881 の内容です

```rb
    change_table :users, bulk: true do |t|
      t.string :name, null: false
      t.string :nickname
    end
```

実行されるSQL

```sql
 ALTER TABLE `users` ADD `name` varchar(255) NOT NULL, ADD `nickname` varchar(255)
```


- RuboCop Rails
を導入していれば指摘してくれるようです
 - https://docs.rubocop.org/rubocop-rails/cops_rails.html#railsbulkchangetable
Homebrewをインストールする

本記事では、Macに`Homebrew`をインストールする。

## Homebrewとは
Homebrewは、Appleが提供していないものをインストールすることができるパッケージマネージャー。

## Homebrewのインストール

Homebrewの[公式サイト](https://brew.sh/index_ja.html)に記載されているコマンドをコピーしてターミナルから実行する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/397734/f8f73a4d-c1d0-48f8-0b43-898f291c3c59.png)

以下のコマンドをターミナルから実行

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

完了すると以下のようなメッセージが表示される。

```bash
...
... 
==> Homebrew is run entirely by unpaid volunteers. Please consider donating:
  https://github.com/Homebrew/brew#donations

==> Next steps:
- Run `brew help` to get started
- Further documentation: 
    https://docs.brew.sh
```

## 動作確認
今回はバージョンをbrewコマンドで確認しインストールに成功しているか確認する。

```zsh
% brew -v
Homebrew 2.7.6
Homebrew/homebrew-core (git revision 5830b8; last commit 2021-01-27)
```

バージョンが表示されれば無事にインストールに成功している。
Googleカレンダーの予定を作成する（GoogleAppsScript）

#Calendar.createEvent

```gcal.ts
function createEvent() {

  const title = 'タイトル';
  //予定時間の設定
  //実行日12:00から
  let startTime = new Date();
  startTime.setHours(12); 
  startTime.setMinutes(0);
  //実行日13:00まで
  let endTime = new Date();
  endTime.setHours(13); 
  endTime.setMinutes(0);
  //オプションを追加
  const options = {
  //   description:'説明', 
  //   location:'場所',       
  //   guests:'guests@gmail.com', //ゲスト
  //   sendInvites:true           //招待メールの送信
  }

  //デフォルトカレンダーに予定を作成
  const calendar = CalendarApp.getDefaultCalendar();
  // //IDでカレンダーを指定する場合
  // var calendar = CalendarApp.getCalendarById('{{id}}@group.calendar.google.com');
  const event = calendar.createEvent(title, startTime, endTime, options);
  Logger.log('createEvent: ' + event.getTitle());  //createEvent: title

}
```

繰り返し予定の作成では，明日以降にも予定が表示されてしまうので，
時間主導型トリガーを毎日0時に設定し，当日のみ表示しています。

#Reference
[https://developers.google.com/apps-script/reference/calendar/calendar](https://developers.google.com/apps-script/reference/calendar/calendar#createeventtitle,-starttime,-endtime,-options)
エンジニアになって１年経ったので感想を書いてみる

javaエンジニアになって１年経ちました。
[→未経験からＩＴ企業に就職した勉強メモ](https://qiita.com/nekomaru991/items/1d6d7e8ca801cd5e5d36)


＜大変だったこと＞
・何が質問したいのかわからない
・何がわからないのかわからない
・エラーの切り分け



わかないことを質問するわけですが、質問の仕方がざっくりだと
「なにが言いたいのか分からない」といわれ解決しないので、できるだけ具体的にかつ
忙しいリーダーにスッと答えてもらえるような文面を考える力がつきました。
（まだまだですが、初期と比べるとだいぶまし）

例）
✕　→　○○がうまく動きません。どうすれば良いでしょうか？
○　→　○○の動きが以下の様になっています。
　　　〜〜〜〜〜〜（事象のログとか）
　　　△△ファイルの配備がうまくいってないと思いますがいかがでしょうか。


＜粘り強くなった＞
参画したときはわからないことだらけで、先輩に頼りまくっていました。
ちょっとしたことでも調べず、質問しまくっていました。
ただ、このときに質問していた先輩があまり親切な人ではなかったため
（伝えるのが苦手または人に教えるほどはわかってない人だった可能性有）
あまり知識が身についた感覚はありませんでした。
現場ガチャ・先輩ガチャ、あると思います。

途中で先輩がいなくなったので自分ひとりでやらなきゃという場面が増えて
だんだんと検索力が身につきました。

すぐ質問するのも悔しい気がして期限ギリギリまで粘ってみたりします。
ただしプロジェクトに支障が出るほどは持ち越さない方がいいに決まってるので
上記の期限は自分の中での期限です。
頑張ってもわからないときは上に投げるのも仕方ないかなと。
ただ何が間違っていたのかはできるだけ理解できるようにがんばります。

＜素敵な人としか付き合わない＞
分からない・知らないことを聞いたときに馬鹿にしたり見下したりせず、教えてくれる人と付き合う。

この世のすべての知識を得ることは誰にも不可能ですよね、
「知っている人」というのは「知らない人」と比べて
ただ単に「先にその知識を習得した人」に過ぎないと自分は思っています。

「素敵な人」はそのことをわかっているので、勿体ぶらず、優しく教えてくれます。

※「そんなことも知らないの？」っていう態度で小馬鹿にしてくる人は大成しないと思います。
（そもそも人望がないから成功しなそう）

「素敵な人」とだけ交流するようにして、知識をどんどん習得するようにしています。
※人間は、｢知っていることは教えたくなる生き物｣だと勝手に思っています。よくわかってないひとは聞いても教えてくれません。


＜未経験からエンジニアになってよかった＞
ベテラン様からしたらほんとにまだまだペーペーで、こんな記事書くのもどうかと思いましたが一応記録として。
エンジニアの端くれになれて楽しい毎日を送っています。

「素敵な人」に色々教えていただくのもうれしいです。

一番楽しいのは作業の効率化を考えているときです
（実際に作業をするときは死んだ顔してやっています）

日頃から、いかに楽をするかを考える自分にはロジカルシンキングの世界は合っていたのかなと感じています。

今後も頑張ろう。
【Windows10】IME入力モード切替の通知を消す

下記のように、画面の中央に「あ」や「A」が表示される
　・[半角/全角]キーを押下したとき
　・[Alt] + [Tab] で画面を切り替えたとき

　![あ.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864611/97a08605-c5e4-c459-c064-5ab83c30ea9b.png)
この表示について、設定方法（表示する or 表示しない）を紹介する。

##設定方法
　①IMEアイコンを右クリック
![1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864611/de29712c-6382-1a48-2c0a-74fa7cd42679.png)
　②[プロパティ]をクリック
![2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864611/7d43c150-16c2-168b-8c43-ebdc630303b4.png)
　③Microsoft IMEの設定が表示され、「IME入力モード切替の通知」の「画面中央に表示する」のチェックボックス
　　・チェックを入れる　→　表示される
　　・チェックを外す　　→　表示されない

　④「OK」ボタンを押下
![無題.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/864611/040dec41-3f2f-6ada-db44-7790531d1405.png)

##まとめ
　備忘録としてメモを投稿
paiza スキルチェック 見本問題 go言語 Sランク  島探し

paizaの見本問題 go言語 Sランク 島探し
go言語の解答例などは存在していないので、上げることにしました。
また、見本問題は解説や公開してもいいとのことで公開させていただいてます。
単純な問題だったので、特にコメントアウトで細かい補足はしていません。

実装方針としては

メイン関数で2次元のスライスを宣言、関数外からでも値を自由に操作できるように、ポインタ変数にしています。
不随するデータの方はcontent int, fl intでcontentは中身を保持用で値が参照されたかどうかと、countの数を入れるデータを入れています。

関数conでは、関数cを回すための土台を作っています。

contentが1かつまだ未参照の値(flが0)を見つけたときに関数cを実行します。
関数cは再帰関数かつ、ツリー状に関数を実行していきます。例えば

010
111

という値を見たとき、土台の関数conでは左上から右へそして下へ移動するようになっているので、まず初めに関数cが実行されるのは[0][1]となっています。

関数cでは上下左右を確認し、もし1があれがそちらに移動して再度関数cを実行するようなプログラムになっています。



```
package main
import "fmt"
type Data struct{
    content int
    fl int
}
var count = 0

func con(data *[][]Data, n int, m int) {
    var pos =[2]int{n, m}
    for i := 0; i < n ; i++{
        for j := 0; j < m; j++{
            if (*data)[i][j].content == 1 &&(*data)[i][j].fl == 0{
                count++
                c(data, pos,i,j)
               // print((*data)[i][j].fl)
                if (*data)[i][j].fl != 0{
                    continue
                }

             }
            //int((*data)[i][j].fl)
            //print(" ")
        }
       // print("\n")
    }
    fmt.Print(count)
}


func c(data *[][]Data, pos [2]int,cur_x,cur_y int) {
    /*
    print(cur_x + 1, cur_y + 1)
    print("     ")
    print((*data)[cur_x][cur_y].fl)
    print("     ")
    print(count)
    print("\n")
    */
     if (*data)[cur_x][cur_y].content == 1{
         (*data)[cur_x][cur_y].fl = count

         //flag into := {0, 0, 0}
            if (cur_x + 1) != pos[0] && (*data)[cur_x + 1][cur_y].fl == 0 && (*data)[cur_x + 1][cur_y].content == 1{
          //    if((*data)[cur_x + 1][cur_y].content == 1){
                 c(data, pos, cur_x + 1, cur_y)
                 //flag.l = 1
          //    }
            }
             if (cur_x - 1) != -1 && (*data)[cur_x - 1][cur_y].fl == 0 && (*data)[cur_x - 1][cur_y].content == 1{
          //    if((*data)[cur_x + 1][cur_y].content == 1){
                 c(data, pos, cur_x - 1, cur_y)
                 //flag.l = 1
          //    }
            }
        //    }
            if (cur_y + 1) != pos[1] && (*data)[cur_x][cur_y + 1].content == 1 && (*data)[cur_x][cur_y + 1].fl == 0{
                //if (*data)[cur_x][cur_y + 1].content == 1{
                    c(data, pos, cur_x, cur_y+ 1)
               // }
            }
            if (cur_y - 1) != -1 && (*data)[cur_x][cur_y - 1].content == 1 && (*data)[cur_x][cur_y - 1].fl == 0{
                //if (*data)[cur_x][cur_y + 1].content == 1{
                    c(data, pos, cur_x, cur_y - 1)
               // }
            }
    }
}

func main(){
    var m, n int
    fmt.Scanf("%d %d\n", &m, &n)
    var dum int
    var a = make([][]Data, n)//2次元配列aの仮宣言
    for i := 0; i < n ; i++ {
        for j:=0; j < m; j++{
                fmt.Scanf("%d", &dum)
                        ap := Data{content:dum, el:false, fl:0}
            a[i] = append(a[i], ap)
        }
    }
    con(&a, n, m)
}
    //fmt.Print(con(a, n, m))


```
ルーティングのネストについて

#目次
<b>①ネストをする意味
<b>②ネストの記述方法
<b>③ネストしない場合とする場合
<b>④まとめ

##①ネストをする意味
アソシエーション先のid情報を取得するためにネストをする。

##②ネストの記述方法
以下のように親のコントローラに対してdoとendで挟んで記述をすると、ネストがされている状態になる。

```
Rails.application.routes.draw do
  resources :親となるコントローラー do
    resources :子となるコントローラー          
  end
end
```


##③ネストしない場合とする場合

```php:ネストなし
Rails.application.routes.draw do
  resources :images
  resources :comments, only: :create
end

```


```php:ターミナル
Prefix   Verb    URI Pattern           Controller#Action
comments POST   /comments(.:format)   comments#create
```
ネストなしの場合、ターミナルにてrails routesをすると上記のように表示される。ではネストがある場合どうなるのだろうか？


```php:ネストあり
Rails.application.routes.draw do
  resources :images do
    resources :comments, only: :create
  end
end
```

```php:ターミナル
Prefix         Verb    URI Pattern                            Controller#Action
image_comments POST   /images/:tweet_id/comments(.:format)   comments#create
```

ネストありの場合、ターミナルにてrails routesをすると上記のように表示される。ネストした場合は、コメントの投稿先のidがあるのに対して、ネストしない場合は、どの画像に対してコメントかわからなくなってしまう。

##まとめ
ネストをすることで親のidの情報を取得することができる。
きっとgit使えないとbad④

#はじめに
git使っていて「コマンドなんだっけ？」ってなったら、
結局これ。

##help

```bash
% git --help
usage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
           [--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
           [-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
           [--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
           <command> [<args>]

These are common Git commands used in various situations:

start a working area (see also: git help tutorial)
   clone     Clone a repository into a new directory
   init      Create an empty Git repository or reinitialize an existing one

work on the current change (see also: git help everyday)
   add       Add file contents to the index
   mv        Move or rename a file, a directory, or a symlink
   restore   Restore working tree files
   rm        Remove files from the working tree and from the index

examine the history and state (see also: git help revisions)
   bisect    Use binary search to find the commit that introduced a bug
   diff      Show changes between commits, commit and working tree, etc
   grep      Print lines matching a pattern
   log       Show commit logs
   show      Show various types of objects
   status    Show the working tree status

grow, mark and tweak your common history
   branch    List, create, or delete branches
   commit    Record changes to the repository
   merge     Join two or more development histories together
   rebase    Reapply commits on top of another base tip
   reset     Reset current HEAD to the specified state
   switch    Switch branches
   tag       Create, list, delete or verify a tag object signed with GPG

collaborate (see also: git help workflows)
   fetch     Download objects and refs from another repository
   pull      Fetch from and integrate with another repository or a local branch
   push      Update remote refs along with associated objects

'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.

```
や

```bash
% git add --help
```
など
##最後に
ただ、説明が全て英語なので、その解読に時間が掛かってしょうがない…
【環境構築】Docker　rails　備忘録

Docker使ってrailsでアプリを作成した際の備忘録

#手順１
ファイル作成
既にDockerをインストールしているので
使用しているディレクトリの配下に任意の名前でディレクトリを作成し
以下作成したディレクトリにファイル準備。
・Gemfile
・Gemfile.lock
・Dockerfile
・docker-compose.yml
※ターミナルでのファイル作成コマンド：touch XXXXXX(※XXXに作成するファイル名)

#手順2
作成したファイルの内容を編集

```ruby:Gemfile
source 'https://rubygems.org'
gem 'rails', 5.2.2
```

```ruby:Dockerfile
FROM ruby:2.5
RUN apt-get update -qq && apt-get install -y build-essential libpq-dev nodejs
RUN mkdir /sample
WORKDIR /sample

COPY Gemfile /sample/Gemfile
COPY Gemfile.lock /sample/Gemfile.lock

RUN bundle install
COPY . /sample
```

```ruby:docker-compose.yml
version: '3'

services:
    db:
        image: mysql:5.7
        environment:
            MYSQL_USER: root
            MYSQL_ROOT_PASSWORD: password
        ports:
            - "3306:3306"
        volumes:
            - ./db/mysql/volumes:/var/lib/mysql

    web:
        build: .
        command: bash -c "rm -f tmp/pids/server.pid && bundle exec rails s -p 3000 -b '0.0.0.0'"
        volumes:
            - .:/sample
            - gem_data:/usr/local/bundle
        ports:
            - 3000:3000
        depends_on:
            - db 
        tty: true
        stdin_open: true

volumes:
  gem_data:
```

#手順3
Dockerコマンドを実行し、railsアプリケーションを作成
※Dockerを起動していない場合は次のコマンドを実行：
docker run -d -p 80:80 docker/getting-started


・rails new コマンド（DBにmysqlを指定）
docker-compose run web rails new . --force --database=mysql --skip-bundle
【AWS認定 Alexa スキルビルダー - 専門知識】に一週間で合格した話

## はじめに
2021/01/23にAlexaスキルビルダーに合格しました。

勉強しようと思い立ってAlexa資格の学習を始めたのが2021/01/16(※1)なので、ちょうど一週間で資格を取得できたと言うことになります。

こちらの資格が2021/03/23で廃止となるので、私と同様に急いで取得しておきたいと言う人もいると思うので、少しでもこの記事を参考にしていただければ幸いです。

(※1 この日はセキュリティ専門知識に落ちてしまい、逆に学習意欲に満ち溢れていました。）

## 経歴とAWS資格歴
エンジニア歴1年、業務でのAWS歴は0年です。
ソフトバンク株式会社でソフトウェアエンジニアとして働いています。

| AWS資格名 | 取得日 |
|:-:|:-:|
| クラウドプラクティショナー | 2020.6.25 |
| ソリューションアーキテクト - アソシエイト | 2020.7.25 |
| SysOpsアドミニストレーター - アソシエイト | 2020.7.26 |
| デベロッパー - アソシエイト | 2020.8.9 |
| ソリューションアーキテクト - プロフェッショナル | 2020.11.27 |
| Alexa スキルビルダー - 専門知識 | 2021.1.23 |

## 試験に向けて学習したこと
※ AWSの基本的なサービスは理解しているという前提です。
※ 試験の結果については一切責任を取りません。

1. [Alexa道場 - Amazon Developer](https://developer.amazon.com/ja-JP/alexa/alexa-skills-kit/get-deeper/webinars)
全くAlexaが知らない状態から、こちらの動画を参考に自分で手を動かして道場を進めていくことで、Alexaの基本的な部分を知ることができます。

2. [Exam Readiness: AWS Certified Alexa Skill Builder - Specialty (Japanese)](https://www.aws.training/Details/eLearning?id=45890)
Alexa試験の出題傾向などを網羅的に確認することができる無料のデジタルEラーニングとなっています。3時間ほどの内容なので、受験日が近づいてきたら必ず受講していただきたい内容となっています。
因みに、[Alexa for Developers](https://www.aws.training/Details/eLearning?id=34322)というAlexa自体の学習用のEラーニングも準備はされていますが、日本語で公開されていません。私自身はこちらは受講せずに資格に合格しています。

3. [模擬試験](https://www.aws.training/certification?src=exam-prep)
最後の学習内容としてはやはり模擬試験ではないでしょうか。メモを取りながら試験を受けて、解けなかった問題や理解が十分ではないと思われた部分に関しては、十分に理解できるところまでQiitaやその他資料等を活用して調べていくことをおすすめします。

## 最後に
AWS12冠を目指している方にとっては、今回のAlexa資格廃止は唐突なことだったと思います。

学習次第では一週間で資格を取得することも可能ですので、諦めないでAWS12冠取得を目指して頂ければと思います。

私も次回はセキュリティ - 専門知識、7つ目のAWS資格に挑戦します。
Git初心者のメモ その6：リモートからブランチを持ってくる

* 前の記事：[Git初心者のメモ その5：共有リポジトリ](https://qiita.com/y_ito/items/d1ed245b99729ad929c2)

<br>
--

まず `git fetch` でリモート追跡ブランチを作る。

`git fetch ＜リモート名＞ ＜ブランチ名＞`

そして `git checkout -t` でブランチを作ってその作ったブランチに切り替える。

`git checkout -t ＜リモート追跡ブランチ＞`

もし別な名前でブランチを作りたい場合（developブランチからfeatureブランチを作るなど）は `-b` オプションを付けてチェックアウトする。

`git checkout -b ＜新しいブランチ名＞ ＜リモート追跡ブランチ＞`


例：`git lg` は `git log --graph …` のエイリアス。

```shell-session
y_ito@note MINGW64 /c/work/local_dev (master)
$ git branch

y_ito@note MINGW64 /c/work/local_dev (master)
$ git fetch origin develop
remote: Enumerating objects: 6, done.
remote: Counting objects: 100% (6/6), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From file:///c/work/pub_rep/uchinaaguchi
 * branch            develop    -> FETCH_HEAD
 * [new branch]      develop    -> origin/develop

y_ito@note MINGW64 /c/work/local_dev (master)
$ git branch

y_ito@note MINGW64 /c/work/local_dev (master)
$ git branch -r
  origin/develop

y_ito@note MINGW64 /c/work/local_dev (master)
$ git checkout -t origin/develop
Switched to a new branch 'develop'
Branch 'develop' set up to track remote branch 'develop' from 'origin'.

y_ito@note MINGW64 /c/work/local_dev (develop)
$ git branch
* develop

y_ito@note MINGW64 /c/work/local_dev (develop)
$ git branch -r
  origin/develop

y_ito@note MINGW64 /c/work/local_dev (develop)
$ git lg
* f6c90fa  (HEAD -> develop, origin/develop) 2021-02-09 y_ito add develop
* 7194866  2021-02-09 y_ito first commit

y_ito@note MINGW64 /c/work/local_dev (develop)
$ git checkout -b feature origin/develop
Switched to a new branch 'feature'
Branch 'feature' set up to track remote branch 'develop' from 'origin'.

y_ito@note MINGW64 /c/work/local_dev (feature)
$ git branch
  develop
* feature

y_ito@note MINGW64 /c/work/local_dev (feature)
$ git branch -r
  origin/develop

y_ito@note MINGW64 /c/work/local_dev (feature)
$ git lg
* f6c90fa  (HEAD -> feature, origin/develop, develop) 2021-02-09 y_ito add develop
* 7194866  2021-02-09 y_ito first commit

```
【Ruby】文字列の中に式や変数を埋め込みたい

# 文字列の中に式を埋め込みたい時
変数の値などを含む文字列を表示したい時、
Rubyでは文字列中に`#{}`で囲んだ式を埋め込むとスクリプト実行時にその式の評価した結果に置き換えられます。

```ruby
sample = "sample_str"

message = "#{sample}さん、おはよう！" # => "sample_strさん、、おはよう！"
```

また数値(int)を代入した場合は計算結果に置き換えられます。

```ruby
int1 = 5
int2 = 2

message = "5+2 = #{int1 + int2} です！" # => "5+2 = 7 です！"
```

# まとめ
Rubyの「式展開」についてまとめました。
簡単ですけどよく使います。

Ruby 2.7.0 リファレンスマニュアル
https://docs.ruby-lang.org/ja/2.7.0/doc/spec=2fliteral.html#exp
label_map.pbtxt をつくる

Tensorflow Object Detection API に必要なlabel_map。
手作業で書き換えるのは面倒ということで、ラベルの配列から作れるコードがこちら。


```python

label_map_path = "./test.pbtxt" #保存パス
categories = ["dog","cat","bird"] #ラベルの配列

end = '\n'
s = ' '
class_map = {}
for ID, name in enumerate(categories):
    out = ''
    out += 'item' + s + '{' + end
    out += s*2 + 'id:' + ' ' + (str(ID+1)) + end
    out += s*2 + 'name:' + ' ' + '\'' + name + '\'' + end
    out += '}' + end*2
    

    with open(label_map_path, 'a') as f:
        f.write(out)
        
    class_map[name] = ID+1
```

これで出力保存されます。

```:label_map.pbtxt

item {
  id: 1
  name: 'dog'
}

item {
  id: 2
  name: 'cat'
}

item {
  id: 3
  name: 'bird'
}
```

このlabel_map.pbtxtで物体検出のラベルIDとラベル名を対応づけられます。

**[ObjectDetectionAPIの使い方はこちら](https://qiita.com/john-rocky/items/eb962f9aea438dc4eb75)**

🐣
****
フリーランスエンジニアです。
お仕事のご相談こちらまで
rockyshikoku@gmail.com

Core MLを使ったアプリを作っています。
機械学習関連の情報を発信しています。

[Twitter](https://twitter.com/JackdeS11)
[Medium](https://medium.com/@rockyshikoku)
Railsでの検索機能実装方法(whereメソッド)

#目次
<b>①結論
<b>②ActiveRecordとは
<b>③whereメソッドとは
<b>④whereメソッドの使い方

##①結論
ルーティングを設定し、検索窓のビューを実装し、コントローラーにてActiveRecordのwhereメソッドを使用する

```php:ルーティング
resources :users do
  get :search, on: :collection
end
```


```php:コントローラ

def  search
 if params[:name] != ""
  @users =  User.where("name LIKE(?)","%#{params[:name]}%") 
else
  @users = User.all
end
```

```php:検索機能のビュー
<h1>検索機能の実装</h1>
<%= form_with(url: search_users_path, method: :get, local: true)do |form| %>
  <%= form.text_field :name %>
  <%= form.submit :search %>
<% end %>


  <div calss= "contents">
    <% @users.each do |user| %>
       <p><%= user.name %></p>
    <% end %>
  </div>

```

##②ActiveRecordとは
Rubyのライブラリのひとつで、Rubyのオブジェクト(Object)をSQLに翻訳してリレーショナルデータベース（RDBMS）を操作できる(Mapping)ツールのこと。Railsとデータベース橋渡しの役割をしている。この機能をそれぞれの頭文字をとって、ORMapperと呼ぶ。Railsには、ActiveRecordがデフォルトで組み込まれている。

##③whereメソッドとは
テーブル内の条件に一致したレコードを配列の形で取得できるメソッドのこと

##④whereメソッドの使い方
以下3つのパターンを紹介する
◯完全一致の場合

```
User.where(id:5)
#idの5が欲しいとき

User.where(name:"キャリア君")
#キャリア君を探したいとき
```


◯範囲検索(5~10のidのユーザーを取得したいとき)

```
User.where(id: 5..10)
```

◯部分一致(文字列)

```
User.where("name LIKE(?)","%キャリア%")
```
LIKE句は曖昧な文字列の検索をする時に使用するものでwhereメソッドと一緒に使用する。
name LIKEと書くことでnameカラムを検索、という意味になる。?は次の引数"%hana%"を受け取る場所になる。
?のことろに%◯◯%がそのまま入るイメージ。この場合だと、name LIKE "%キャリア君%"という風になる。%は任意の文字列を指します。まとめると、nameカラムにhanaを含むレコードを抽出する、という処理になる。
ActiveModel::Serializer ( Gem ) のインストール方法

**ActiveModel::Serializer ( Gem )** のインストールの仕方を簡単に書いておきます！
## ActiveModel::Serializer ( Gem ) のインストール その①
`Gemfile` に以下のコードを記述する。

```ruby:Gemfile
gem 'active_model_serializers'
```

その後、ターミナル上で bundle install を実行。

```ruby:terminal
bundle install
```

## ActiveModel::Serializer ( Gem ) のインストール その②

ターミナル上で以下のコマンドを実行し、
Gemfile に `gem 'active_model_serializers'` を追記。

```ruby:terminal
echo "gem 'devise_token_auth'" >> Gemfile
```


その後、ターミナル上で bundle install。

```ruby:terminal
bundle install
```

# まとめ
どちらの方法でもインストール可能です。

本日、Qiita に初投稿してみました！とても簡単な内容かもしれませんが、自分が検索したときにパッと出てこなかったのと、Markdown の書き方の勉強を兼ねて投稿してみました！
プログラミング学習日記

2021/01/27　day２２
Ruby　on Rails Twitterクローン課題

今日からTwitterと並行してQiita活用していく！！

Rails入って、難しくて理解に苦しんでたけど
すこーーーしずつ理解できてる。気がする。笑
アリの歩くスピードレベルだけど、もっと頑張ろう


※今日学んだことを殴り書きで貼り付けてます。
意味わからないところばかりだと思うけど自分でわかるように書いているのでご容赦下さい。
あとまだ理解不足なところばかりなので、明らかに違う！というところは何かアドバイスください、

コントローラーの@word の部分は、
例@words = Word.all　だと.allで複数のレコードをDBから持ってくるから複数形で@words sをつける

@word = Word.new　　これだと .newで一つのインスタンスを生成するから　word　s　つけない
こういう形で区別していく

コントローラーのアクションは全く別物だから、同じ単語でもエラーにならない
それぞれのファイルに

例
def index
    @words = Word.all
  end

def index
    @words = Word.all
ここにrender:index　がある。これはindexファイルに飛ばすためのもの。だけどdef indexでもう指定してあるので書く必要なし。ただ、他のファイルに飛ばしたい場合は、
render:new など他のファイルにとぶ。この場合render:の方が優先される
new,showなども同様
  end

このツイッタークローンでいうここは、新規の画面をnewアクションとcreateアクションの２段階で登録

def new
    @word = Word.new
  end

  def create
    Word.create(word_params)
    redirect_to new_word_path
  end

twitterクローンでいうアクション詳細


![スクリーンショット 2021-01-27 23.01.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954637/002651a8-cd1c-68fd-bdfb-447e3412199c.png)

リソース＝処理の対象になる情報、特定の資源
Twitterクローンでいうと、Twitter全体の情報

例
def create
    （（# binding.pry））
    @word = Word.new(word_params)
    if @word.save
      redirect_to new_word_path
    else
      render :new
    end
省略

private
  def word_params
    params.require(:word).permit(:content)
  end

(word_params)　これは、privateで取得したやつを引数で(word_params)で取得している



❶if @word.save
      redirect_to new_word_path
 ❷   else
      render :new

❶もし、(word_params)で取得した値がsave（投稿）できたら、new.html.erbのページにリダイレクトする（投稿ボタンを押した後の画面、初めの投稿する前の↓の画面に戻る。）
![スクリーンショット 2021-01-27 22.42.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/954637/73efee6d-e61f-25b8-8fba-dbd2dea55a33.png)

❷そうじゃなかったら、

def new
    @word = Word.new
  end

newアクションが起きる→new.html.erbのページになって、エラー文がでる

paramsとデバックがまだよく理解できない、

学習開始してもう３週間すぎた。。
まだまだ学ぶことたくさんあるけど楽しんでやります
DrupalでAttempting to re-run cron while it is already runningというエラーが出た時の対処法

## やり方

コマンドラインでこれを打つだけ

```
drush sqlq "DELETE FROM semaphore WHERE name = 'cron';"
```

## 参考

https://www.drupal.org/forum/support/post-installation/2018-10-03/attempting-to-re-run-cron-while-it-is-already-running-in
Vimの正規表現で肯定先読みによるローワーキャメルケース変換（なんのこっちゃ）

## 何が起きたか

MyBatisを使っているのですが、Mapperファイルの編集時、いろいろあって以下のような感じに（実際は複数行）。

```xml
<!-- 現実 -->
<result poperty="foo_bar_baz" column="foo_bar_baz" />
```

ああ、`property`属性値はキャメルケースにしたいなあ。

```xml
<!-- 理想 -->
<result poperty="fooBarBaz" column="foo_bar_baz" />
```

もちろん自動で読み替えてくれる設定はあるのですが、あいにく使用実績がなくて使えない。
そして属性の順序もproperty -> columnがいい。

そしてVimでなんとかしたい。

## 何をしたか

```vim

:s/\v_(.)(column)@=/\u\1/g
```

* `\u`で大文字に変換。
* ポイントとして、マジックモード(`\v`)の場合、肯定先読みは`\@=`ではなくて`@=`になる。
【JavaScript学習記録】アルファベットの配列の作り方

　PHPでは、以下のように簡単にアルファベットの配列を作ることができます。

```
　$alphabets = range('a', 'z');
```
　JavaScriptでは、どのようにして作るのだろう。
　今日はそれを調べてみましたので、アウトプットします。

　※　下記を参考にさせて頂きました:relieved::tulip:
　http://2amcode.hatenablog.com/entry/2017/08/22/102156

```
　const start = "a" . charCodeAt(0);
　const alphabets = Array.apply(null, new Array(26)).map((v, i) => {
　　　 return String.fromCharCode(start + i);
　}, {})
```

　コードを一行ずつみていきます。
　
　まずは一行目の「charCodeAt(0)」。
　charCodeAt(n)は、Stringオブジェクトで利用可能なメンバーです。
　n + 1番目の文字をLatin-1コードに変換します。
　※　Latin-1・・・ラテンアルファベットの文字コード標準。

　二行目の「.apply()」、「.map()」。
　.apply()は、関数を呼び出すメソッドです。


```
　【構文】
　関数名.apply(関数の処理の対象となる要素, 関数で使う引数(配列のみ));
```
　
　.map()は、コールバック関数によって新しい配列を生成します。


```
　【構文】
　関数名.map([要素], [インデックス], [元配列]) => 変更後の要素
```

　三行目の「String」、「fromCharCode(start + i)」。
　Stringは、文字列型の値を扱うラッパーオブジェクトです。
　文字列の抽出や加工、検索等を行う為の機能を提供します。
　
　fromCharCode(c1, c2...)は、Stringオブジェクトで利用可能なメンバーの一つです。
　Latin-1コードc1,c2...を文字に変換します。
　
　startで定義したラテンコードをアルファベットにどんどん変換して返しているということでしょうか。
　
　PHPと比較すると大分難しく感じますが、少しずつ理解できるよう努めていきたいと思います。
　
　今回の記事の内容に不備等ございましたら、後学の為にご指摘頂けますと幸いです。

:pencil2:　追記
@vf8974様よりコメントで代替案をご提案いただきましたので、そちらをご紹介いたします。

```
【代替案１】
const alphabets = [...Array(26)].map((a, b) => (10 + b).toString(36));
```
とてもスッキリしたコードです:sparkles:
まだまだコードが長くなりがちですので、他の誰かを意識した可読性の高いコードが書けるようになりたいです。

```
【代替案２】
const alphabets = [...'abcdefghijklmnopqrstuvwxyz'];
```
一文字ずつカンマ区切りにせずとも、このようにまとめて書くことができるのですね:bulb:

とても勉強になりました。
@vf8974様、ありがとうございました:relieved:
Reactにおける基本的なライフサイクルメソッド

hooksの登場により、classコンポーネントにしかなかった機能が使えるようになり、あらゆる場面で関数コンポーネントを使えるようになりました。

とはいえ、いきなりclassコンポーネントに関する事項を飛ばしてhooksの内容を学習するのはお勧めできません。classコンポーネントの学習から始め、classコンポーネントにおけるライフサイクルメソッドなどの概念を理解してからのほうがhooksの学習に入った際にスムーズに理解できると思います。[^1]

そこで、ここではclassコンポーネントのライフサイクルメソッドについてまとめます。
（尚、ここではshouldComponentUpdateなどの使用されるケースが稀なものは除いています。）

[^1]: この理由の1つに、hooksのuseEffectがあります。useEffectは、classコンポーネントのライフサイクルメソッドに相当する機能であり、ライフサイクルメソッドを理解していればuseEffectも理解しやすいです。私はReactを学習するのにUdemyの講座「 Modern React with Redux [2020 Update] 」（ https://www.udemy.com/course/react-redux/ ）を利用しました。この講座でも、先述の理由から、classコンポーネントの解説がhooksの解説に先行しています。正しい順序で効率的にReactを学習するのにお勧めです。

# ライフサイクルについて

コンポーネントには、画面上に表示され、再レンダリング（更新）を何度か経て、やがて表示されなくなるまでの流れがあります。この一連の流れがライフサイクルと呼ばれるもので、この流れは3つの期間に大別できます。

## マウント時（Mounting）

コンポーネントが画面上に表示されるまでの期間にあたります。この期間では、constructor、render、componentDidMountの主に3つが呼ばれます。

### constructor

最初に呼ばれます。後述のrenderメソッドと同様、画面にコンポーネントが表示される前に呼び出されます。stateの初期化などはここで行います。ただし、ここでsetStateメソッドを呼び出してはいけません。尚、データの読み込みもここで行うことは可能ですが、後述のcomponentDidMountで行うことが推奨されています。

### render

renderメソッドは、唯一定義が必須となっています。このメソッドが呼ばれると、JSXの内容がDOMに追加され、コンポーネントが画面に表示されます。これが初回のレンダリングになります。

### componentDidMount

初回レンダリング後に1度限りで呼ばれます。データの読み込みなどはこちらで行います。

## 更新時（Updating）

stateが更新されたり、親から新たなpropsを受け取ったりした場合に、この期間で再レンダリングされ、更新されます。以下のrender→componentDidUpdateというこの期間の流れは、コンポーネントが表示されなくなるまでの間、更新が必要になる度に繰り返されます。

### render

マウント時に呼ばれたrenderメソッドですが、ここで再び呼ばれ、再レンダリングが行われます。

### componentDidUpdate

コンポーネントがアンマウントされる（コンポーネントがDOMから削除され、画面に表示されなくなる）までの間、コンポーネントの再レンダリングが起こった（renderメソッドが呼ばれた）度に呼ばれます。

## マウント解除時（Unmounting）

他のコンポーネントを表示するなどの理由により現在のコンポーネントが表示されなくなる（マウントが解除される）ことになったときがこの期間です。

### componentWillUnmount

マウント解除時に1度限りで呼ばれます。ここでネットワークリクエストのキャンセルなどを行います。



# その他のメソッド

以上の他にも、shouldComponentUpdate、getDerivedStateFromProps、getSnapshotBeforeUpdateといったものがあります。
しかし、これらは滅多に使われないものなので、初めは以上の5つのメソッドを理解できていれば良いと思います。
【docker】Node.jsのコンテナ立ち上げてサンプルアプリを動かしたい

# この記事の目標

dockerのコンテナ立ち上げて、このアプリ↓をローカル環境で立ち上げる

https://github.com/justadudewhohacks/face-api.js

# GitHubからリポジトリcloneする

ローカルの任意のディレクトリにcloneする

```bash
$ git clone https://github.com/justadudewhohacks/face-api.js
```

# docker hubからnode.jsのイメージpullしてくる

alpineが軽量でオススメらしいので、v14のをpullする

```bash
$ docker pull node:14-alpine
```

イメージをpullできたことの確認

```bash
$ docker images
```

# コンテナ立ち上げる

```bash
docker run -it -v $PWD:/workspace -p 8100:3000 --name node-face-api node:14-alpine /bin/ash
```

- ``-it``で、コンテナ内で入力可能な状態にする
- ``-v $PWD:/workspace``で、カレントディレクトリのファイルをコンテナ内の「workspace」ディレクトリにマウントするように指定
  - そのため、リポジトリをcloneしたディレクトリで作業する必要あり
  - ``$PWD``は``$(pwd)``といった指定方法もありらしい
- ``-p 8100:3000``で、ホスト側のポート``8100``とコンテナ側のポート``3000``を繋ぐ
  - このホスト側のポート番号は空いているものを適宜使う
  - コンテナ側はよしなに設定
  - ポート使用状況はMacの場合「ネットワークユーティリティ」で確認できる
- ``--name node-face-api``で、コンテナ名を「node-face-api」に設定
- ``node:14-alpine``で、イメージとバージョン（TAG？）の指定
- ``/bin/ash``で、コンテナ内で使うコマンドを指定

今回は使ってないが、以下のオプションもよく使われる

- ``--rm``で、コンテナから出た時にコンテナ削除

※ちなみに、コマンドの記述順は、以下の通りらしい

```bash
$ docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
```

起動時にエラーが起こって上手くコンテナに入れなかった場合、以下の手順でコンテナ削除し、
runコマンド見直してから再度試す

```bash
# コンテナ一覧表示
$ docker ps -a

# 起動（作成）に失敗したコンテナのIDを指定してコンテナ削除
$ docker rm [CONTAINER ID]
```

# コンテナ内でアプリケーションを立ち上げる

コンテナ作成して中に入ると、ホストのファイル群がworkspaceディレクトリ内にあるはずなので、確認する

```bash
$ cd workspace
$ ls
```

あとは、[face-ap.js](https://github.com/justadudewhohacks/face-api.js)のチュートリアル通りに進めていくだけ

```bash
$ cd examples/examples-browser
$ npm install
$ npm start
```

ホストマシンのポートは8100に指定したので、以下にアクセス

http://localhost:8100/

それっぽいページが表示されればOK！

# 参考
- [node - Docker Hub](https://hub.docker.com/_/node?tab=description&page=1&ordering=last_updated)
- [justadudewhohacks/face-api.js: JavaScript API for face detection and face recognition in the browser and nodejs with tensorflow.js](https://github.com/justadudewhohacks/face-api.js)
- [Volume相対パス指定でもdocker runがしたい！ - Qiita](https://qiita.com/KentoDodo/items/24117025924d64998110)
- [docker runでオプションの順番を間違えるとダメだよってメモ - by shigemk2](https://www.shigemk2.com/entry/docker_run_order)
「Locale.JAPAN」と「Locale.JAPANESE」の違い。

「Locale.JAPAN」と「Locale.JAPANESE」の違い。
locale.toString()したときに、「ja_JP」「ja」と返却値が違う。

「Locale.JAPAN = "ja_JP"」
「Locale.JAPANESE = "ja"」

IntraMartの「AccountContext.getLocale()」をやると「Locale.JAPANESE」が返却される。
IntraMartのバージョンは、2017 summer

デバッガで中身を見ると「Locale.JAPANESE」はLanguage（"ja"）だけ設定されてる。

[参考URL]
https://www.gwtcenter.com/acquiring-and-setting-locale